diff --git a/src/ST-Events/TriggerStartTouch.cs b/src/ST-Events/TriggerStartTouch.cs index 1403c00..680b519 100644 --- a/src/ST-Events/TriggerStartTouch.cs +++ b/src/ST-Events/TriggerStartTouch.cs @@ -55,13 +55,13 @@ internal HookResult OnTriggerStartTouch(DynamicHook handler) player.Stats.ThisRun.EndVelZ = velocity_z; // End pre speed for the run // To-do: make Style (currently 0) be dynamic - if (player.Stats.PB[0].RunTime <= 0) // Player first ever PersonalBest for the map + if (player.Stats.PB[0].Ticks <= 0) // Player first ever PersonalBest for the map { Server.PrintToChatAll($"{PluginPrefix} {player.Controller.PlayerName} finished the map in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} ({player.Timer.Ticks})!"); } - else if (player.Timer.Ticks < player.Stats.PB[0].RunTime) // Player beating their existing PersonalBest for the map + else if (player.Timer.Ticks < player.Stats.PB[0].Ticks) // Player beating their existing PersonalBest for the map { - Server.PrintToChatAll($"{PluginPrefix} {ChatColors.Lime}{player.Profile.Name}{ChatColors.Default} beat their PB in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} (Old: {ChatColors.BlueGrey}{player.HUD.FormatTime(player.Stats.PB[0].RunTime)}{ChatColors.Default})!"); + Server.PrintToChatAll($"{PluginPrefix} {ChatColors.Lime}{player.Profile.Name}{ChatColors.Default} beat their PB in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} (Old: {ChatColors.BlueGrey}{player.HUD.FormatTime(player.Stats.PB[0].Ticks)}{ChatColors.Default})!"); } else // Player did not beat their existing PersonalBest for the map { @@ -73,13 +73,13 @@ internal HookResult OnTriggerStartTouch(DynamicHook handler) throw new Exception("CS2 Surf ERROR >> OnTriggerStartTouch (Map end zone) -> DB object is null, this shouldn't happen."); - player.Stats.PB[0].RunTime = player.Timer.Ticks; // Reload the run_time for the HUD and also assign for the DB query + player.Stats.PB[0].Ticks = player.Timer.Ticks; // Reload the run_time for the HUD and also assign for the DB query #if DEBUG Console.WriteLine($"CS2 Surf DEBUG >> OnTriggerStartTouch (Map end zone) -> " + $"============== INSERT INTO `MapTimes` " + $"(`player_id`, `map_id`, `style`, `type`, `stage`, `run_time`, `start_vel_x`, `start_vel_y`, `start_vel_z`, `end_vel_x`, `end_vel_y`, `end_vel_z`, `run_date`) " + - $"VALUES ({player.Profile.ID}, {CurrentMap.ID}, 0, 0, 0, {player.Stats.PB[0].RunTime}, " + + $"VALUES ({player.Profile.ID}, {CurrentMap.ID}, 0, 0, 0, {player.Stats.PB[0].Ticks}, " + $"{player.Stats.ThisRun.StartVelX}, {player.Stats.ThisRun.StartVelY}, {player.Stats.ThisRun.StartVelZ}, {velocity_x}, {velocity_y}, {velocity_z}, {(int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()}) " + // To-do: get the `start_vel` values for the run from CP implementation $"ON DUPLICATE KEY UPDATE run_time=VALUES(run_time), start_vel_x=VALUES(start_vel_x), start_vel_y=VALUES(start_vel_y), " + $"start_vel_z=VALUES(start_vel_z), end_vel_x=VALUES(end_vel_x), end_vel_y=VALUES(end_vel_y), end_vel_z=VALUES(end_vel_z), run_date=VALUES(run_date);"); @@ -139,16 +139,16 @@ internal HookResult OnTriggerStartTouch(DynamicHook handler) player.HUD.DisplayCheckpointMessages(PluginPrefix); // store the checkpoint in the player's current run checkpoints used for Checkpoint functionality - CheckpointObject cp2 = new CheckpointObject(stage, - player.Timer.Ticks, // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - player.Timer.Ticks, // To-do: this was supposed to be the ticks but that is used for run_time for HUD + Checkpoint cp2 = new Checkpoint(stage, + player.Timer.Ticks, velocity_x, velocity_y, velocity_z, -1.0f, -1.0f, -1.0f, - -1.0f, + 0, + 0, 0); player.Stats.ThisRun.Checkpoint[stage] = cp2; } @@ -176,15 +176,15 @@ internal HookResult OnTriggerStartTouch(DynamicHook handler) player.HUD.DisplayCheckpointMessages(PluginPrefix); // store the checkpoint in the player's current run checkpoints used for Checkpoint functionality - CheckpointObject cp2 = new CheckpointObject(checkpoint, - player.Timer.Ticks, // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - player.Timer.Ticks, // To-do: this was supposed to be the ticks but that is used for run_time for HUD + Checkpoint cp2 = new Checkpoint(checkpoint, + player.Timer.Ticks, velocity_x, velocity_y, velocity_z, -1.0f, -1.0f, -1.0f, + 0, -1.0f, 0); player.Stats.ThisRun.Checkpoint[checkpoint] = cp2; diff --git a/src/ST-Player/PlayerHUD.cs b/src/ST-Player/PlayerHUD.cs index df6f630..321f512 100644 --- a/src/ST-Player/PlayerHUD.cs +++ b/src/ST-Player/PlayerHUD.cs @@ -77,7 +77,7 @@ public void Display() string velocityModule = FormatHUDElementHTML("Speed", velocity.ToString("0"), "#79d1ed") + " u/s"; // Rank Module string rankModule = FormatHUDElementHTML("Rank", $"N/A", "#7882dd"); - if (_player.Stats.PB[0].RunTime > 0 && _player.CurrMap.WrRunTime > 0) + if (_player.Stats.PB[0].Ticks > 0 && _player.CurrMap.WrRunTime > 0) { rankModule = FormatHUDElementHTML("Rank", $"{_player.Stats.PB[0].Rank}/{_player.CurrMap.TotalCompletions}", "#7882dd"); } @@ -86,7 +86,7 @@ public void Display() rankModule = FormatHUDElementHTML("Rank", $"N/A/{_player.CurrMap.TotalCompletions}", "#7882dd"); } // PB & WR Modules - string pbModule = FormatHUDElementHTML("PB", _player.Stats.PB[0].RunTime > 0 ? FormatTime(_player.Stats.PB[0].RunTime) : "N/A", "#7882dd"); // IMPLEMENT IN PlayerStats // To-do: make Style (currently 0) be dynamic + string pbModule = FormatHUDElementHTML("PB", _player.Stats.PB[0].Ticks > 0 ? FormatTime(_player.Stats.PB[0].Ticks) : "N/A", "#7882dd"); // IMPLEMENT IN PlayerStats // To-do: make Style (currently 0) be dynamic string wrModule = FormatHUDElementHTML("WR", _player.CurrMap.WrRunTime > 0 ? FormatTime(_player.CurrMap.WrRunTime) : "N/A", "#ffc61a"); // IMPLEMENT IN PlayerStats - This should be part of CurrentMap, not PlayerStats? // Build HUD @@ -119,7 +119,7 @@ public void DisplayCheckpointMessages(string PluginPrefix) // To-do: PluginPrefi // Can check checkpoints count instead of try/catch try { - pbTime = _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].RunTime; + pbTime = _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].Ticks; pbSpeed = (float)Math.Sqrt(_player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].StartVelX * _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].StartVelX + _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].StartVelY * _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].StartVelY + _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].StartVelZ * _player.Stats.PB[0].Checkpoint[_player.Timer.Checkpoint].StartVelZ); diff --git a/src/ST-Player/PlayerStats.cs b/src/ST-Player/PlayerStats.cs index 2960e78..107db8f 100644 --- a/src/ST-Player/PlayerStats.cs +++ b/src/ST-Player/PlayerStats.cs @@ -7,8 +7,8 @@ namespace SurfTimer; /// internal class CurrentRun { - public Dictionary Checkpoint { get; set; } // Current RUN checkpoints tracker - public int RunTime { get; set; } // To-do: will be the last (any) zone end touch time + public Dictionary Checkpoint { get; set; } // Current RUN checkpoints tracker + public int Ticks { get; set; } // To-do: will be the last (any) zone end touch time public float StartVelX { get; set; } // This will store MAP START VELOCITY X public float StartVelY { get; set; } // This will store MAP START VELOCITY Y public float StartVelZ { get; set; } // This will store MAP START VELOCITY Z @@ -21,8 +21,8 @@ internal class CurrentRun // Constructor public CurrentRun() { - Checkpoint = new Dictionary(); - RunTime = 0; + Checkpoint = new Dictionary(); + Ticks = 0; StartVelX = 0.0f; StartVelY = 0.0f; StartVelZ = 0.0f; @@ -35,7 +35,7 @@ public CurrentRun() public void Reset() { Checkpoint.Clear(); - RunTime = 0; + Ticks = 0; StartVelX = 0.0f; StartVelY = 0.0f; StartVelZ = 0.0f; @@ -47,45 +47,14 @@ public void Reset() } } -public class CheckpointObject -{ - public int CP { get; set; } - public int RunTime { get; set; } // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - public int Ticks { get; set; } // To-do: this was supposed to be the ticks but that is used for run_time for HUD???? - // public float Speed { get; set; } // We shouldn't really need this, we can calculate it from the velocities - public float StartVelX { get; set; } - public float StartVelY { get; set; } - public float StartVelZ { get; set; } - public float EndVelX { get; set; } - public float EndVelY { get; set; } - public float EndVelZ { get; set; } - public float EndTouch { get; set; } - public int Attempts { get; set; } - - public CheckpointObject(int cp, int runTime, int ticks, float startVelX, float startVelY, float startVelZ, float endVelX, float endVelY, float endVelZ, float endTouch, int attempts) - { - CP = cp; - RunTime = runTime; // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - Ticks = ticks; // To-do: this was supposed to be the ticks but that is used for run_time for HUD???? - StartVelX = startVelX; - StartVelY = startVelY; - StartVelZ = startVelZ; - EndVelX = endVelX; - EndVelY = endVelY; - EndVelZ = endVelZ; - EndTouch = endTouch; - Attempts = attempts; - } -} - // To-do: make Style (currently 0) be dynamic // To-do: add `Type` internal class PersonalBest { - public int ID { get; set; } - public int RunTime { get; set; } - public int Rank { get; set; } - public Dictionary Checkpoint { get; set; } + public int ID { get; set; } = -1; // Exclude from constructor, retrieve from Database when loading/saving + public int Ticks { get; set; } + public int Rank { get; set; } = -1; // Exclude from constructor, retrieve from Database when loading/saving + public Dictionary Checkpoint { get; set; } // public int Type { get; set; } public float StartVelX { get; set; } public float StartVelY { get; set; } @@ -97,12 +66,10 @@ internal class PersonalBest // Add other properties as needed // Constructor - public PersonalBest(int id, int runTime, int rank, float startVelX, float startVelY, float startVelZ, float endVelX, float endVelY, float endVelZ, int runDate) + public PersonalBest(int runTime, float startVelX, float startVelY, float startVelZ, float endVelX, float endVelY, float endVelZ, int runDate) { - ID = id; - RunTime = runTime; // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - Rank = rank; - Checkpoint = new Dictionary(); + Ticks = runTime; // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? + Checkpoint = new Dictionary(); // Type = type; StartVelX = startVelX; StartVelY = startVelY; @@ -136,13 +103,13 @@ public void LoadCheckpointsForRun(TimerDatabase DB) Console.WriteLine($"CS2 Surf DEBUG >> internal class PersonalBest -> LoadCheckpointsForRun -> Checkpoints list is not initialized."); #endif - this.Checkpoint = new Dictionary(); // Initialize if null + this.Checkpoint = new Dictionary(); // Initialize if null } #if DEBUG Console.WriteLine($"this.Checkpoint.Count {this.Checkpoint.Count} "); Console.WriteLine($"this.ID {this.ID} "); - Console.WriteLine($"this.RunTime {this.RunTime} "); + Console.WriteLine($"this.Ticks {this.Ticks} "); Console.WriteLine($"this.RunDate {this.RunDate} "); #endif @@ -169,21 +136,24 @@ public void LoadCheckpointsForRun(TimerDatabase DB) Console.WriteLine($"sVelY {results.GetFloat("start_vel_y")} "); #endif - CheckpointObject cp = new(results.GetInt32("cp"), + Checkpoint cp = new(results.GetInt32("cp"), results.GetInt32("run_time"), // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - results.GetInt32("run_time"), // To-do: this was supposed to be the ticks but that is used for run_time for HUD results.GetFloat("start_vel_x"), results.GetFloat("start_vel_y"), results.GetFloat("start_vel_z"), results.GetFloat("end_vel_x"), results.GetFloat("end_vel_y"), results.GetFloat("end_vel_z"), + results.GetInt32("run_date"), results.GetFloat("end_touch"), results.GetInt32("attempts")); + cp.ID = results.GetInt32("id"); + // To-do: cp.ID = calculate Rank # from DB + Checkpoint[cp.CP] = cp; #if DEBUG - Console.WriteLine($"======= CS2 Surf DEBUG >> internal class PersonalBest -> LoadCheckpointsForRun -> Loaded CP {cp.CP} with RunTime {cp.RunTime}."); + Console.WriteLine($"======= CS2 Surf DEBUG >> internal class PersonalBest -> LoadCheckpointsForRun -> Loaded CP {cp.CP} with RunTime {cp.Ticks}."); #endif } results.Close(); @@ -203,8 +173,8 @@ public void LoadCheckpointsForRun(TimerDatabase DB) foreach (var item in player.Stats.ThisRun.Checkpoint) { int cp = item.Key; - int runTime = item.Value.RunTime; // To-do: what type of value we use here? DB uses DECIMAL but `.Tick` is int??? - int ticks = item.Value.Ticks; // To-do: this was supposed to be the ticks but that is used for run_time for HUD + int ticks = item.Value.Ticks; + int runTime = item.Value.Ticks / 64; // Runtime in decimal // double speed = item.Value.Speed; double startVelX = item.Value.StartVelX; double startVelY = item.Value.StartVelY; @@ -255,7 +225,7 @@ public void SaveMapTime(Player player, TimerDatabase DB, int mapId = 0) // To-do: add `type` Task updatePlayerRunTask = DB.Write($"INSERT INTO `MapTimes` " + $"(`player_id`, `map_id`, `style`, `type`, `stage`, `run_time`, `start_vel_x`, `start_vel_y`, `start_vel_z`, `end_vel_x`, `end_vel_y`, `end_vel_z`, `run_date`) " + - $"VALUES ({player.Profile.ID}, {player.CurrMap.ID}, 0, 0, 0, {this.RunTime}, " + + $"VALUES ({player.Profile.ID}, {player.CurrMap.ID}, 0, 0, 0, {this.Ticks}, " + $"{player.Stats.ThisRun.StartVelX}, {player.Stats.ThisRun.StartVelY}, {player.Stats.ThisRun.StartVelZ}, {player.Stats.ThisRun.EndVelX}, {player.Stats.ThisRun.EndVelY}, {player.Stats.ThisRun.EndVelZ}, {(int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()}) " + $"ON DUPLICATE KEY UPDATE run_time=VALUES(run_time), start_vel_x=VALUES(start_vel_x), start_vel_y=VALUES(start_vel_y), " + $"start_vel_z=VALUES(start_vel_z), end_vel_x=VALUES(end_vel_x), end_vel_y=VALUES(end_vel_y), end_vel_z=VALUES(end_vel_z), run_date=VALUES(run_date);"); @@ -269,6 +239,20 @@ public void SaveMapTime(Player player, TimerDatabase DB, int mapId = 0) } } +internal class Checkpoint : PersonalBest +{ + public int CP { get; set; } // Checkpoint number + public float EndTouch { get; set; } + public int Attempts { get; set; } + + public Checkpoint(int cp, int runTime, float startVelX, float startVelY, float startVelZ, float endVelX, float endVelY, float endVelZ, int runDate, float endTouch, int attempts) : base(runTime, startVelX, startVelY, startVelZ, endVelX, endVelY, endVelZ, runDate) + { + CP = cp; + EndTouch = endTouch; + Attempts = attempts; + } +} + internal class PlayerStats { // To-Do: Each stat should be a class of its own, with its own methods and properties - easier to work with. @@ -284,7 +268,7 @@ internal class PlayerStats // Here we can loop through all available styles at some point and initialize them public PlayerStats() { - PB[0] = new PersonalBest(-1, 0, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0); + PB[0] = new PersonalBest(0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0); // Add more styles as needed } @@ -318,11 +302,11 @@ public void LoadMapTimesData(Player player, TimerDatabase DB, int playerId = 0, PB[style].EndVelX = (float)playerStats.GetDouble("end_vel_x"); PB[style].EndVelY = (float)playerStats.GetDouble("end_vel_y"); PB[style].EndVelZ = (float)playerStats.GetDouble("end_vel_z"); - PB[style].RunTime = playerStats.GetInt32("run_time"); + PB[style].Ticks = playerStats.GetInt32("run_time"); PB[style].RunDate = playerStats.GetInt32("run_date"); PB[style].Rank = playerStats.GetInt32("rank"); - Console.WriteLine($"============== CS2 Surf DEBUG >> LoadMapTimesData -> PlayerID: {player.Profile.ID} | Rank: {PB[style].Rank} | ID: {PB[style].ID} | RunTime: {PB[style].RunTime} | SVX: {PB[style].StartVelX} | SVY: {PB[style].StartVelY} | SVZ: {PB[style].StartVelZ} | EVX: {PB[style].EndVelX} | EVY: {PB[style].EndVelY} | EVZ: {PB[style].EndVelZ} | Run Date (UNIX): {PB[style].RunDate}"); + Console.WriteLine($"============== CS2 Surf DEBUG >> LoadMapTimesData -> PlayerID: {player.Profile.ID} | Rank: {PB[style].Rank} | ID: {PB[style].ID} | RunTime: {PB[style].Ticks} | SVX: {PB[style].StartVelX} | SVY: {PB[style].StartVelY} | SVZ: {PB[style].StartVelZ} | EVX: {PB[style].EndVelX} | EVY: {PB[style].EndVelY} | EVZ: {PB[style].EndVelZ} | Run Date (UNIX): {PB[style].RunDate}"); #if DEBUG Console.WriteLine($"CS2 Surf DEBUG >> internal class PlayerStats -> LoadMapTimesData -> PlayerStats.PB (ID {PB[style].ID}) loaded from DB."); #endif