From d10fcdf15eeaaeda7b0e989823d90a49911dfdde Mon Sep 17 00:00:00 2001
From: Wizzard <rich@bandaholics.cash>
Date: Sun, 16 Mar 2025 13:38:31 -0400
Subject: [PATCH] Add: Show health

---
 src/comms.rs           | 13 ++++++---
 src/dma/context/mod.rs |  2 --
 src/dma/mod.rs         |  6 ++--
 webradar/index.html    |  5 +++-
 webradar/script.js     | 66 ++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 83 insertions(+), 9 deletions(-)

diff --git a/src/comms.rs b/src/comms.rs
index 4e89a7a..6f9c011 100755
--- a/src/comms.rs
+++ b/src/comms.rs
@@ -26,11 +26,14 @@ pub struct PlayerData {
 
     #[serde(rename = "money", default)]
     money: i32,
+
+    #[serde(rename = "health", default)]
+    health: u32,
 }
 
 impl PlayerData {
     pub fn new(pos: Vec3, yaw: f32, player_type: PlayerType, has_bomb: bool, has_awp: bool,
-               is_scoped: bool, player_name: String, weapon_id: i16) -> PlayerData {
+               is_scoped: bool, player_name: String, weapon_id: i16, health: u32) -> PlayerData {
         PlayerData {
             pos,
             yaw,
@@ -40,12 +43,13 @@ impl PlayerData {
             is_scoped,
             player_name,
             weapon_id,
-            money: 0
+            money: 0,
+            health
         }
     }
 
     pub fn new_with_money(pos: Vec3, yaw: f32, player_type: PlayerType, has_bomb: bool, has_awp: bool,
-                    is_scoped: bool, player_name: String, weapon_id: i16, money: i32) -> PlayerData {
+                    is_scoped: bool, player_name: String, weapon_id: i16, money: i32, health: u32) -> PlayerData {
         PlayerData {
             pos,
             yaw,
@@ -55,7 +59,8 @@ impl PlayerData {
             is_scoped,
             player_name,
             weapon_id,
-            money
+            money,
+            health
         }
     }
 
diff --git a/src/dma/context/mod.rs b/src/dma/context/mod.rs
index 43498a3..454eb84 100755
--- a/src/dma/context/mod.rs
+++ b/src/dma/context/mod.rs
@@ -117,8 +117,6 @@ impl DmaCtx {
         if money_services_ptr != 0 {
             let money_addr: Address = money_services_ptr.into();
             money = self.process.read(money_addr + cs2dumper::client::CCSPlayerController_InGameMoneyServices::m_iAccount)?;
-
-            log::debug!("Read money value: {} for player", money);
         }
 
         let player_name = if player_name_ptr != 0 {
diff --git a/src/dma/mod.rs b/src/dma/mod.rs
index 0a97471..59f4b6c 100755
--- a/src/dma/mod.rs
+++ b/src/dma/mod.rs
@@ -205,7 +205,8 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
                             local_data.is_scoped,
                             local_data.player_name,
                             local_data.weapon_id,
-                            local_data.money
+                            local_data.money,
+                            local_data.health
                         )
                     )
                 );
@@ -246,7 +247,8 @@ pub async fn run(radar_data: ArcRwlockRadarData, connector: Connector, pcileech_
                                     player_data.is_scoped,
                                     player_data.player_name,
                                     player_data.weapon_id,
-                                    player_data.money
+                                    player_data.money,
+                                    player_data.health
                                 )
                             )
                         );
diff --git a/webradar/index.html b/webradar/index.html
index 58ccb87..0978c50 100644
--- a/webradar/index.html
+++ b/webradar/index.html
@@ -39,6 +39,10 @@
                         checked />
                     <label for="moneyDisplay">Display Money</label>
                 </div>
+                <div>
+                    <input type="checkbox" onclick="toggleHealth()" id="healthCheck" name="health" checked />
+                    <label for="healthCheck">Display Health</label>
+                </div>
                 <div>
                     <input type="checkbox" onclick="toggleRotate()" id="rotateCheck" name="rotate" checked />
                     <label for="rotateCheck">Rotate Map</label>
