diff --git a/RolesMods/Patch/EndGamePatch.cs b/RolesMods/Patch/EndGamePatch.cs index 81bf159..349e7cd 100644 --- a/RolesMods/Patch/EndGamePatch.cs +++ b/RolesMods/Patch/EndGamePatch.cs @@ -24,7 +24,7 @@ public static void ResetGlobalVariable() { GlobalVariable.isGameStarted = false; Systems.Investigator.FootPrint.allFootprint.Clear(); HelperRoles.ClearRoles(); - Systems.TimeMaster.Time.pointsInTime.Clear(); + Systems.TimeMaster.Time.ClearGameHistory(); } } } \ No newline at end of file diff --git a/RolesMods/Patch/HandleRpcPatch.cs b/RolesMods/Patch/HandleRpcPatch.cs index e44353c..cdfed84 100644 --- a/RolesMods/Patch/HandleRpcPatch.cs +++ b/RolesMods/Patch/HandleRpcPatch.cs @@ -44,7 +44,7 @@ public static bool Prefix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] return false; } - if (callId == (byte) CustomRPC.SetLighter) { + if (callId == (byte) CustomRPC.SetPsychic) { GlobalVariable.PsychicList.Clear(); List selectedPlayers = reader.ReadBytesAndSize().ToList(); @@ -62,15 +62,6 @@ public static bool Prefix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1)] return false; } - if (callId == (byte) CustomRPC.TimeRevive) { - PlayerControl player = PlayerControlUtils.FromPlayerId(reader.ReadByte()); - player.Revive(); - var body = Object.FindObjectsOfType().FirstOrDefault(b => b.ParentId == player.PlayerId); - - if (body != null) - Object.Destroy(body.gameObject); - return false; - } if (callId == (byte) CustomRPC.SendOverlayPsychic) { bool show = reader.ReadBoolean(); diff --git a/RolesMods/Patch/StartPatch.cs b/RolesMods/Patch/StartPatch.cs index 2368642..77d1f06 100644 --- a/RolesMods/Patch/StartPatch.cs +++ b/RolesMods/Patch/StartPatch.cs @@ -10,7 +10,7 @@ public static void Postfix(ShipStatus __instance) { GlobalVariable.texts.Clear(); GlobalVariable.herePoints.Clear(); - Systems.TimeMaster.Time.pointsInTime.Clear(); + Systems.TimeMaster.Time.ClearGameHistory(); Systems.Investigator.FootPrint.allFootprint.Clear(); GlobalVariable.buttonTime.MaxTimer = RolesMods.TimeMasterCooldown.GetValue(); GlobalVariable.buttonTime.EffectDuration = RolesMods.TimeMasterDuration.GetValue() / 2; diff --git a/RolesMods/RolesMods.cs b/RolesMods/RolesMods.cs index deafcf4..0f95010 100644 --- a/RolesMods/RolesMods.cs +++ b/RolesMods/RolesMods.cs @@ -18,7 +18,7 @@ public class RolesMods : BasePlugin { // Investigator CustomOptions public static CustomToggleOption EnableInvestigator = CustomOption.AddToggle("Enable Investigator", false); public static CustomNumberOption NumberInvestigator = CustomOption.AddNumber("Number Investigator", 1f, 1f, 10f, 1f); - public static CustomNumberOption footPrintSize = CustomOption.AddNumber("Footprint Size", 0.25f, 0.5f, 0.05f, 0.05f); + public static CustomNumberOption footPrintSize = CustomOption.AddNumber("Footprint Size", 0.75f, 0.3f, 1f, 0.1f); public static CustomNumberOption fontPrintInterval = CustomOption.AddNumber("Footprint Interval", 1f, 0.25f, 5f, 0.25f); public static CustomNumberOption fontPrintDuration = CustomOption.AddNumber("Footprint Duration", 10f, 3f, 30f, 1f); public static CustomToggleOption AnonymousFootPrint = CustomOption.AddToggle("Anonymous Footprint", false); diff --git a/RolesMods/Systems/Investigator/FootPrint.cs b/RolesMods/Systems/Investigator/FootPrint.cs index b3ff409..c3d8fe2 100644 --- a/RolesMods/Systems/Investigator/FootPrint.cs +++ b/RolesMods/Systems/Investigator/FootPrint.cs @@ -1,76 +1,54 @@ -using RolesMods.Utility; +using Reactor; +using RolesMods.Utility; using System; +using System.Collections; using System.Collections.Generic; using UnityEngine; namespace RolesMods.Systems.Investigator { class FootPrint { public static List allFootprint = new List(); - - private readonly float footPrintSize; private Color footPrintColor; - private Vector3 footPrintPosition; - private readonly float footPrintDuration; - private readonly int footPrintUnixTime; private GameObject footPrint; - private Vector2 velocity; private SpriteRenderer spriteRenderer; - private readonly PlayerControl player; + public PlayerControl player; + public Vector2 position; public FootPrint(float footPrintSize, float footPrintDuration, PlayerControl player) { - this.footPrintSize = footPrintSize; this.footPrintColor = Palette.PlayerColors[(int) player.Data.ColorId]; - this.footPrintPosition = player.transform.position; - this.footPrintDuration = footPrintDuration; - this.velocity = player.gameObject.GetComponent().velocity; this.player = player; - this.footPrintUnixTime = (int) DateTimeOffset.Now.ToUnixTimeSeconds(); - + this.position = player.transform.position; if (RolesMods.AnonymousFootPrint.GetValue()) this.footPrintColor = new Color(0.2f, 0.2f, 0.2f, 1f); - Start(); - } - - private void Start() { footPrint = new GameObject("FootPrint"); - footPrint.transform.position = footPrintPosition; - footPrint.transform.localPosition = footPrintPosition; + footPrint.transform.position = position; + footPrint.transform.localPosition = position; footPrint.transform.localScale = new Vector2(footPrintSize, footPrintSize); footPrint.transform.SetParent(player.transform.parent); - footPrint.transform.Rotate(Vector3.forward * Vector2.SignedAngle(Vector2.up, velocity)); + footPrint.transform.Rotate(Vector3.forward * Vector2.SignedAngle(Vector2.up, player.gameObject.GetComponent().velocity)); + spriteRenderer = footPrint.AddComponent(); - spriteRenderer.sprite = HelperSprite.LoadSpriteFromEmbeddedResources("RolesMods.Resources.Footprint.png", 100f); + spriteRenderer.sprite = ResourceLoader.FootprintSprite; spriteRenderer.color = footPrintColor; footPrint.SetActive(true); allFootprint.Add(this); + Coroutines.Start(CoFadeOutAndDestroy(footPrintDuration)); } - private void DestroyThis() { - UnityEngine.Object.Destroy(footPrint); - allFootprint.Remove(this); - } + public IEnumerator CoFadeOutAndDestroy(float duration) { + for (float time = 0f; time < duration; time += Time.deltaTime) { + footPrintColor = Palette.PlayerColors[(int) player.Data.ColorId]; - public void Update() { - int currentUnixTime = (int) DateTimeOffset.Now.ToUnixTimeSeconds(); - float alpha = Mathf.Max((1f - ((currentUnixTime - footPrintUnixTime) / footPrintDuration)), 0f); - this.footPrintColor = Palette.PlayerColors[(int) player.Data.ColorId]; - - if (alpha < 0 || alpha > 1) - alpha = 0; + if (spriteRenderer) + spriteRenderer.color = new Color(footPrintColor.r, footPrintColor.g, footPrintColor.b, Mathf.Clamp(1f - time / duration, 0f, 1f)); - footPrintColor = new Color(footPrintColor.r, footPrintColor.g, footPrintColor.b, alpha); - spriteRenderer.color = footPrintColor; - - if (footPrintUnixTime + (int) footPrintDuration < currentUnixTime) - DestroyThis(); - } + yield return null; + } - public Vector3 FootPrintPosition { - get => footPrintPosition; + UnityEngine.Object.Destroy(footPrint); + allFootprint.Remove(this); } - - public PlayerControl Player => player; } } diff --git a/RolesMods/Systems/Investigator/UpdatePlayer.cs b/RolesMods/Systems/Investigator/UpdatePlayer.cs index c9364b2..5c62bf4 100644 --- a/RolesMods/Systems/Investigator/UpdatePlayer.cs +++ b/RolesMods/Systems/Investigator/UpdatePlayer.cs @@ -1,6 +1,5 @@ using HarmonyLib; using RolesMods.Utility; -using System.Collections.Generic; using System.Linq; using UnityEngine; @@ -8,18 +7,15 @@ namespace RolesMods.Systems.Investigator { [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.FixedUpdate))] public static class UpdatePlayerPatch { public static float time = 0.0f; - public static float interpolationPeriodNew = RolesMods.fontPrintInterval.GetValue(); - - public static float timeUpdate = 0.0f; - public static float interpolationPeriodUpdate = 1f; public static void Postfix(PlayerControl __instance) { + float interpolationPeriod = RolesMods.fontPrintInterval.GetValue(); + if (GlobalVariable.isGameStarted && GlobalVariable.InvestigatorsList != null && HelperRoles.IsInvestigator(PlayerControl.LocalPlayer.PlayerId)) { - // New Footprint time += Time.deltaTime; - if (time >= interpolationPeriodNew) { - time -= interpolationPeriodNew; + if (time >= interpolationPeriod) { + time -= interpolationPeriod; if (HelperRoles.IsInvestigator(PlayerControl.LocalPlayer.PlayerId)) { foreach (var player in PlayerControl.AllPlayerControls) { @@ -27,7 +23,7 @@ public static void Postfix(PlayerControl __instance) { bool canPlace = true; foreach (var footprint in FootPrint.allFootprint) - if (player.PlayerId == footprint.Player.PlayerId && Vector3.Distance(footprint.FootPrintPosition, PlayerControlUtils.Position(player)) < 0.25f) + if (player.PlayerId == footprint.player.PlayerId && Vector3.Distance(footprint.position, PlayerControlUtils.Position(player)) < 0.05f) canPlace = false; if (!RolesMods.VentFootprintVisible.GetValue() && ShipStatus.Instance != null) @@ -35,21 +31,12 @@ public static void Postfix(PlayerControl __instance) { if (Vector2.Distance(vent.gameObject.transform.position, PlayerControlUtils.Position(player)) < 1f) canPlace = false; - if (canPlace) new FootPrint(RolesMods.footPrintSize.GetValue(), RolesMods.fontPrintDuration.GetValue(), player); + if (canPlace) + new FootPrint(RolesMods.footPrintSize.GetValue(), RolesMods.fontPrintDuration.GetValue(), player); } } } } - - // Update - timeUpdate += Time.deltaTime; - if (timeUpdate >= interpolationPeriodUpdate) { - timeUpdate -= interpolationPeriodUpdate; - - foreach (var footprint in FootPrint.allFootprint.ToList()) { - footprint.Update(); - } - } } } } diff --git a/RolesMods/Systems/TimeMaster/Button.cs b/RolesMods/Systems/TimeMaster/Button.cs index c231cfb..7a8f40b 100644 --- a/RolesMods/Systems/TimeMaster/Button.cs +++ b/RolesMods/Systems/TimeMaster/Button.cs @@ -33,12 +33,11 @@ private static void OnUpdate(CooldownButton button) { if (PlayerControl.LocalPlayer.PlayerId == GlobalVariable.TimeMaster.PlayerId) if (PlayerControl.LocalPlayer.Data.IsDead) button.SetCanUse(false); - else - button.SetCanUse(true); + else button.SetCanUse(true); if (Time.isRewinding) for (int i = 0; i < 2; i++) - Time.Rewind(); + Time.Rewind(); else Time.Record(); } diff --git a/RolesMods/Systems/TimeMaster/GameHistory.cs b/RolesMods/Systems/TimeMaster/GameHistory.cs new file mode 100644 index 0000000..7baa5d8 --- /dev/null +++ b/RolesMods/Systems/TimeMaster/GameHistory.cs @@ -0,0 +1,16 @@ +using System; +using UnityEngine; + +namespace RolesMods.Systems.TimeMaster { + public class GameHistory { + public Vector3 position; + public DateTime positionTime; + public Vector2 velocity; + + public GameHistory(Vector3 position, DateTime positionTime, Vector2 velocity) { + this.position = position; + this.positionTime = positionTime; + this.velocity = velocity; + } + } +} diff --git a/RolesMods/Systems/TimeMaster/Time.cs b/RolesMods/Systems/TimeMaster/Time.cs index b4f6e43..eae6bf0 100644 --- a/RolesMods/Systems/TimeMaster/Time.cs +++ b/RolesMods/Systems/TimeMaster/Time.cs @@ -6,72 +6,73 @@ namespace RolesMods.Systems.TimeMaster { public static class Time { + public static Dictionary> PlayersPositions = new Dictionary>(); + public static Dictionary DeadPlayers = new Dictionary(); public static float recordTime = RolesMods.TimeMasterDuration.GetValue(); public static bool isRewinding = false; - internal static List pointsInTime = new List(); - private static long deadtime; - private static bool isDead = false; public static void Record() { - if (pointsInTime.Count > Mathf.Round(recordTime / UnityEngine.Time.fixedDeltaTime)) - pointsInTime.RemoveAt(pointsInTime.Count - 1); - - if (PlayerControl.LocalPlayer != null) { - pointsInTime.Insert(0, new TimePoint( - PlayerControl.LocalPlayer.transform.position, - PlayerControl.LocalPlayer.gameObject.GetComponent().velocity, - DateTimeOffset.Now.ToUnixTimeSeconds() - )); - - if (PlayerControl.LocalPlayer.Data.IsDead && !isDead) { - isDead = true; - deadtime = DateTimeOffset.Now.ToUnixTimeSeconds(); - } + foreach (var player in PlayerControl.AllPlayerControls) { + if (!PlayersPositions.ContainsKey(player.PlayerId)) + PlayersPositions[player.PlayerId] = new List(); - if (!PlayerControl.LocalPlayer.Data.IsDead && isDead) { - isDead = false; - deadtime = 0; - } + var currentPlayer = PlayersPositions.FirstOrDefault(d => d.Key == player.PlayerId); + while (currentPlayer.Value.Count >= Mathf.Round(RolesMods.TimeMasterDuration.GetValue() / UnityEngine.Time.fixedDeltaTime)) + currentPlayer.Value.RemoveAt(currentPlayer.Value.Count - 1); + currentPlayer.Value.Insert(0, new GameHistory(player.transform.position, DateTime.UtcNow, player.gameObject.GetComponent().velocity)); + + if (player.Data.IsDead && !DeadPlayers.ContainsKey(player.PlayerId)) + DeadPlayers[player.PlayerId] = DateTime.UtcNow; } } public static void Rewind() { - if (pointsInTime.Count > 0) { - - if (!PlayerControl.LocalPlayer.inVent) { - TimePoint currentTimePoint = pointsInTime[0]; - - PlayerControl.LocalPlayer.transform.position = currentTimePoint.Position; - PlayerControl.LocalPlayer.gameObject.GetComponent().velocity = currentTimePoint.Velocity; - - if (isDead && currentTimePoint.Unix < deadtime && PlayerControl.LocalPlayer.Data.IsDead && RolesMods.EnableReiveTimeMaster.GetValue()) { - PlayerControl.LocalPlayer.Revive(); - var body = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(b => b.ParentId == PlayerControl.LocalPlayer.PlayerId); + foreach (var player in PlayerControl.AllPlayerControls) { + if (!PlayersPositions.ContainsKey(player.PlayerId)) + continue; + + List gameHistory = PlayersPositions.FirstOrDefault(d => d.Key == player.PlayerId).Value; + + if (gameHistory.Count > 0) { + if (!player.inVent) { + var currentGemeHistory = gameHistory[0]; + player.transform.position = currentGemeHistory.position; + player.gameObject.GetComponent().velocity = currentGemeHistory.velocity; + + if (RolesMods.EnableReiveTimeMaster.GetValue() && player.Data.IsDead) + if (DeadPlayers.ContainsKey(player.PlayerId)) + if (currentGemeHistory.positionTime < DeadPlayers[player.PlayerId]) + TimeMasterRevive(player.PlayerId); + + if (Minigame.Instance) { + try { + Minigame.Instance.Close(); + } catch { } + } + } - if (body != null) - UnityEngine.Object.Destroy(body.gameObject); + gameHistory.RemoveAt(0); + } + } - deadtime = 0; - isDead = false; + bool CanStopRewind = true; + foreach (var player in PlayerControl.AllPlayerControls) { + if (!PlayersPositions.ContainsKey(player.PlayerId)) + continue; - MessageWriter write = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte) CustomRPC.TimeRevive, SendOption.None, -1); - write.Write(PlayerControl.LocalPlayer.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(write); - } - - if (Minigame.Instance) { - try { - Minigame.Instance.Close(); - } catch { } - } - } + List gameHistory = PlayersPositions.FirstOrDefault(d => d.Key == player.PlayerId).Value; + if (gameHistory.Count != 0 || gameHistory == null) + CanStopRewind = false; + } - pointsInTime.RemoveAt(0); - } else StopRewind(); + if (CanStopRewind) + StopRewind(); } public static void StartRewind() { + RolesMods.Logger.LogInfo(RolesMods.EnableReiveTimeMaster.GetValue()); + isRewinding = true; PlayerControl.LocalPlayer.moveable = false; HudManager.Instance.FullScreen.color = new Color(0f, 0.5f, 0.8f, 0.3f); @@ -85,6 +86,26 @@ public static void StopRewind() { isRewinding = false; PlayerControl.LocalPlayer.moveable = true; HudManager.Instance.FullScreen.enabled = false; + HudManager.Instance.FullScreen.color = new Color(1f, 0f, 0f, 0.3f); + } + + public static void TimeMasterRevive(byte playerId) { + foreach (PlayerControl player in PlayerControl.AllPlayerControls) { + if (player.PlayerId == playerId) { + player.Revive(); + var body = UnityEngine.Object.FindObjectsOfType().FirstOrDefault(b => b.ParentId == playerId); + if (body != null) + UnityEngine.Object.Destroy(body.gameObject); + + if (DeadPlayers.ContainsKey(player.PlayerId)) + DeadPlayers.Remove(player.PlayerId); + } + } + } + + public static void ClearGameHistory() { + PlayersPositions.Clear(); + DeadPlayers.Clear(); } } } diff --git a/RolesMods/Systems/TimeMaster/TimePoint.cs b/RolesMods/Systems/TimeMaster/TimePoint.cs deleted file mode 100644 index 3a9dc50..0000000 --- a/RolesMods/Systems/TimeMaster/TimePoint.cs +++ /dev/null @@ -1,31 +0,0 @@ -using UnityEngine; - -namespace RolesMods.Systems.TimeMaster { - class TimePoint { - - private Vector3 position; - private Vector2 velocity; - private long unix; - - public TimePoint(Vector3 position, Vector2 velocity, long unix) { - this.position = position; - this.velocity = velocity; - this.unix = unix; - } - - public Vector3 Position { - get => position; - set => position = value; - } - - public Vector2 Velocity { - get => velocity; - set => velocity = value; - } - - public long Unix { - get => unix; - set => unix = value; - } - } -} diff --git a/RolesMods/Utility/CooldownButton.cs b/RolesMods/Utility/CooldownButton.cs index c5adcdc..06e6546 100644 --- a/RolesMods/Utility/CooldownButton.cs +++ b/RolesMods/Utility/CooldownButton.cs @@ -65,6 +65,7 @@ private void Start() { startColorText = killButtonManager.TimerText.Color; killButtonManager.gameObject.SetActive(true); killButtonManager.renderer.enabled = true; + killButtonManager.renderer.sprite = sprite; PassiveButton button = killButtonManager.GetComponent(); button.OnClick.RemoveAllListeners(); button.OnClick.AddListener((UnityEngine.Events.UnityAction) listener);