diff --git a/source/Patches/CrewmateRoles/ImitatorMod/MeetingStart.cs b/source/Patches/CrewmateRoles/ImitatorMod/MeetingStart.cs index cded736fa..dbc12a52c 100644 --- a/source/Patches/CrewmateRoles/ImitatorMod/MeetingStart.cs +++ b/source/Patches/CrewmateRoles/ImitatorMod/MeetingStart.cs @@ -3,6 +3,8 @@ using System; using System.Linq; using TownOfUs.CrewmateRoles.OracleMod; +using System.Collections.Generic; +using UnityEngine; namespace TownOfUs.CrewmateRoles.ImitatorMod { @@ -11,8 +13,51 @@ public class MeetingStart { public static void Postfix(MeetingHud __instance) { + if (!PlayerControl.LocalPlayer.Is(RoleEnum.Imitator)) + { + // RPC how many uses your ability had left so the Imitator's role knows the accurate count + List LimitedUsesRoles = new List() + { + RoleEnum.Engineer, + RoleEnum.Veteran, + RoleEnum.VampireHunter, + RoleEnum.Transporter, + RoleEnum.Trapper + }; + RoleEnum playerRole = Role.GetRole(PlayerControl.LocalPlayer).RoleType; + if (PlayerControl.LocalPlayer.Data.IsDead && LimitedUsesRoles.Contains(playerRole) && !StartImitate.UpdatedUses) + { + int newUses = 0; + if (playerRole == RoleEnum.Engineer) + { + newUses = ((Engineer)Role.GetRole(PlayerControl.LocalPlayer)).UsesLeft; + } + else if (playerRole == RoleEnum.Veteran) + { + newUses = ((Veteran)Role.GetRole(PlayerControl.LocalPlayer)).UsesLeft; + } + else if (playerRole == RoleEnum.VampireHunter) + { + newUses = ((VampireHunter)Role.GetRole(PlayerControl.LocalPlayer)).UsesLeft; + } + else if (playerRole == RoleEnum.Transporter) + { + newUses = ((Transporter)Role.GetRole(PlayerControl.LocalPlayer)).UsesLeft; + } + else if (playerRole == RoleEnum.Trapper) + { + newUses = ((Trapper)Role.GetRole(PlayerControl.LocalPlayer)).UsesLeft; + } + foreach(var role in Role.GetRoles(RoleEnum.Imitator)) + { + // Only needed once per game + StartImitate.UpdatedUses = true; + } + Utils.Rpc(CustomRPC.UpdateImitator, PlayerControl.LocalPlayer.PlayerId, newUses); + } + return; + } if (PlayerControl.LocalPlayer.Data.IsDead) return; - if (!PlayerControl.LocalPlayer.Is(RoleEnum.Imitator)) return; var imitatorRole = Role.GetRole(PlayerControl.LocalPlayer); if (imitatorRole.trappedPlayers != null) { diff --git a/source/Patches/CrewmateRoles/ImitatorMod/StartImitate.cs b/source/Patches/CrewmateRoles/ImitatorMod/StartImitate.cs index 228f8dbcd..a2638b6b7 100644 --- a/source/Patches/CrewmateRoles/ImitatorMod/StartImitate.cs +++ b/source/Patches/CrewmateRoles/ImitatorMod/StartImitate.cs @@ -4,6 +4,7 @@ using UnityEngine; using Object = UnityEngine.Object; using TownOfUs.Patches; +using System.Collections.Generic; namespace TownOfUs.CrewmateRoles.ImitatorMod { @@ -17,6 +18,8 @@ public static class AirshipExileController_WrapUpAndSpawn public class StartImitate { public static PlayerControl ImitatingPlayer; + public static Dictionary LimitedRoleUses; + public static bool UpdatedUses = false; public static void ExileControllerPostfix(ExileController __instance) { var exiled = __instance.exiled?.Object; @@ -45,6 +48,7 @@ public static void Imitate(Imitator imitator) { if (imitator.ImitatePlayer == null) return; ImitatingPlayer = imitator.Player; + LimitedRoleUses = imitator.LimitedRoleUses; var imitatorRole = Role.GetRole(imitator.ImitatePlayer).RoleType; if (imitatorRole == RoleEnum.Haunter) { @@ -62,12 +66,56 @@ public static void Imitate(Imitator imitator) if (imitatorRole == RoleEnum.Spy) new Spy(ImitatingPlayer); if (imitatorRole == RoleEnum.Tracker) new Tracker(ImitatingPlayer); if (imitatorRole == RoleEnum.Sheriff) new Sheriff(ImitatingPlayer); - if (imitatorRole == RoleEnum.Veteran) new Veteran(ImitatingPlayer); + if (imitatorRole == RoleEnum.Veteran) + { + var veteran = new Veteran(ImitatingPlayer); + if (LimitedRoleUses.ContainsKey("Veteran")) + { + veteran.UsesLeft = LimitedRoleUses["Veteran"]; + } + else + { + veteran.UsesLeft = ((Veteran)Role.GetRole(imitator.ImitatePlayer)).UsesLeft; + } + } if (imitatorRole == RoleEnum.Altruist) new Altruist(ImitatingPlayer); - if (imitatorRole == RoleEnum.Engineer) new Engineer(ImitatingPlayer); + if (imitatorRole == RoleEnum.Engineer) + { + var engi = new Engineer(ImitatingPlayer); + if (LimitedRoleUses.ContainsKey("Engineer")) + { + engi.UsesLeft = LimitedRoleUses["Engineer"]; + } + else + { + engi.UsesLeft = ((Engineer)Role.GetRole(imitator.ImitatePlayer)).UsesLeft; + } + } if (imitatorRole == RoleEnum.Medium) new Medium(ImitatingPlayer); - if (imitatorRole == RoleEnum.Transporter) new Transporter(ImitatingPlayer); - if (imitatorRole == RoleEnum.Trapper) new Trapper(ImitatingPlayer); + if (imitatorRole == RoleEnum.Transporter) + { + var trans = new Transporter(ImitatingPlayer); + if (LimitedRoleUses.ContainsKey("Transporter")) + { + trans.UsesLeft = LimitedRoleUses["Transporter"]; + } + else + { + trans.UsesLeft = ((Transporter)Role.GetRole(imitator.ImitatePlayer)).UsesLeft; + } + } + if (imitatorRole == RoleEnum.Trapper) + { + var trapper = new Trapper(ImitatingPlayer); + if (LimitedRoleUses.ContainsKey("Trapper")) + { + trapper.UsesLeft = LimitedRoleUses["Trapper"]; + } + else + { + trapper.UsesLeft = ((Trapper)Role.GetRole(imitator.ImitatePlayer)).UsesLeft; + } + } if (imitatorRole == RoleEnum.Oracle) new Oracle(ImitatingPlayer); if (imitatorRole == RoleEnum.Medic) { @@ -78,7 +126,14 @@ public static void Imitate(Imitator imitator) if (imitatorRole == RoleEnum.VampireHunter) { var vh = new VampireHunter(ImitatingPlayer); - vh.UsesLeft = CustomGameOptions.MaxFailedStakesPerGame; + if (LimitedRoleUses.ContainsKey("VampireHunter")) + { + vh.UsesLeft = LimitedRoleUses["VampireHunter"]; + } + else + { + vh.UsesLeft = ((VampireHunter)Role.GetRole(imitator.ImitatePlayer)).UsesLeft; + } vh.AddedStakes = true; } if (imitatorRole == RoleEnum.Aurial) diff --git a/source/Patches/CrewmateRoles/ImitatorMod/StopImitate.cs b/source/Patches/CrewmateRoles/ImitatorMod/StopImitate.cs index 8d6b55c58..7ac967eb1 100644 --- a/source/Patches/CrewmateRoles/ImitatorMod/StopImitate.cs +++ b/source/Patches/CrewmateRoles/ImitatorMod/StopImitate.cs @@ -23,6 +23,7 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameDat { List trappedPlayers = null; PlayerControl confessingPlayer = null; + Dictionary LimitedRoleUses = StartImitate.LimitedRoleUses; if (PlayerControl.LocalPlayer == StartImitate.ImitatingPlayer) { @@ -31,6 +32,7 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameDat if (PlayerControl.LocalPlayer.Is(RoleEnum.Engineer)) { var engineerRole = Role.GetRole(PlayerControl.LocalPlayer); + LimitedRoleUses["Engineer"] = engineerRole.UsesLeft; Object.Destroy(engineerRole.UsesText); } @@ -45,6 +47,7 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameDat if (PlayerControl.LocalPlayer.Is(RoleEnum.VampireHunter)) { var vhRole = Role.GetRole(PlayerControl.LocalPlayer); + LimitedRoleUses["VampireHunter"] = vhRole.UsesLeft; Object.Destroy(vhRole.UsesText); } @@ -58,6 +61,7 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameDat if (PlayerControl.LocalPlayer.Is(RoleEnum.Transporter)) { var transporterRole = Role.GetRole(PlayerControl.LocalPlayer); + LimitedRoleUses["Transporter"] = transporterRole.UsesLeft; Object.Destroy(transporterRole.UsesText); if (transporterRole.TransportList != null) { @@ -72,12 +76,14 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameDat if (PlayerControl.LocalPlayer.Is(RoleEnum.Veteran)) { var veteranRole = Role.GetRole(PlayerControl.LocalPlayer); + LimitedRoleUses["Veteran"] = veteranRole.UsesLeft; Object.Destroy(veteranRole.UsesText); } if (PlayerControl.LocalPlayer.Is(RoleEnum.Trapper)) { var trapperRole = Role.GetRole(PlayerControl.LocalPlayer); + LimitedRoleUses["Trapper"] = trapperRole.UsesLeft; Object.Destroy(trapperRole.UsesText); trapperRole.traps.ClearTraps(); trappedPlayers = trapperRole.trappedPlayers; @@ -121,6 +127,7 @@ public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] GameDat var imitator = new Imitator(StartImitate.ImitatingPlayer); imitator.trappedPlayers = trappedPlayers; imitator.confessingPlayer = confessingPlayer; + imitator.LimitedRoleUses = LimitedRoleUses; var newRole = Role.GetRole(StartImitate.ImitatingPlayer); newRole.RemoveFromRoleHistory(newRole.RoleType); newRole.Kills = killsList.Kills; diff --git a/source/Patches/CustomRPC.cs b/source/Patches/CustomRPC.cs index d02637ea7..ca8c883be 100644 --- a/source/Patches/CustomRPC.cs +++ b/source/Patches/CustomRPC.cs @@ -75,6 +75,7 @@ public enum CustomRPC HunterStalk, HunterCatchPlayer, Retribution, + UpdateImitator, BypassKill, BypassMultiKill, diff --git a/source/Patches/Roles/Imitator.cs b/source/Patches/Roles/Imitator.cs index a179e6199..0c6025aa8 100644 --- a/source/Patches/Roles/Imitator.cs +++ b/source/Patches/Roles/Imitator.cs @@ -12,6 +12,7 @@ public class Imitator : Role public List trappedPlayers = null; public PlayerControl confessingPlayer = null; + public Dictionary LimitedRoleUses = new Dictionary(); public Imitator(PlayerControl player) : base(player) diff --git a/source/Patches/RpcHandling.cs b/source/Patches/RpcHandling.cs index c74a2c663..a3c52730b 100644 --- a/source/Patches/RpcHandling.cs +++ b/source/Patches/RpcHandling.cs @@ -1215,6 +1215,31 @@ public static void Postfix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) var lastVoted = Utils.PlayerById(reader.ReadByte()); AssassinKill.MurderPlayer(lastVoted); break; + case CustomRPC.UpdateImitator: + var updatedPlayer = Utils.PlayerById(reader.ReadByte()); + int newUses = reader.ReadInt32(); + var playerRole = Role.GetRole(updatedPlayer); + if (playerRole.RoleType == RoleEnum.Engineer) + { + ((Engineer)playerRole).UsesLeft = newUses; + } + else if (playerRole.RoleType == RoleEnum.Veteran) + { + ((Veteran)playerRole).UsesLeft = newUses; + } + else if (playerRole.RoleType == RoleEnum.VampireHunter) + { + ((VampireHunter)playerRole).UsesLeft = newUses; + } + else if (playerRole.RoleType == RoleEnum.Transporter) + { + ((Transporter)playerRole).UsesLeft = newUses; + } + else if (playerRole.RoleType == RoleEnum.Trapper) + { + ((Trapper)playerRole).UsesLeft = newUses; + } + break; } } }