@@ -47,7 +51,6 @@
                     <input type="checkbox" onclick="toggleCentered()" id="centerCheck" name="center" checked />
                     <label for="centerCheck">Player Centered</label>
                 </div>
-
                 <div class="player-focus">
                     <label for="playerSelect">Focus Player:</label>
                     <select id="playerSelect" onchange="changePlayerFocus()">
diff --git a/webradar/script.js b/webradar/script.js
index bb77603..cee8670 100644
--- a/webradar/script.js
+++ b/webradar/script.js
@@ -10,6 +10,8 @@ let shouldZoom = false;
 let rotateMap = true;
 let playerCentered = true;
 
+let drawHealth = true;
+
 let drawStats = true;
 let drawNames = true;
 let drawGuns = true;
@@ -259,6 +261,56 @@ function drawImage() {
     ctx.restore();
 }
 
+function toggleHealth() {
+    drawHealth = !drawHealth;
+    update = true;
+    localStorage.setItem('drawHealth', drawHealth ? 'true' : 'false');
+}
+
+function drawPlayerHealth(pos, playerType, health, hasBomb) {
+    if (!map) return;
+
+    const transformed = mapAndTransformCoordinates(pos);
+    const mapPos = transformed.pos;
+    const textSize = transformed.textSize * 0.8;
+
+    let extraOffset = 0;
+    if (drawNames) extraOffset += 15;
+    if (drawGuns) extraOffset += 15;
+    if (hasBomb) extraOffset += 15;
+    if (drawMoney) extraOffset += 15;
+
+    let textY = mapPos.y + 20 + extraOffset;
+
+    let healthColor;
+    if (health > 70) {
+        healthColor = "#32CD32";
+    } else if (health > 30) {
+        healthColor = "#FFFF00";
+    } else {
+        healthColor = "#FF0000";
+    }
+
+    const barWidth = 40;
+    const barHeight = 5;
+    ctx.fillStyle = "#444444";
+    ctx.fillRect(mapPos.x - barWidth / 2, textY, barWidth, barHeight);
+
+    ctx.fillStyle = healthColor;
+    const healthWidth = (health / 100) * barWidth;
+    ctx.fillRect(mapPos.x - barWidth / 2, textY, healthWidth, barHeight);
+
+    ctx.font = `${textSize}px Arial`;
+    ctx.textAlign = "center";
+    ctx.textBaseline = "top";
+
+    ctx.lineWidth = 2;
+    ctx.strokeStyle = "black";
+    ctx.strokeText(`${health}HP`, mapPos.x, textY + barHeight + 1);
+    ctx.fillStyle = healthColor;
+    ctx.fillText(`${health}HP`, mapPos.x, textY + barHeight + 1);
+}
+
 function drawEntities() {
     if (!entityData) return;
 
@@ -323,6 +375,15 @@ function drawEntities() {
                         player.hasBomb
                     );
                 }
+
+                if (drawHealth && typeof player.health === 'number') {
+                    drawPlayerHealth(
+                        player.pos,
+                        player.playerType,
+                        player.health,
+                        player.hasBomb
+                    );
+                }
             }
         }
     });
@@ -960,22 +1021,27 @@ function togglePerformanceMode() {
         drawNames = false;
         drawGuns = false;
         drawMoney = false;
+        drawHealth = false;
 
         document.getElementById("namesCheck").checked = false;
         document.getElementById("gunsCheck").checked = false;
         document.getElementById("moneyDisplay").checked = false;
+        document.getElementById("healthCheck").checked = false;
 
         console.log("[radarflow] Performance mode enabled");
     } else {
         drawNames = document.getElementById("namesCheck").checked = true;
         drawGuns = document.getElementById("gunsCheck").checked = true;
         drawMoney = document.getElementById("moneyDisplay").checked = true;
+        drawHealth = document.getElementById("healthCheck").checked = true;
 
         console.log("[radarflow] Performance mode disabled");
     }
 }
 
 addEventListener("DOMContentLoaded", () => {
+    const savedDrawHealth = localStorage.getItem('drawHealth');
+    drawHealth = savedDrawHealth !== null ? savedDrawHealth === 'true' : true;
     const savedDrawMoney = localStorage.getItem('drawMoney');
     drawMoney = savedDrawMoney !== null ? savedDrawMoney === 'true' : true;