From d1a4841dc2f67d00fe386f85081dcb4219150a70 Mon Sep 17 00:00:00 2001 From: TNTaddicted <131607911+TNTaddicted@users.noreply.github.com> Date: Thu, 12 Feb 2026 20:23:31 +0100 Subject: [PATCH 1/3] Add distance-based tracer color functionality --- src/Cheats/TracersHandler.cs | 50 ++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/Cheats/TracersHandler.cs b/src/Cheats/TracersHandler.cs index 50cc5ce1..2a9ac576 100644 --- a/src/Cheats/TracersHandler.cs +++ b/src/Cheats/TracersHandler.cs @@ -10,13 +10,17 @@ public static void drawPlayerTracer(PlayerPhysics playerPhysics){ if (!playerPhysics.myPlayer.Data.IsDead){ if (CheatToggles.tracersCrew && !playerPhysics.myPlayer.Data.Role.IsImpostor){ - if (CheatToggles.colorBasedTracers){ + if (CheatToggles.distanceBasedTracers){ + color = GetDistanceBasedColor(playerPhysics.myPlayer.transform.position); + }else if (CheatToggles.colorBasedTracers){ color = playerPhysics.myPlayer.Data.Color; // Color-Based Tracer }else{ color = playerPhysics.myPlayer.Data.Role.TeamColor; // Team-Based Tracer } }else if (CheatToggles.tracersImps && playerPhysics.myPlayer.Data.Role.IsImpostor){ - if (CheatToggles.colorBasedTracers){ + if (CheatToggles.distanceBasedTracers){ + color = GetDistanceBasedColor(playerPhysics.myPlayer.transform.position); + }else if (CheatToggles.colorBasedTracers){ color = playerPhysics.myPlayer.Data.Color; // Color-Based Tracer }else{ color = playerPhysics.myPlayer.Data.Role.TeamColor; // Team-Based Tracer @@ -24,7 +28,9 @@ public static void drawPlayerTracer(PlayerPhysics playerPhysics){ } }else{ if (CheatToggles.tracersGhosts){ - if (CheatToggles.colorBasedTracers){ + if (CheatToggles.distanceBasedTracers){ + color = GetDistanceBasedColor(playerPhysics.myPlayer.transform.position); + }else if (CheatToggles.colorBasedTracers){ color = playerPhysics.myPlayer.Data.Color; // Color-Based Tracer }else{ color = Palette.White; // Ghost Tracer (White) @@ -42,7 +48,9 @@ public static void drawBodyTracer(DeadBody deadBody){ Color color = Color.clear; // All tracers are invisible by default if (CheatToggles.tracersBodies){ - if (CheatToggles.colorBasedTracers){ + if (CheatToggles.distanceBasedTracers){ + color = GetDistanceBasedColor(deadBody.transform.position); + }else if (CheatToggles.colorBasedTracers){ // Fetch the dead body's PlayerInfo NetworkedPlayerInfo playerById = GameData.Instance.GetPlayerById(deadBody.ParentId); @@ -59,4 +67,36 @@ public static void drawBodyTracer(DeadBody deadBody){ // Draw tracer between the dead body and LocalPlayer using the right color Utils.drawTracer(deadBody.gameObject, PlayerControl.LocalPlayer.gameObject, color); } -} \ No newline at end of file + + // Red-Yellow-Green cycle: Red = close, Yellow = medium, Green = far + private static Color GetDistanceBasedColor(Vector3 targetPosition) + { + float distance = Vector3.Distance(targetPosition, PlayerControl.LocalPlayer.transform.position); + + float maxDistance = 20f; // Green at 20+ units + float minDistance = 2f; // Red at 2 units or less + + distance = Mathf.Clamp(distance, minDistance, maxDistance); + + float normalized = (distance - minDistance) / (maxDistance - minDistance); + + float r; + float g; + float b = 0f; + + if (normalized < 0.5f) + { + float t = normalized * 2f; + r = 1f; + g = t; + } + else + { + float t = (normalized - 0.5f) * 2f; + r = 1f - t; + g = 1f; + } + + return new Color(r, g, b, 1f); + } +} From 9381e2ebb5d72e0b1fffcf81f22b6ed6b4fe643a Mon Sep 17 00:00:00 2001 From: TNTaddicted <131607911+TNTaddicted@users.noreply.github.com> Date: Thu, 12 Feb 2026 20:23:51 +0100 Subject: [PATCH 2/3] Add Distance-based toggle to MenuUI --- src/UI/MenuUI.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/UI/MenuUI.cs b/src/UI/MenuUI.cs index 1ed42cf6..fd6be812 100644 --- a/src/UI/MenuUI.cs +++ b/src/UI/MenuUI.cs @@ -58,7 +58,8 @@ private void Start() new ToggleInfo(" Impostors", () => CheatToggles.tracersImps, x => CheatToggles.tracersImps = x), new ToggleInfo(" Ghosts", () => CheatToggles.tracersGhosts, x => CheatToggles.tracersGhosts = x), new ToggleInfo(" Dead Bodies", () => CheatToggles.tracersBodies, x => CheatToggles.tracersBodies = x), - new ToggleInfo(" Color-based", () => CheatToggles.colorBasedTracers, x => CheatToggles.colorBasedTracers = x) + new ToggleInfo(" Color-based", () => CheatToggles.colorBasedTracers, x => CheatToggles.colorBasedTracers = x), + new ToggleInfo(" Distance-based", () => CheatToggles.distanceBasedTracers, x => CheatToggles.distanceBasedTracers = x) ]), new SubmenuInfo("Minimap", false, [ From 25ee08e0863265aaccfd9da2b2ef1eeab4a4aa3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Astral=E2=9C=A8?= <90265231+astra1dev@users.noreply.github.com> Date: Thu, 12 Feb 2026 22:45:27 +0100 Subject: [PATCH 3/3] refactor: add documentation and improve color interpolation --- src/Cheats/TracersHandler.cs | 131 +++++++++++++++------------- src/Patches/PlayerPhysicsPatches.cs | 11 +-- 2 files changed, 71 insertions(+), 71 deletions(-) diff --git a/src/Cheats/TracersHandler.cs b/src/Cheats/TracersHandler.cs index 2a9ac576..246952a2 100644 --- a/src/Cheats/TracersHandler.cs +++ b/src/Cheats/TracersHandler.cs @@ -1,38 +1,52 @@ using UnityEngine; namespace MalumMenu; + public static class TracersHandler { - public static void drawPlayerTracer(PlayerPhysics playerPhysics){ - try{ - - Color color = Color.clear; // All tracers are invisible by default - - if (!playerPhysics.myPlayer.Data.IsDead){ - if (CheatToggles.tracersCrew && !playerPhysics.myPlayer.Data.Role.IsImpostor){ - if (CheatToggles.distanceBasedTracers){ + /// + /// Draws a tracer from the local player to another player. + /// + /// The PlayerPhysics of the target player. + public static void DrawPlayerTracer(PlayerPhysics playerPhysics) + { + try + { + var color = Color.clear; // All tracers are invisible by default + + if (!playerPhysics.myPlayer.Data.IsDead) + { + if (CheatToggles.tracersCrew && !playerPhysics.myPlayer.Data.Role.IsImpostor || + CheatToggles.tracersImps && playerPhysics.myPlayer.Data.Role.IsImpostor) + { + if (CheatToggles.distanceBasedTracers) + { color = GetDistanceBasedColor(playerPhysics.myPlayer.transform.position); - }else if (CheatToggles.colorBasedTracers){ - color = playerPhysics.myPlayer.Data.Color; // Color-Based Tracer - }else{ - color = playerPhysics.myPlayer.Data.Role.TeamColor; // Team-Based Tracer } - }else if (CheatToggles.tracersImps && playerPhysics.myPlayer.Data.Role.IsImpostor){ - if (CheatToggles.distanceBasedTracers){ - color = GetDistanceBasedColor(playerPhysics.myPlayer.transform.position); - }else if (CheatToggles.colorBasedTracers){ + else if (CheatToggles.colorBasedTracers) + { color = playerPhysics.myPlayer.Data.Color; // Color-Based Tracer - }else{ + } + else + { color = playerPhysics.myPlayer.Data.Role.TeamColor; // Team-Based Tracer } } - }else{ - if (CheatToggles.tracersGhosts){ - if (CheatToggles.distanceBasedTracers){ + } + else + { + if (CheatToggles.tracersGhosts) + { + if (CheatToggles.distanceBasedTracers) + { color = GetDistanceBasedColor(playerPhysics.myPlayer.transform.position); - }else if (CheatToggles.colorBasedTracers){ + } + else if (CheatToggles.colorBasedTracers) + { color = playerPhysics.myPlayer.Data.Color; // Color-Based Tracer - }else{ + } + else + { color = Palette.White; // Ghost Tracer (White) } } @@ -40,27 +54,30 @@ public static void drawPlayerTracer(PlayerPhysics playerPhysics){ // Draw tracer between the player and LocalPlayer using the right color Utils.drawTracer(playerPhysics.myPlayer.gameObject, PlayerControl.LocalPlayer.gameObject, color); - }catch{} } - public static void drawBodyTracer(DeadBody deadBody){ - Color color = Color.clear; // All tracers are invisible by default + /// + /// Draws a tracer from the local player to a dead body. Only draws tracers for unreported dead bodies. + /// + /// The DeadBody to draw a tracer to. + public static void DrawBodyTracer(DeadBody deadBody) + { + var color = Color.clear; // All tracers are invisible by default - if (CheatToggles.tracersBodies){ - if (CheatToggles.distanceBasedTracers){ + if (CheatToggles.tracersBodies) + { + if (CheatToggles.distanceBasedTracers) + { color = GetDistanceBasedColor(deadBody.transform.position); - }else if (CheatToggles.colorBasedTracers){ - - // Fetch the dead body's PlayerInfo - NetworkedPlayerInfo playerById = GameData.Instance.GetPlayerById(deadBody.ParentId); - - color = playerById.Color; // Color-Based Tracer - - }else{ - + } + else if (CheatToggles.colorBasedTracers) + { + color = GameData.Instance.GetPlayerById(deadBody.ParentId).Color; // Color-Based Tracer + } + else + { color = Color.yellow; // Dead Body Tracer (Yellow) - } } @@ -68,35 +85,23 @@ public static void drawBodyTracer(DeadBody deadBody){ Utils.drawTracer(deadBody.gameObject, PlayerControl.LocalPlayer.gameObject, color); } - // Red-Yellow-Green cycle: Red = close, Yellow = medium, Green = far + /// + /// Gets a color based on the distance between the local player and a target position. + /// Closer distances are red, medium distances are yellow, and farther distances are green. + /// + /// The position to calculate the distance from. + /// A Color that represents the distance (red for close, yellow for medium, green for far). private static Color GetDistanceBasedColor(Vector3 targetPosition) { - float distance = Vector3.Distance(targetPosition, PlayerControl.LocalPlayer.transform.position); - - float maxDistance = 20f; // Green at 20+ units - float minDistance = 2f; // Red at 2 units or less + const float maxDistance = 20f; // Green at 20+ units + const float minDistance = 2f; // Red at 2 units or fewer - distance = Mathf.Clamp(distance, minDistance, maxDistance); - - float normalized = (distance - minDistance) / (maxDistance - minDistance); - - float r; - float g; - float b = 0f; - - if (normalized < 0.5f) - { - float t = normalized * 2f; - r = 1f; - g = t; - } - else - { - float t = (normalized - 0.5f) * 2f; - r = 1f - t; - g = 1f; - } + var distance = Vector3.Distance(targetPosition, PlayerControl.LocalPlayer.transform.position); + var normalized = Mathf.InverseLerp(minDistance, maxDistance, distance); - return new Color(r, g, b, 1f); + // Interpolate: Red (close) -> Yellow (medium) -> Green (far) + return normalized < 0.5f + ? Color.Lerp(Color.red, Color.yellow, normalized * 2f) + : Color.Lerp(Color.yellow, Color.green, (normalized - 0.5f) * 2f); } } diff --git a/src/Patches/PlayerPhysicsPatches.cs b/src/Patches/PlayerPhysicsPatches.cs index c5e81e73..6fb8931d 100644 --- a/src/Patches/PlayerPhysicsPatches.cs +++ b/src/Patches/PlayerPhysicsPatches.cs @@ -9,7 +9,6 @@ public static class PlayerPhysics_LateUpdate { public static void Postfix(PlayerPhysics __instance) { - MalumESP.PlayerNametags(__instance); MalumESP.seeGhostsCheat(__instance); @@ -33,18 +32,15 @@ public static void Postfix(PlayerPhysics __instance) MalumPPMCheats.changeRolePPM(); MalumPPMCheats.forceRolePPM(); - TracersHandler.drawPlayerTracer(__instance); + TracersHandler.DrawPlayerTracer(__instance); GameObject[] bodyObjects = GameObject.FindGameObjectsWithTag("DeadBody"); foreach(GameObject bodyObject in bodyObjects) // Finds and loops through all dead bodies { DeadBody deadBody = bodyObject.GetComponent(); - if (deadBody){ - if (!deadBody.Reported){ // Only draw tracers for unreported dead bodies - TracersHandler.drawBodyTracer(deadBody); - } - } + if (!deadBody || deadBody.Reported) continue; // Only draw tracers for unreported dead bodies + TracersHandler.DrawBodyTracer(deadBody); } try @@ -60,7 +56,6 @@ public static void Postfix(PlayerPhysics __instance) PlayerControl.LocalPlayer.MyPhysics.GhostSpeed = Mathf.Abs(PlayerControl.LocalPlayer.MyPhysics.GhostSpeed); } }catch (NullReferenceException) {} - } }