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) {}
-
}
}