diff --git a/README.md b/README.md index 803cbeb26..d0149cebe 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ Join our [Discord](https://discord.gg/ugyc4EVUYZ) if you have any problems or wa # Releases | Among Us - Version| Mod Version | Link | |----------|-------------|-----------------| +| 2023.3.28s & 2023.3.28e | v4.0.6 | [Download](https://github.com/eDonnes124/Town-Of-Us/releases/download/v4.0.6/ToU.v4.0.6.zip) | | 2023.3.28s & 2023.3.28e | v4.0.5 | [Download](https://github.com/eDonnes124/Town-Of-Us/releases/download/v4.0.5/ToU.v4.0.5.zip) | | 2023.3.28s & 2023.3.28e | v4.0.4 | [Download](https://github.com/eDonnes124/Town-Of-Us/releases/download/v4.0.4/ToU.v4.0.4.zip) | | 2023.2.28s & 2023.2.28e | v4.0.3 | [Download](https://github.com/eDonnes124/Town-Of-Us/releases/download/v4.0.3/ToU.v4.0.3.zip) | @@ -133,6 +134,10 @@ Join our [Discord](https://discord.gg/ugyc4EVUYZ) if you have any problems or wa
Changelog
+ v4.0.6 + +
+
v4.0.5
diff --git a/source/Patches/AddHauntPatch.cs b/source/Patches/AddHauntPatch.cs new file mode 100644 index 000000000..259356ba2 --- /dev/null +++ b/source/Patches/AddHauntPatch.cs @@ -0,0 +1,46 @@ +using HarmonyLib; +using System.Collections.Generic; +using UnityEngine; +using System; +using Object = UnityEngine.Object; +using TownOfUs.NeutralRoles.PhantomMod; +using TownOfUs.CrewmateRoles.HaunterMod; + +namespace TownOfUs.Patches +{ + [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] + public static class AirshipAddHauntPatch + { + public static void Postfix(AirshipExileController __instance) => AddHauntPatch.ExileControllerPostfix(__instance); + } + + [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] + [HarmonyPriority(Priority.First)] + class AddHauntPatch + { + public static List AssassinatedPlayers = new List(); + + public static void ExileControllerPostfix(ExileController __instance) + { + foreach (var player in AssassinatedPlayers) + { + try + { + if (SetPhantom.WillBePhantom != player && SetHaunter.WillBeHaunter != player + && !player.Data.Disconnected) player.Exiled(); + } + catch { } + } + AssassinatedPlayers.Clear(); + } + + public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); + + [HarmonyPatch(typeof(Object), nameof(Object.Destroy), new Type[] { typeof(GameObject) })] + public static void Prefix(GameObject obj) + { + if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; + if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); + } + } +} \ No newline at end of file diff --git a/source/Patches/CrewmateRoles/AltruistMod/Coroutine.cs b/source/Patches/CrewmateRoles/AltruistMod/Coroutine.cs index 4f327b24f..21736678a 100644 --- a/source/Patches/CrewmateRoles/AltruistMod/Coroutine.cs +++ b/source/Patches/CrewmateRoles/AltruistMod/Coroutine.cs @@ -10,8 +10,6 @@ using Object = UnityEngine.Object; using TownOfUs.Roles.Modifiers; using AmongUs.GameOptions; -using TownOfUs.Patches; -using Hazel; namespace TownOfUs.CrewmateRoles.AltruistMod { @@ -100,59 +98,6 @@ public static IEnumerator AltruistRevive(DeadBody target, Altruist role) { } - ExilePatch.CheckTraitorSpawn(null); - if (AmongUsClient.Instance.AmHost) - { - if (ExilePatch.WillBeHaunter == player) - { - var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && !x.Is(ModifierEnum.Lover) && x.Data.IsDead && !x.Data.Disconnected && x != player).ToList(); - if (toChooseFrom.Count == 0) - { - ExilePatch.WillBeHaunter = null; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); - writer.Write(byte.MaxValue); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - else - { - var rand = UnityEngine.Random.RandomRangeInt(0, toChooseFrom.Count); - var pc = toChooseFrom[rand]; - - ExilePatch.WillBeHaunter = pc; - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); - writer.Write(pc.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - if (ExilePatch.WillBePhantom == player) - { - var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => (x.Is(Faction.NeutralOther) || x.Is(Faction.NeutralKilling)) && !x.Is(ModifierEnum.Lover) && x.Data.IsDead && !x.Data.Disconnected && x != player).ToList(); - if (toChooseFrom.Count == 0) - { - ExilePatch.WillBePhantom = null; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); - writer.Write(byte.MaxValue); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - else - { - var rand = UnityEngine.Random.RandomRangeInt(0, toChooseFrom.Count); - var pc = toChooseFrom[rand]; - - ExilePatch.WillBePhantom = pc; - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); - writer.Write(pc.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - } - if (PlayerControl.LocalPlayer.Data.IsImpostor() || PlayerControl.LocalPlayer.Is(RoleEnum.Glitch) || PlayerControl.LocalPlayer.Is(RoleEnum.Juggernaut) || PlayerControl.LocalPlayer.Is(RoleEnum.Arsonist) || PlayerControl.LocalPlayer.Is(RoleEnum.Werewolf) || PlayerControl.LocalPlayer.Is(RoleEnum.Plaguebearer) || PlayerControl.LocalPlayer.Is(RoleEnum.Pestilence)) diff --git a/source/Patches/CrewmateRoles/HaunterMod/RepickHaunter.cs b/source/Patches/CrewmateRoles/HaunterMod/RepickHaunter.cs new file mode 100644 index 000000000..645afdf65 --- /dev/null +++ b/source/Patches/CrewmateRoles/HaunterMod/RepickHaunter.cs @@ -0,0 +1,32 @@ +using HarmonyLib; +using System.Linq; +using Hazel; +using UnityEngine; + +namespace TownOfUs.CrewmateRoles.HaunterMod +{ + [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] + public class RepickHaunter + { + private static void Postfix(HudManager __instance) + { + if (PlayerControl.AllPlayerControls.Count <= 1) return; + if (PlayerControl.LocalPlayer == null) return; + if (PlayerControl.LocalPlayer.Data == null) return; + if (PlayerControl.LocalPlayer != SetHaunter.WillBeHaunter) return; + if (PlayerControl.LocalPlayer.Data.IsDead) return; + var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && !x.Is(ModifierEnum.Lover) && x.Data.IsDead && !x.Data.Disconnected).ToList(); + if (toChooseFrom.Count == 0) return; + var rand = Random.RandomRangeInt(0, toChooseFrom.Count); + var pc = toChooseFrom[rand]; + + SetHaunter.WillBeHaunter = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + return; + } + } +} \ No newline at end of file diff --git a/source/Patches/CrewmateRoles/HaunterMod/SetHaunter.cs b/source/Patches/CrewmateRoles/HaunterMod/SetHaunter.cs new file mode 100644 index 000000000..c9926d32b --- /dev/null +++ b/source/Patches/CrewmateRoles/HaunterMod/SetHaunter.cs @@ -0,0 +1,89 @@ +using System; +using HarmonyLib; +using Hazel; +using TownOfUs.Roles; +using UnityEngine; +using Object = UnityEngine.Object; +using Random = UnityEngine.Random; +using TownOfUs.Patches; + +namespace TownOfUs.CrewmateRoles.HaunterMod +{ + [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] + public static class AirshipExileController_WrapUpAndSpawn + { + public static void Postfix(AirshipExileController __instance) => SetHaunter.ExileControllerPostfix(__instance); + } + + [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] + public class SetHaunter + { + public static PlayerControl WillBeHaunter; + public static Vector2 StartPosition; + + public static void ExileControllerPostfix(ExileController __instance) + { + if (WillBeHaunter == null) return; + var exiled = __instance.exiled?.Object; + if (!WillBeHaunter.Data.IsDead && exiled.Is(Faction.Crewmates) && !exiled.IsLover()) WillBeHaunter = exiled; + if (WillBeHaunter.Data.Disconnected) return; + if (!WillBeHaunter.Data.IsDead && WillBeHaunter != exiled) return; + + if (!WillBeHaunter.Is(RoleEnum.Haunter)) + { + var oldRole = Role.GetRole(WillBeHaunter); + var killsList = (oldRole.CorrectKills, oldRole.IncorrectKills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); + Role.RoleDictionary.Remove(WillBeHaunter.PlayerId); + if (PlayerControl.LocalPlayer == WillBeHaunter) + { + var role = new Haunter(PlayerControl.LocalPlayer); + role.formerRole = oldRole.RoleType; + role.CorrectKills = killsList.CorrectKills; + role.IncorrectKills = killsList.IncorrectKills; + role.CorrectAssassinKills = killsList.CorrectAssassinKills; + role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; + role.RegenTask(); + } + else + { + var role = new Haunter(WillBeHaunter); + role.formerRole = oldRole.RoleType; + role.CorrectKills = killsList.CorrectKills; + role.IncorrectKills = killsList.IncorrectKills; + role.CorrectAssassinKills = killsList.CorrectAssassinKills; + role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; + } + + Utils.RemoveTasks(WillBeHaunter); + if (!PlayerControl.LocalPlayer.Is(RoleEnum.Phantom)) WillBeHaunter.MyPhysics.ResetMoveState(); + + WillBeHaunter.gameObject.layer = LayerMask.NameToLayer("Players"); + } + + if (PlayerControl.LocalPlayer != WillBeHaunter) return; + + if (Role.GetRole(PlayerControl.LocalPlayer).Caught) return; + var startingVent = + ShipStatus.Instance.AllVents[Random.RandomRangeInt(0, ShipStatus.Instance.AllVents.Count)]; + + var writer2 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPos, SendOption.Reliable, -1); + writer2.Write(PlayerControl.LocalPlayer.PlayerId); + writer2.Write(startingVent.transform.position.x); + writer2.Write(startingVent.transform.position.y + 0.3636f); + AmongUsClient.Instance.FinishRpcImmediately(writer2); + + PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(new Vector2(startingVent.transform.position.x, startingVent.transform.position.y + 0.3636f)); + PlayerControl.LocalPlayer.MyPhysics.RpcEnterVent(startingVent.Id); + } + + public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); + + [HarmonyPatch(typeof(Object), nameof(Object.Destroy), new Type[] { typeof(GameObject) })] + public static void Prefix(GameObject obj) + { + if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; + if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); + } + } +} \ No newline at end of file diff --git a/source/Patches/CrewmateRoles/SpyMod/Admin.cs b/source/Patches/CrewmateRoles/SpyMod/Admin.cs index 411db92c8..c780c4187 100644 --- a/source/Patches/CrewmateRoles/SpyMod/Admin.cs +++ b/source/Patches/CrewmateRoles/SpyMod/Admin.cs @@ -39,6 +39,7 @@ public static void UpdateBlips(CounterArea area, List colorMapping, bool is public static void UpdateBlips(MapCountOverlay __instance, bool isSpy) { var rooms = ShipStatus.Instance.FastRooms; + var colorMapDuplicate = new List(); foreach (var area in __instance.CountAreas) { if (!rooms.ContainsKey(area.RoomType)) continue; @@ -46,21 +47,33 @@ public static void UpdateBlips(MapCountOverlay __instance, bool isSpy) if (room.roomArea == null) continue; var objectsInRoom = room.roomArea.OverlapCollider(__instance.filter, __instance.buffer); var colorMap = new List(); - for (var i = 0;i < objectsInRoom;i++) + for (var i = 0; i < objectsInRoom; i++) { var collider = __instance.buffer[i]; var player = collider.GetComponent(); var data = player?.Data; if (collider.tag == "DeadBody" && - (isSpy && CustomGameOptions.WhoSeesDead == AdminDeadPlayers.Spy || + (isSpy && CustomGameOptions.WhoSeesDead == AdminDeadPlayers.Spy || !isSpy && CustomGameOptions.WhoSeesDead == AdminDeadPlayers.EveryoneButSpy || CustomGameOptions.WhoSeesDead == AdminDeadPlayers.Everyone)) { var playerId = collider.GetComponent().ParentId; colorMap.Add(GameData.Instance.GetPlayerById(playerId).DefaultOutfit.ColorId); + colorMapDuplicate.Add(GameData.Instance.GetPlayerById(playerId).DefaultOutfit.ColorId); continue; } - if (data != null && !data.Disconnected && !data.IsDead && !colorMap.Contains(data.DefaultOutfit.ColorId)) colorMap.Add(data.DefaultOutfit.ColorId); + else + { + PlayerControl component = collider.GetComponent(); + if (component && component.Data != null && !component.Data.Disconnected && !component.Data.IsDead && (__instance.showLivePlayerPosition || !component.AmOwner)) + { + if (!colorMapDuplicate.Contains(data.DefaultOutfit.ColorId)) + { + colorMap.Add(data.DefaultOutfit.ColorId); + colorMapDuplicate.Add(data.DefaultOutfit.ColorId); + } + } + } } UpdateBlips(area, colorMap, isSpy); } diff --git a/source/Patches/CrewmateRoles/SwapperMod/NoButtons.cs b/source/Patches/CrewmateRoles/SwapperMod/NoButtons.cs deleted file mode 100644 index 42df1d1da..000000000 --- a/source/Patches/CrewmateRoles/SwapperMod/NoButtons.cs +++ /dev/null @@ -1,24 +0,0 @@ -using HarmonyLib; - -namespace TownOfUs.CrewmateRoles.SwapperMod -{ - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetRole))] - public class NoButtons - { - public static void Postfix() - { - if (!CustomGameOptions.SwapperButton) - if (PlayerControl.LocalPlayer.Is(RoleEnum.Swapper)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; - } - } - - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Start))] - public class NoButtonsHost - { - public static void Postfix() - { - if (!CustomGameOptions.SwapperButton) - if (PlayerControl.LocalPlayer.Is(RoleEnum.Swapper)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; - } - } -} \ No newline at end of file diff --git a/source/Patches/CrewmateRoles/SwapperMod/ShowHideButtons.cs b/source/Patches/CrewmateRoles/SwapperMod/ShowHideButtons.cs index 2010b4c82..dcf7fdcae 100644 --- a/source/Patches/CrewmateRoles/SwapperMod/ShowHideButtons.cs +++ b/source/Patches/CrewmateRoles/SwapperMod/ShowHideButtons.cs @@ -2,7 +2,6 @@ using System.Linq; using HarmonyLib; using Hazel; -using Reactor.Utilities; using TownOfUs.CrewmateRoles.MayorMod; using TownOfUs.Extensions; using TownOfUs.Roles; diff --git a/source/Patches/CrewmateRoles/VeteranMod/PerformKill.cs b/source/Patches/CrewmateRoles/VeteranMod/PerformKill.cs index 14808bcda..709fc0a76 100644 --- a/source/Patches/CrewmateRoles/VeteranMod/PerformKill.cs +++ b/source/Patches/CrewmateRoles/VeteranMod/PerformKill.cs @@ -23,7 +23,6 @@ public static bool Prefix(KillButton __instance) if (role.AlertTimer() != 0) return false; role.TimeRemaining = CustomGameOptions.AlertDuration; role.UsesLeft--; - role.RegenTask(); role.Alert(); var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.Alert, SendOption.Reliable, -1); diff --git a/source/Patches/CrewmateRoles/VigilanteMod/VigilanteKill.cs b/source/Patches/CrewmateRoles/VigilanteMod/VigilanteKill.cs index 08133fd27..8307f0f26 100644 --- a/source/Patches/CrewmateRoles/VigilanteMod/VigilanteKill.cs +++ b/source/Patches/CrewmateRoles/VigilanteMod/VigilanteKill.cs @@ -212,35 +212,10 @@ public static void MurderPlayer( } } - if (ExilePatch.HaunterOn && ExilePatch.WillBeHaunter == null) - { - if (player.Is(Faction.Crewmates) && !player.Is(ModifierEnum.Lover)) - { - ExilePatch.WillBeHaunter = player; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); - writer.Write(player.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - - if (ExilePatch.PhantomOn && ExilePatch.WillBePhantom == null) - { - if ((player.Is(Faction.NeutralOther) || player.Is(Faction.NeutralKilling)) && !player.Is(ModifierEnum.Lover)) - { - ExilePatch.WillBePhantom = player; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); - writer.Write(player.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - meetingHud.CheckForEndVoting(); } - ExilePatch.AssassinatedPlayers.Add(player); - ExilePatch.CheckTraitorSpawn(player); + AddHauntPatch.AssassinatedPlayers.Add(player); } } } diff --git a/source/Patches/CultistRoles/ChameleonMod/PerformKill.cs b/source/Patches/CultistRoles/ChameleonMod/PerformKill.cs index f7dcfc00b..d96c80cfc 100644 --- a/source/Patches/CultistRoles/ChameleonMod/PerformKill.cs +++ b/source/Patches/CultistRoles/ChameleonMod/PerformKill.cs @@ -22,7 +22,6 @@ public static bool Prefix(KillButton __instance) if (!__instance.isActiveAndEnabled) return false; if (role.SwoopTimer() != 0) return false; role.TimeRemaining = CustomGameOptions.SwoopDuration; - role.RegenTask(); role.Swoop(); var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.ChameleonSwoop, SendOption.Reliable, -1); diff --git a/source/Patches/CultistRoles/CultistExile.cs b/source/Patches/CultistRoles/CultistExile.cs new file mode 100644 index 000000000..081a08bc7 --- /dev/null +++ b/source/Patches/CultistRoles/CultistExile.cs @@ -0,0 +1,55 @@ +using HarmonyLib; +using System.Linq; +using TownOfUs.Extensions; +using UnityEngine; +using System; +using TownOfUs.Patches; + +namespace TownOfUs.CultistRoles +{ + [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] + public static class AirshipExileController_WrapUpAndSpawn + { + public static void Postfix(AirshipExileController __instance) => CultistExilePatch.ExileControllerPostfix(__instance); + } + + [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] + public class CultistExilePatch + { + public static void ExileControllerPostfix(ExileController __instance) + { + var exiled = __instance.exiled?.Object; + var cultist = PlayerControl.AllPlayerControls.ToArray() + .Where(x => x.Is(RoleEnum.Necromancer) || x.Is(RoleEnum.Whisperer)).ToList(); + foreach (var cult in cultist) + { + if (cult.Data.IsDead || cult.Data.Disconnected) + { + foreach (var player in PlayerControl.AllPlayerControls) + { + if (player.Data.IsImpostor()) Utils.MurderPlayer(player, player, true); + } + } + } + if (exiled == null) return; + if (exiled.Is(RoleEnum.Necromancer) || exiled.Is(RoleEnum.Whisperer)) + { + var alives = PlayerControl.AllPlayerControls.ToArray() + .Where(x => !x.Data.IsDead && !x.Data.Disconnected).ToList(); + foreach (var player in alives) + { + if (player.Data.IsImpostor()) Utils.MurderPlayer(player, player, true); + } + } + } + + public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); + + [HarmonyPatch(typeof(UnityEngine.Object), nameof(UnityEngine.Object.Destroy), new Type[] { typeof(GameObject) })] + public static void Prefix(GameObject obj) + { + if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; + if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); + } + } +} \ No newline at end of file diff --git a/source/Patches/CustomRPC.cs b/source/Patches/CustomRPC.cs index d346b1365..fdb415703 100644 --- a/source/Patches/CustomRPC.cs +++ b/source/Patches/CustomRPC.cs @@ -8,7 +8,6 @@ public enum CustomRPC SetAssassin, SetTarget, SetGATarget, - SetDelayRoles, SetPhantom, CatchPhantom, @@ -17,6 +16,7 @@ public enum CustomRPC CatchHaunter, SetTraitor, + TraitorSpawn, LoveWin, GlitchWin, diff --git a/source/Patches/Disconnect.cs b/source/Patches/Disconnect.cs index e20183a40..ce330594a 100644 --- a/source/Patches/Disconnect.cs +++ b/source/Patches/Disconnect.cs @@ -1,4 +1,8 @@ using HarmonyLib; +using Hazel; +using System.Linq; +using UnityEngine; +using TownOfUs.ImpostorRoles.TraitorMod; using TownOfUs.Roles.Modifiers; namespace TownOfUs.Patches @@ -22,8 +26,7 @@ public static void Prefix([HarmonyArgument(0)] PlayerControl player) } else { - ExilePatch.CheckTraitorSpawn(player); - /*if (player.IsLover()) + /*if (player.IsLover() && CustomGameOptions.BothLoversDie) { var otherLover = Modifier.GetModifier(player).OtherLover; if (!otherLover.Is(RoleEnum.Pestilence) && !otherLover.Data.IsDead @@ -34,6 +37,24 @@ public static void Prefix([HarmonyArgument(0)] PlayerControl player) sheriff.IncorrectKills -= 1; } }*/ + if (AmongUsClient.Instance.AmHost) + { + if (player == SetTraitor.WillBeTraitor) + { + var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && + !x.Is(ModifierEnum.Lover) && !x.Data.IsDead && !x.Data.Disconnected && !x.IsExeTarget()).ToList(); + if (toChooseFrom.Count == 0) return; + var rand = Random.RandomRangeInt(0, toChooseFrom.Count); + var pc = toChooseFrom[rand]; + + SetTraitor.WillBeTraitor = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetTraitor, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + } } } } diff --git a/source/Patches/Exile.cs b/source/Patches/Exile.cs deleted file mode 100644 index 309e7740c..000000000 --- a/source/Patches/Exile.cs +++ /dev/null @@ -1,407 +0,0 @@ -using HarmonyLib; -using System.Linq; -using TownOfUs.Extensions; -using UnityEngine; -using System; -using Hazel; -using TownOfUs.Roles; -using TownOfUs.CrewmateRoles.ImitatorMod; -using TownOfUs.CrewmateRoles.InvestigatorMod; -using TownOfUs.CrewmateRoles.SnitchMod; -using AmongUs.GameOptions; -using Reactor.Utilities; -using TownOfUs.Roles.Modifiers; -using System.Collections.Generic; - -namespace TownOfUs.Patches -{ - [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] - public static class AirshipExileController_WrapUpAndSpawn - { - public static void Postfix(AirshipExileController __instance) => ExilePatch.ExileControllerPostfix(__instance); - } - - [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] - public class ExilePatch - { - public static List AssassinatedPlayers = new List(); - public static void ExileControllerPostfix(ExileController __instance) - { - if (PlayerControl.LocalPlayer.Data.Disconnected) return; - foreach (var player in AssassinatedPlayers) - { - if (!player.Data.Disconnected) player.Exiled(); - } - AssassinatedPlayers.Clear(); - var exiled = __instance.exiled?.Object; - if (exiled != null) - { - foreach (var role in Role.GetRoles(RoleEnum.Jester)) - { - if (exiled.PlayerId == ((Jester)role).Player.PlayerId) ((Jester)role).Wins(); - return; - } - foreach (var role in Role.GetRoles(RoleEnum.Executioner)) - { - if (exiled.PlayerId == ((Executioner)role).target.PlayerId) ((Executioner)role).Wins(); - return; - } - } - if (CustomGameOptions.GameMode == GameMode.Cultist) CultistExile(exiled); - CheckTraitorSpawn(exiled); - SetHaunter(exiled); - SetPhantom(exiled); - SetTraitor(exiled); - if (PlayerControl.LocalPlayer.Is(RoleEnum.Arsonist)) ArsonistLastKiller(exiled); - if (exiled.IsLover() && CustomGameOptions.BothLoversDie) - { - var otherLover = Modifier.GetModifier(exiled).OtherLover.Player; - if (!otherLover.Is(RoleEnum.Pestilence) && !otherLover.Data.IsDead - && !otherLover.Data.Disconnected) otherLover.Exiled(); - } - } - - public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); - - [HarmonyPatch(typeof(UnityEngine.Object), nameof(UnityEngine.Object.Destroy), new Type[] { typeof(GameObject) })] - public static void Prefix(GameObject obj) - { - if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; - if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); - } - - public static void CultistExile(PlayerControl exiled) - { - var cultist = PlayerControl.AllPlayerControls.ToArray() - .Where(x => x.Is(RoleEnum.Necromancer) || x.Is(RoleEnum.Whisperer)).ToList(); - foreach (var cult in cultist) - { - if (cult.Data.IsDead || cult.Data.Disconnected) - { - foreach (var player in PlayerControl.AllPlayerControls) - { - if (player.Data.IsImpostor()) Utils.MurderPlayer(player, player, true); - } - } - } - if (exiled == null) return; - if (exiled.Is(RoleEnum.Necromancer) || exiled.Is(RoleEnum.Whisperer)) - { - var alives = PlayerControl.AllPlayerControls.ToArray() - .Where(x => !x.Data.IsDead && !x.Data.Disconnected).ToList(); - foreach (var player in alives) - { - if (player.Data.IsImpostor()) Utils.MurderPlayer(player, player, true); - } - } - } - - public static bool HaunterOn; - public static PlayerControl WillBeHaunter; - public static void SetHaunter(PlayerControl exiled) - { - if (!HaunterOn) return; - if (WillBeHaunter == null && exiled.Is(Faction.Crewmates) && !exiled.IsLover()) WillBeHaunter = exiled; - if (WillBeHaunter != null && !WillBeHaunter.Is(RoleEnum.Haunter)) - { - var oldRole = Role.GetRole(WillBeHaunter); - var killsList = (oldRole.CorrectKills, oldRole.IncorrectKills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); - Role.RoleDictionary.Remove(WillBeHaunter.PlayerId); - var role = new Haunter(WillBeHaunter); - role.formerRole = oldRole.RoleType; - role.CorrectKills = killsList.CorrectKills; - role.IncorrectKills = killsList.IncorrectKills; - role.CorrectAssassinKills = killsList.CorrectAssassinKills; - role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; - role.RegenTask(); - - WillBeHaunter.gameObject.layer = LayerMask.NameToLayer("Players"); - RemoveTasks(WillBeHaunter); - if (!PlayerControl.LocalPlayer.Is(RoleEnum.Phantom)) PlayerControl.LocalPlayer.MyPhysics.ResetMoveState(); - } - if (WillBeHaunter != null && WillBeHaunter == PlayerControl.LocalPlayer) - { - if (Role.GetRole(WillBeHaunter).Caught) return; - var startingVent = - ShipStatus.Instance.AllVents[UnityEngine.Random.RandomRangeInt(0, ShipStatus.Instance.AllVents.Count)]; - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPos, SendOption.Reliable, -1); - writer.Write(WillBeHaunter.PlayerId); - writer.Write(startingVent.transform.position.x); - writer.Write(startingVent.transform.position.y + 0.3636f); - AmongUsClient.Instance.FinishRpcImmediately(writer); - - WillBeHaunter.NetTransform.RpcSnapTo(new Vector2(startingVent.transform.position.x, startingVent.transform.position.y + 0.3636f)); - PlayerControl.LocalPlayer.MyPhysics.RpcEnterVent(startingVent.Id); - } - } - - public static bool PhantomOn; - public static PlayerControl WillBePhantom; - public static void SetPhantom(PlayerControl exiled) - { - if (!PhantomOn) return; - if (WillBePhantom == null && (exiled.Is(Faction.NeutralOther) || exiled.Is(Faction.NeutralKilling)) && !exiled.IsLover()) WillBePhantom = exiled; - if (WillBePhantom != null && !WillBePhantom.Is(RoleEnum.Phantom)) - { - var oldRole = Role.GetRole(WillBePhantom); - var killsList = (oldRole.Kills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); - Role.RoleDictionary.Remove(WillBePhantom.PlayerId); - var role = new Phantom(WillBePhantom); - role.Kills = killsList.Kills; - role.CorrectAssassinKills = killsList.CorrectAssassinKills; - role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; - role.RegenTask(); - - WillBePhantom.gameObject.layer = LayerMask.NameToLayer("Players"); - RemoveTasks(WillBePhantom); - if (!PlayerControl.LocalPlayer.Is(RoleEnum.Haunter)) PlayerControl.LocalPlayer.MyPhysics.ResetMoveState(); - } - if (WillBePhantom != null && WillBePhantom == PlayerControl.LocalPlayer) - { - if (Role.GetRole(WillBePhantom).Caught) return; - var startingVent = - ShipStatus.Instance.AllVents[UnityEngine.Random.RandomRangeInt(0, ShipStatus.Instance.AllVents.Count)]; - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPos, SendOption.Reliable, -1); - writer.Write(WillBePhantom.PlayerId); - writer.Write(startingVent.transform.position.x); - writer.Write(startingVent.transform.position.y + 0.3636f); - AmongUsClient.Instance.FinishRpcImmediately(writer); - - WillBePhantom.NetTransform.RpcSnapTo(new Vector2(startingVent.transform.position.x, startingVent.transform.position.y + 0.3636f)); - PlayerControl.LocalPlayer.MyPhysics.RpcEnterVent(startingVent.Id); - } - } - - public static bool TraitorOn; - public static bool TraitorCanSpawn; - public static PlayerControl WillBeTraitor; - public static Sprite Sprite => TownOfUs.Arrow; - public static void SetTraitor(PlayerControl exiled) - { - if (!TraitorOn || !TraitorCanSpawn) return; - if (AmongUsClient.Instance.AmHost && WillBeTraitor == null) - { - var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && - !x.Is(ModifierEnum.Lover) && !x.Data.IsDead && !x.Data.Disconnected && x != exiled && !x.IsExeTarget()).ToList(); - var rand = UnityEngine.Random.RandomRangeInt(0, toChooseFrom.Count); - var pc = toChooseFrom[rand]; - - WillBeTraitor = pc; - - if (WillBeTraitor == StartImitate.ImitatingPlayer) StartImitate.ImitatingPlayer = null; - - var oldRole = Role.GetRole(WillBeTraitor); - var killsList = (oldRole.CorrectKills, oldRole.IncorrectKills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); - Role.RoleDictionary.Remove(WillBeTraitor.PlayerId); - var role = new Traitor(WillBeTraitor); - role.formerRole = oldRole.RoleType; - role.CorrectKills = killsList.CorrectKills; - role.IncorrectKills = killsList.IncorrectKills; - role.CorrectAssassinKills = killsList.CorrectAssassinKills; - role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; - role.RegenTask(); - - SpawnTraitor(WillBeTraitor); - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetTraitor, SendOption.Reliable, -1); - writer.Write(pc.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - - public static void SpawnTraitor(PlayerControl player) - { - if (PlayerControl.LocalPlayer == player) - { - if (PlayerControl.LocalPlayer.Is(RoleEnum.Snitch)) - { - var snitchRole = Role.GetRole(PlayerControl.LocalPlayer); - snitchRole.ImpArrows.DestroyAll(); - snitchRole.SnitchArrows.Values.DestroyAll(); - snitchRole.SnitchArrows.Clear(); - CompleteTask.Postfix(PlayerControl.LocalPlayer); - } - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Investigator)) Footprint.DestroyAll(Role.GetRole(PlayerControl.LocalPlayer)); - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Engineer)) - { - var engineerRole = Role.GetRole(PlayerControl.LocalPlayer); - UnityEngine.Object.Destroy(engineerRole.UsesText); - } - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Tracker)) - { - var trackerRole = Role.GetRole(PlayerControl.LocalPlayer); - trackerRole.TrackerArrows.Values.DestroyAll(); - trackerRole.TrackerArrows.Clear(); - UnityEngine.Object.Destroy(trackerRole.UsesText); - } - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Transporter)) - { - var transporterRole = Role.GetRole(PlayerControl.LocalPlayer); - UnityEngine.Object.Destroy(transporterRole.UsesText); - } - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Veteran)) - { - var veteranRole = Role.GetRole(PlayerControl.LocalPlayer); - UnityEngine.Object.Destroy(veteranRole.UsesText); - } - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Medium)) - { - var medRole = Role.GetRole(PlayerControl.LocalPlayer); - medRole.MediatedPlayers.Values.DestroyAll(); - medRole.MediatedPlayers.Clear(); - } - - if (PlayerControl.LocalPlayer.Is(RoleEnum.Trapper)) - { - var trapperRole = Role.GetRole(PlayerControl.LocalPlayer); - UnityEngine.Object.Destroy(trapperRole.UsesText); - } - - DestroyableSingleton.Instance.KillButton.gameObject.SetActive(true); - Coroutines.Start(Utils.FlashCoroutine(Color.red, 1f)); - } - player.Data.Role.TeamType = RoleTeamTypes.Impostor; - RoleManager.Instance.SetRole(player, RoleTypes.Impostor); - player.SetKillTimer(GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown); - - foreach (var player2 in PlayerControl.AllPlayerControls) - { - if (player2.Data.IsImpostor() && PlayerControl.LocalPlayer.Data.IsImpostor()) - { - player2.nameText().color = Patches.Colors.Impostor; - } - } - - if (CustomGameOptions.TraitorCanAssassin) new Assassin(player); - - foreach (var snitch in Role.GetRoles(RoleEnum.Snitch)) - { - var snitchRole = (Snitch)snitch; - if (snitchRole.TasksDone && PlayerControl.LocalPlayer.Is(RoleEnum.Snitch) && CustomGameOptions.SnitchSeesTraitor) - { - var gameObj = new GameObject(); - var arrow = gameObj.AddComponent(); - gameObj.transform.parent = PlayerControl.LocalPlayer.gameObject.transform; - var renderer = gameObj.AddComponent(); - renderer.sprite = Sprite; - arrow.image = renderer; - gameObj.layer = 5; - snitchRole.SnitchArrows.Add(player.PlayerId, arrow); - } - else if (snitchRole.Revealed && PlayerControl.LocalPlayer.Is(RoleEnum.Traitor) && CustomGameOptions.SnitchSeesTraitor) - { - var gameObj = new GameObject(); - var arrow = gameObj.AddComponent(); - gameObj.transform.parent = PlayerControl.LocalPlayer.gameObject.transform; - var renderer = gameObj.AddComponent(); - renderer.sprite = Sprite; - arrow.image = renderer; - gameObj.layer = 5; - snitchRole.ImpArrows.Add(arrow); - } - } - - foreach (var haunter in Role.GetRoles(RoleEnum.Haunter)) - { - var haunterRole = (Haunter)haunter; - if (haunterRole.Revealed && PlayerControl.LocalPlayer.Is(RoleEnum.Traitor)) - { - var gameObj = new GameObject(); - var arrow = gameObj.AddComponent(); - gameObj.transform.parent = PlayerControl.LocalPlayer.gameObject.transform; - var renderer = gameObj.AddComponent(); - renderer.sprite = Sprite; - arrow.image = renderer; - gameObj.layer = 5; - haunterRole.ImpArrows.Add(arrow); - } - } - } - - public static void CheckTraitorSpawn(PlayerControl deadPlayer) - { - if (CustomGameOptions.GameMode == GameMode.Cultist || CustomGameOptions.GameMode == GameMode.KillingOnly) return; - if (!TraitorOn) return; - foreach (var traitor in PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(RoleEnum.Traitor))) - { - TraitorCanSpawn = false; - return; - } - var alivePlayers = PlayerControl.AllPlayerControls.ToArray().Where(x => !x.Data.IsDead && !x.Data.Disconnected && x != deadPlayer).ToList(); - foreach (var player in alivePlayers) - { - if (player.Data.IsImpostor() || (player.Is(Faction.NeutralKilling) && CustomGameOptions.NeutralKillingStopsTraitor)) - { - TraitorCanSpawn = false; - return; - } - } - if (alivePlayers.Count < CustomGameOptions.LatestSpawn) - { - TraitorCanSpawn = false; - return; - } - - alivePlayers = alivePlayers.ToArray().Where(x => x.Is(Faction.Crewmates) && !x.IsLover() && !x.IsExeTarget()).ToList(); - if (alivePlayers.Count == 0) - { - TraitorCanSpawn = false; - return; - } - TraitorCanSpawn = true; - } - - public static void RemoveTasks(PlayerControl player) - { - foreach (var task in player.myTasks) - if (task.TryCast() != null) - { - var normalPlayerTask = task.Cast(); - - var updateArrow = normalPlayerTask.taskStep > 0; - - normalPlayerTask.taskStep = 0; - normalPlayerTask.Initialize(); - if (normalPlayerTask.TaskType == TaskTypes.PickUpTowels) - foreach (var console in UnityEngine.Object.FindObjectsOfType()) - console.Image.color = Color.white; - normalPlayerTask.taskStep = 0; - if (normalPlayerTask.TaskType == TaskTypes.UploadData) - normalPlayerTask.taskStep = 1; - if ((normalPlayerTask.TaskType == TaskTypes.EmptyGarbage || normalPlayerTask.TaskType == TaskTypes.EmptyChute) - && (GameOptionsManager.Instance.currentNormalGameOptions.MapId == 0 || - GameOptionsManager.Instance.currentNormalGameOptions.MapId == 3 || - GameOptionsManager.Instance.currentNormalGameOptions.MapId == 4)) - normalPlayerTask.taskStep = 1; - if (updateArrow) - normalPlayerTask.UpdateArrow(); - - var taskInfo = player.Data.FindTaskById(task.Id); - taskInfo.Complete = false; - } - } - public static void ArsonistLastKiller(PlayerControl deadPlayer) - { - var alives = PlayerControl.AllPlayerControls.ToArray() - .Where(x => !x.Data.IsDead && !x.Data.Disconnected && x != deadPlayer).ToList(); - foreach (var player in alives) - { - if (player.Data.IsImpostor() || player.Is(Faction.NeutralKilling)) return; - } - var role = Role.GetRole(PlayerControl.LocalPlayer); - role.LastKiller = true; - return; - } - } -} diff --git a/source/Patches/GhostRoleClick.cs b/source/Patches/GhostRoleClick.cs index bf2025bde..6f94ae34c 100644 --- a/source/Patches/GhostRoleClick.cs +++ b/source/Patches/GhostRoleClick.cs @@ -22,6 +22,7 @@ public static void Prefix(PlayerControl __instance) { var role = Role.GetRole(__instance); role.Caught = true; + role.Player.Exiled(); var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CatchPhantom, SendOption.Reliable, -1); writer.Write(role.Player.PlayerId); @@ -36,6 +37,7 @@ public static void Prefix(PlayerControl __instance) { var role = Role.GetRole(__instance); role.Caught = true; + role.Player.Exiled(); var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.CatchHaunter, SendOption.Reliable, -1); writer.Write(role.Player.PlayerId); diff --git a/source/Patches/HudUpdate.cs b/source/Patches/HudUpdate.cs new file mode 100644 index 000000000..f57d95acf --- /dev/null +++ b/source/Patches/HudUpdate.cs @@ -0,0 +1,63 @@ +using HarmonyLib; +using UnityEngine; +using System; +using Object = UnityEngine.Object; +using AmongUs.GameOptions; +using TownOfUs.Roles; + +namespace TownOfUs.Patches +{ + [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] + public static class HudUpdate + { + private static GameObject ZoomButton; + public static bool Zooming; + private static Vector3 Pos; + + public static void Postfix(HudManager __instance) + { + if (!ZoomButton) + { + ZoomButton = Object.Instantiate(__instance.MapButton.gameObject, __instance.MapButton.transform.parent); + ZoomButton.GetComponent().OnClick = new(); + ZoomButton.GetComponent().OnClick.AddListener(new Action(Zoom)); + } + + Pos = __instance.MapButton.transform.localPosition + new Vector3(0.02f, -0.66f, 0f); + var dead = false; + if (Utils.ShowDeadBodies) + { + if (PlayerControl.LocalPlayer.Is(RoleEnum.Haunter)) + { + var haunter = Role.GetRole(PlayerControl.LocalPlayer); + if (haunter.Caught) dead = true; + } + else if (PlayerControl.LocalPlayer.Is(RoleEnum.Phantom)) + { + var phantom = Role.GetRole(PlayerControl.LocalPlayer); + if (phantom.Caught) dead = true; + } + else dead = true; + } + ZoomButton.SetActive(!MeetingHud.Instance && dead && AmongUsClient.Instance.GameState == InnerNet.InnerNetClient.GameStates.Started + && GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.Normal); + ZoomButton.transform.localPosition = Pos; + ZoomButton.GetComponent().sprite = Zooming ? TownOfUs.ZoomPlusButton : TownOfUs.ZoomMinusButton; + } + + public static void Zoom() + { + Zooming = !Zooming; + var size = Zooming ? 12f : 3f; + Camera.main.orthographicSize = size; + + foreach (var cam in Camera.allCameras) + { + if (cam?.gameObject.name == "UI Camera") + cam.orthographicSize = size; + } + + ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height); + } + } +} \ No newline at end of file diff --git a/source/Patches/ImpostorRoles/TraitorMod/RepickTraitor.cs b/source/Patches/ImpostorRoles/TraitorMod/RepickTraitor.cs new file mode 100644 index 000000000..f8c45e7ee --- /dev/null +++ b/source/Patches/ImpostorRoles/TraitorMod/RepickTraitor.cs @@ -0,0 +1,34 @@ +using HarmonyLib; +using System.Linq; +using Hazel; +using UnityEngine; + +namespace TownOfUs.ImpostorRoles.TraitorMod +{ + [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] + public class RepickTraitor + { + private static void Postfix(HudManager __instance) + { + if (PlayerControl.AllPlayerControls.Count <= 1) return; + if (PlayerControl.LocalPlayer == null) return; + if (PlayerControl.LocalPlayer.Data == null) return; + if (PlayerControl.LocalPlayer != SetTraitor.WillBeTraitor) return; + if (PlayerControl.LocalPlayer.Is(Faction.Impostors)) return; + if (!PlayerControl.LocalPlayer.Data.IsDead) return; + var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && + !x.Is(ModifierEnum.Lover) && !x.Data.IsDead && !x.Data.Disconnected && !x.IsExeTarget()).ToList(); + if (toChooseFrom.Count == 0) return; + var rand = Random.RandomRangeInt(0, toChooseFrom.Count); + var pc = toChooseFrom[rand]; + + SetTraitor.WillBeTraitor = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetTraitor, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + return; + } + } +} diff --git a/source/Patches/ImpostorRoles/TraitorMod/SetTraitor.cs b/source/Patches/ImpostorRoles/TraitorMod/SetTraitor.cs new file mode 100644 index 000000000..b95fb06cd --- /dev/null +++ b/source/Patches/ImpostorRoles/TraitorMod/SetTraitor.cs @@ -0,0 +1,202 @@ +using HarmonyLib; +using Hazel; +using TownOfUs.Roles; +using System.Linq; +using TownOfUs.CrewmateRoles.InvestigatorMod; +using TownOfUs.CrewmateRoles.SnitchMod; +using TownOfUs.Extensions; +using UnityEngine; +using Reactor.Utilities; +using TownOfUs.Patches; +using AmongUs.GameOptions; +using TownOfUs.CrewmateRoles.ImitatorMod; + +namespace TownOfUs.ImpostorRoles.TraitorMod +{ + [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] + public static class AirshipExileController_WrapUpAndSpawn + { + public static void Postfix(AirshipExileController __instance) => SetTraitor.ExileControllerPostfix(__instance); + } + + [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] + public class SetTraitor + { + public static PlayerControl WillBeTraitor; + public static Sprite Sprite => TownOfUs.Arrow; + + public static void ExileControllerPostfix(ExileController __instance) + { + var exiled = __instance.exiled?.Object; + var alives = PlayerControl.AllPlayerControls.ToArray() + .Where(x => !x.Data.IsDead && !x.Data.Disconnected).ToList(); + foreach (var player in alives) + { + if (player.Data.IsImpostor() || ((player.Is(RoleEnum.Glitch) || player.Is(RoleEnum.Juggernaut) + || player.Is(RoleEnum.Arsonist) || player.Is(RoleEnum.Plaguebearer) || player.Is(RoleEnum.Pestilence) + || player.Is(RoleEnum.Werewolf)) && CustomGameOptions.NeutralKillingStopsTraitor)) + { + return; + } + } + if (PlayerControl.LocalPlayer.Data.IsDead || exiled == PlayerControl.LocalPlayer) return; + if (alives.Count < CustomGameOptions.LatestSpawn) return; + if (PlayerControl.LocalPlayer != WillBeTraitor) return; + + if (!PlayerControl.LocalPlayer.Is(RoleEnum.Traitor)) + { + if (PlayerControl.LocalPlayer.Is(RoleEnum.Snitch)) + { + var snitchRole = Role.GetRole(PlayerControl.LocalPlayer); + snitchRole.ImpArrows.DestroyAll(); + snitchRole.SnitchArrows.Values.DestroyAll(); + snitchRole.SnitchArrows.Clear(); + CompleteTask.Postfix(PlayerControl.LocalPlayer); + } + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Investigator)) Footprint.DestroyAll(Role.GetRole(PlayerControl.LocalPlayer)); + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Engineer)) + { + var engineerRole = Role.GetRole(PlayerControl.LocalPlayer); + Object.Destroy(engineerRole.UsesText); + } + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Tracker)) + { + var trackerRole = Role.GetRole(PlayerControl.LocalPlayer); + trackerRole.TrackerArrows.Values.DestroyAll(); + trackerRole.TrackerArrows.Clear(); + Object.Destroy(trackerRole.UsesText); + } + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Transporter)) + { + var transporterRole = Role.GetRole(PlayerControl.LocalPlayer); + Object.Destroy(transporterRole.UsesText); + } + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Veteran)) + { + var veteranRole = Role.GetRole(PlayerControl.LocalPlayer); + Object.Destroy(veteranRole.UsesText); + } + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Medium)) + { + var medRole = Role.GetRole(PlayerControl.LocalPlayer); + medRole.MediatedPlayers.Values.DestroyAll(); + medRole.MediatedPlayers.Clear(); + } + + if (PlayerControl.LocalPlayer.Is(RoleEnum.Trapper)) + { + var trapperRole = Role.GetRole(PlayerControl.LocalPlayer); + Object.Destroy(trapperRole.UsesText); + } + + if (PlayerControl.LocalPlayer == StartImitate.ImitatingPlayer) StartImitate.ImitatingPlayer = null; + + var oldRole = Role.GetRole(PlayerControl.LocalPlayer); + var killsList = (oldRole.CorrectKills, oldRole.IncorrectKills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); + Role.RoleDictionary.Remove(PlayerControl.LocalPlayer.PlayerId); + var role = new Traitor(PlayerControl.LocalPlayer); + role.formerRole = oldRole.RoleType; + role.CorrectKills = killsList.CorrectKills; + role.IncorrectKills = killsList.IncorrectKills; + role.CorrectAssassinKills = killsList.CorrectAssassinKills; + role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; + role.RegenTask(); + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.TraitorSpawn, SendOption.Reliable, -1); + AmongUsClient.Instance.FinishRpcImmediately(writer); + + TurnImp(PlayerControl.LocalPlayer); + } + } + + public static void TurnImp(PlayerControl player) + { + player.Data.Role.TeamType = RoleTeamTypes.Impostor; + RoleManager.Instance.SetRole(player, RoleTypes.Impostor); + player.SetKillTimer(GameOptionsManager.Instance.currentNormalGameOptions.KillCooldown); + + System.Console.WriteLine("PROOF I AM IMP VANILLA ROLE: " + player.Data.Role.IsImpostor); + + foreach (var player2 in PlayerControl.AllPlayerControls) + { + if (player2.Data.IsImpostor() && PlayerControl.LocalPlayer.Data.IsImpostor()) + { + player2.nameText().color = Patches.Colors.Impostor; + } + } + + if (CustomGameOptions.TraitorCanAssassin) + { + var writer2 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetAssassin, SendOption.Reliable, -1); + writer2.Write(player.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer2); + } + + if (PlayerControl.LocalPlayer.PlayerId == player.PlayerId) + { + DestroyableSingleton.Instance.KillButton.gameObject.SetActive(true); + Coroutines.Start(Utils.FlashCoroutine(Color.red, 3f)); + } + + foreach (var snitch in Role.GetRoles(RoleEnum.Snitch)) + { + var snitchRole = (Snitch)snitch; + if (snitchRole.TasksDone && PlayerControl.LocalPlayer.Is(RoleEnum.Snitch) && CustomGameOptions.SnitchSeesTraitor) + { + var gameObj = new GameObject(); + var arrow = gameObj.AddComponent(); + gameObj.transform.parent = PlayerControl.LocalPlayer.gameObject.transform; + var renderer = gameObj.AddComponent(); + renderer.sprite = Sprite; + arrow.image = renderer; + gameObj.layer = 5; + snitchRole.SnitchArrows.Add(player.PlayerId, arrow); + } + else if (snitchRole.Revealed && PlayerControl.LocalPlayer.Is(RoleEnum.Traitor) && CustomGameOptions.SnitchSeesTraitor) + { + var gameObj = new GameObject(); + var arrow = gameObj.AddComponent(); + gameObj.transform.parent = PlayerControl.LocalPlayer.gameObject.transform; + var renderer = gameObj.AddComponent(); + renderer.sprite = Sprite; + arrow.image = renderer; + gameObj.layer = 5; + snitchRole.ImpArrows.Add(arrow); + } + } + + foreach (var haunter in Role.GetRoles(RoleEnum.Haunter)) + { + var haunterRole = (Haunter)haunter; + if (haunterRole.Revealed && PlayerControl.LocalPlayer.Is(RoleEnum.Traitor)) + { + var gameObj = new GameObject(); + var arrow = gameObj.AddComponent(); + gameObj.transform.parent = PlayerControl.LocalPlayer.gameObject.transform; + var renderer = gameObj.AddComponent(); + renderer.sprite = Sprite; + arrow.image = renderer; + gameObj.layer = 5; + haunterRole.ImpArrows.Add(arrow); + } + } + } + + public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); + + [HarmonyPatch(typeof(Object), nameof(Object.Destroy), new System.Type[] { typeof(GameObject) })] + public static void Prefix(GameObject obj) + { + if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; + if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); + } + } +} \ No newline at end of file diff --git a/source/Patches/MeetingHud_Start.cs b/source/Patches/MeetingHud_Start.cs index 0250db956..52e8bfd8b 100644 --- a/source/Patches/MeetingHud_Start.cs +++ b/source/Patches/MeetingHud_Start.cs @@ -2,6 +2,8 @@ using Object = UnityEngine.Object; using Hazel; using Reactor.Utilities.Extensions; +using UnityEngine; +using TownOfUs.Patches; namespace TownOfUs { @@ -16,6 +18,17 @@ public static void Postfix(MeetingHud __instance) { player.MyPhysics.ResetAnimState(); } + + HudUpdate.Zooming = false; + Camera.main.orthographicSize = 3f; + + foreach (var cam in Camera.allCameras) + { + if (cam?.gameObject.name == "UI Camera") + cam.orthographicSize = 3f; + } + + ResolutionManager.ResolutionChanged.Invoke((float)Screen.width / Screen.height); } } diff --git a/source/Patches/Modifiers/AssassinMod/AssassinKill.cs b/source/Patches/Modifiers/AssassinMod/AssassinKill.cs index 1525fc650..37c929644 100644 --- a/source/Patches/Modifiers/AssassinMod/AssassinKill.cs +++ b/source/Patches/Modifiers/AssassinMod/AssassinKill.cs @@ -252,35 +252,10 @@ public static void MurderPlayer( } } - if (ExilePatch.HaunterOn && ExilePatch.WillBeHaunter == null) - { - if (player.Is(Faction.Crewmates) && !player.Is(ModifierEnum.Lover)) - { - ExilePatch.WillBeHaunter = player; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); - writer.Write(player.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - - if (ExilePatch.PhantomOn && ExilePatch.WillBePhantom == null) - { - if ((player.Is(Faction.NeutralOther) || player.Is(Faction.NeutralKilling)) && !player.Is(ModifierEnum.Lover)) - { - ExilePatch.WillBePhantom = player; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); - writer.Write(player.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - meetingHud.CheckForEndVoting(); } - ExilePatch.AssassinatedPlayers.Add(player); - ExilePatch.CheckTraitorSpawn(player); + AddHauntPatch.AssassinatedPlayers.Add(player); } } } diff --git a/source/Patches/Modifiers/LoversMod/Chat.cs b/source/Patches/Modifiers/LoversMod/Chat.cs index 7fbcb63d3..f21f5f745 100644 --- a/source/Patches/Modifiers/LoversMod/Chat.cs +++ b/source/Patches/Modifiers/LoversMod/Chat.cs @@ -1,9 +1,20 @@ +using System; using HarmonyLib; namespace TownOfUs.Modifiers.LoversMod { public static class Chat { + private static DateTime MeetingStartTime = DateTime.MinValue; + + [HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.Start))] + public class MeetingStart + { + public static void Prefix(MeetingHud __instance) + { + MeetingStartTime = DateTime.UtcNow; + } + } [HarmonyPatch(typeof(ChatController), nameof(ChatController.AddChat))] public static class AddChat { @@ -12,8 +23,13 @@ public static bool Prefix(ChatController __instance, [HarmonyArgument(0)] Player if (__instance != HudManager.Instance.Chat) return true; var localPlayer = PlayerControl.LocalPlayer; if (localPlayer == null) return true; - return MeetingHud.Instance != null || LobbyBehaviour.Instance != null || localPlayer.Data.IsDead || - localPlayer.IsLover() || sourcePlayer.PlayerId == PlayerControl.LocalPlayer.PlayerId; + Boolean shouldSeeMessage = localPlayer.Data.IsDead || localPlayer.IsLover() || + sourcePlayer.PlayerId == PlayerControl.LocalPlayer.PlayerId; + if (DateTime.UtcNow - MeetingStartTime < TimeSpan.FromSeconds(1)) + { + return shouldSeeMessage; + } + return MeetingHud.Instance != null || LobbyBehaviour.Instance != null || shouldSeeMessage; } } diff --git a/source/Patches/Modifiers/LoversMod/Die.cs b/source/Patches/Modifiers/LoversMod/Die.cs new file mode 100644 index 000000000..6f74080be --- /dev/null +++ b/source/Patches/Modifiers/LoversMod/Die.cs @@ -0,0 +1,35 @@ +using HarmonyLib; +using TownOfUs.CrewmateRoles.AltruistMod; +using TownOfUs.Roles.Modifiers; +using TownOfUs.Roles; + +namespace TownOfUs.Modifiers.LoversMod +{ + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Die))] + public class Die + { + public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] DeathReason reason) + { + __instance.Data.IsDead = true; + + var flag3 = __instance.IsLover() && CustomGameOptions.BothLoversDie; + if (!flag3) return true; + var otherLover = Modifier.GetModifier(__instance).OtherLover.Player; + if (otherLover.Data.IsDead) return true; + + if (reason == DeathReason.Exile) + { + KillButtonTarget.DontRevive = __instance.PlayerId; + if (!otherLover.Is(RoleEnum.Pestilence)) otherLover.Exiled(); + } + else if (AmongUsClient.Instance.AmHost && !otherLover.Is(RoleEnum.Pestilence)) Utils.RpcMurderPlayer(otherLover, otherLover); + if (otherLover.Is(RoleEnum.Sheriff)) + { + var sheriff = Role.GetRole(otherLover); + sheriff.IncorrectKills -= 1; + } + + return true; + } + } +} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/ArsonistMod/ExilePatch.cs b/source/Patches/NeutralRoles/ArsonistMod/ExilePatch.cs new file mode 100644 index 000000000..37de998e9 --- /dev/null +++ b/source/Patches/NeutralRoles/ArsonistMod/ExilePatch.cs @@ -0,0 +1,49 @@ +using HarmonyLib; +using TownOfUs.Roles; +using System.Linq; +using TownOfUs.Extensions; +using UnityEngine; +using System; +using TownOfUs.Patches; + +namespace TownOfUs.NeutralRoles.ArsonistMod +{ + [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] + public static class AirshipExileController_WrapUpAndSpawn + { + public static void Postfix(AirshipExileController __instance) => SetLastKillerBool.ExileControllerPostfix(__instance); + } + + [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] + public class SetLastKillerBool + { + + public static void ExileControllerPostfix(ExileController __instance) + { + var exiled = __instance.exiled?.Object; + if (!PlayerControl.LocalPlayer.Is(RoleEnum.Arsonist)) return; + var alives = PlayerControl.AllPlayerControls.ToArray() + .Where(x => !x.Data.IsDead && !x.Data.Disconnected).ToList(); + foreach (var player in alives) + { + if (player.Data.IsImpostor() || player.Is(RoleEnum.Glitch) || player.Is(RoleEnum.Juggernaut) + || player.Is(RoleEnum.Plaguebearer) || player.Is(RoleEnum.Pestilence) || player.Is(RoleEnum.Werewolf)) + { + return; + } + } + var role = Role.GetRole(PlayerControl.LocalPlayer); + role.LastKiller = true; + return; + } + + public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); + + [HarmonyPatch(typeof(UnityEngine.Object), nameof(UnityEngine.Object.Destroy), new Type[] { typeof(GameObject) })] + public static void Prefix(GameObject obj) + { + if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; + if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); + } + } +} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/ExecutionerMod/NoButtons.cs b/source/Patches/NeutralRoles/ExecutionerMod/NoButtons.cs deleted file mode 100644 index cfde757b9..000000000 --- a/source/Patches/NeutralRoles/ExecutionerMod/NoButtons.cs +++ /dev/null @@ -1,24 +0,0 @@ -using HarmonyLib; - -namespace TownOfUs.NeutralRoles.ExecutionerMod -{ - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetRole))] - public class NoButtons - { - public static void Postfix() - { - if (!CustomGameOptions.ExecutionerButton) - if (PlayerControl.LocalPlayer.Is(RoleEnum.Executioner)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; - } - } - - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Start))] - public class NoButtonsHost - { - public static void Postfix() - { - if (!CustomGameOptions.ExecutionerButton) - if (PlayerControl.LocalPlayer.Is(RoleEnum.Executioner)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; - } - } -} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/ExecutionerMod/VoteOut.cs b/source/Patches/NeutralRoles/ExecutionerMod/VoteOut.cs new file mode 100644 index 000000000..3c7d64f3c --- /dev/null +++ b/source/Patches/NeutralRoles/ExecutionerMod/VoteOut.cs @@ -0,0 +1,20 @@ +using HarmonyLib; +using TownOfUs.Roles; + +namespace TownOfUs.NeutralRoles.ExecutionerMod +{ + [HarmonyPatch(typeof(ExileController), nameof(ExileController.Begin))] + internal class MeetingExiledEnd + { + private static void Postfix(ExileController __instance) + { + var exiled = __instance.exiled; + if (exiled == null) return; + var player = exiled.Object; + + foreach (var role in Role.GetRoles(RoleEnum.Executioner)) + if (player.PlayerId == ((Executioner)role).target.PlayerId) + ((Executioner)role).Wins(); + } + } +} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/JesterMod/NoButtons.cs b/source/Patches/NeutralRoles/JesterMod/NoButtons.cs deleted file mode 100644 index 346f5e113..000000000 --- a/source/Patches/NeutralRoles/JesterMod/NoButtons.cs +++ /dev/null @@ -1,24 +0,0 @@ -using HarmonyLib; - -namespace TownOfUs.NeutralRoles.JesterMod -{ - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetRole))] - public class NoButtons - { - public static void Postfix() - { - if (!CustomGameOptions.JesterButton) - if (PlayerControl.LocalPlayer.Is(RoleEnum.Jester)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; - } - } - - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Start))] - public class NoButtonsHost - { - public static void Postfix() - { - if (!CustomGameOptions.JesterButton) - if (PlayerControl.LocalPlayer.Is(RoleEnum.Jester)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; - } - } -} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/JesterMod/VoteOut.cs b/source/Patches/NeutralRoles/JesterMod/VoteOut.cs new file mode 100644 index 000000000..234130ae9 --- /dev/null +++ b/source/Patches/NeutralRoles/JesterMod/VoteOut.cs @@ -0,0 +1,20 @@ +using HarmonyLib; +using TownOfUs.Roles; + +namespace TownOfUs.NeutralRoles.JesterMod +{ + [HarmonyPatch(typeof(ExileController), nameof(ExileController.Begin))] + internal class MeetingExiledEnd + { + private static void Postfix(ExileController __instance) + { + var exiled = __instance.exiled; + if (exiled == null) return; + var player = exiled.Object; + + var role = Role.GetRole(player); + if (role == null) return; + if (role.RoleType == RoleEnum.Jester) ((Jester)role).Wins(); + } + } +} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/PhantomMod/RepickPhantom.cs b/source/Patches/NeutralRoles/PhantomMod/RepickPhantom.cs new file mode 100644 index 000000000..74a3779e0 --- /dev/null +++ b/source/Patches/NeutralRoles/PhantomMod/RepickPhantom.cs @@ -0,0 +1,58 @@ +using HarmonyLib; +using System.Linq; +using Hazel; +using UnityEngine; + +namespace TownOfUs.NeutralRoles.PhantomMod +{ + [HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))] + public class RepickPhantom + { + private static void Postfix(HudManager __instance) + { + if (PlayerControl.AllPlayerControls.Count <= 1) return; + if (PlayerControl.LocalPlayer == null) return; + if (PlayerControl.LocalPlayer.Data == null) return; + if (PlayerControl.LocalPlayer != SetPhantom.WillBePhantom) return; + if (PlayerControl.LocalPlayer.Data.IsDead) return; + var toChooseFrom = PlayerControl.AllPlayerControls.ToArray().Where(x => !x.Is(Faction.Crewmates) && !x.Is(Faction.Impostors) && !x.Is(ModifierEnum.Lover) && x.Data.IsDead && !x.Data.Disconnected).ToList(); + if (!PlayerControl.LocalPlayer.Is(Faction.NeutralKilling) && !PlayerControl.LocalPlayer.Is(Faction.NeutralOther)) + { + var toChooseFromAlive = PlayerControl.AllPlayerControls.ToArray().Where(x => (x.Is(Faction.NeutralKilling) || x.Is(Faction.NeutralOther)) && !x.Is(ModifierEnum.Lover) && !x.Data.Disconnected).ToList(); + if (toChooseFromAlive.Count == 0) + { + SetPhantom.WillBePhantom = null; + + var writer2 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); + writer2.Write(byte.MaxValue); + AmongUsClient.Instance.FinishRpcImmediately(writer2); + } + else + { + var rand2 = Random.RandomRangeInt(0, toChooseFromAlive.Count); + var pc2 = toChooseFromAlive[rand2]; + + SetPhantom.WillBePhantom = pc2; + + var writer3 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); + writer3.Write(pc2.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer3); + } + return; + } + if (toChooseFrom.Count == 0) return; + var rand = Random.RandomRangeInt(0, toChooseFrom.Count); + var pc = toChooseFrom[rand]; + + SetPhantom.WillBePhantom = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + return; + } + } +} \ No newline at end of file diff --git a/source/Patches/NeutralRoles/PhantomMod/SetPhantom.cs b/source/Patches/NeutralRoles/PhantomMod/SetPhantom.cs new file mode 100644 index 000000000..84e43b8be --- /dev/null +++ b/source/Patches/NeutralRoles/PhantomMod/SetPhantom.cs @@ -0,0 +1,86 @@ +using System; +using HarmonyLib; +using Hazel; +using TownOfUs.Roles; +using UnityEngine; +using Object = UnityEngine.Object; +using Random = UnityEngine.Random; +using TownOfUs.Patches; + +namespace TownOfUs.NeutralRoles.PhantomMod +{ + [HarmonyPatch(typeof(AirshipExileController), nameof(AirshipExileController.WrapUpAndSpawn))] + public static class AirshipExileController_WrapUpAndSpawn + { + public static void Postfix(AirshipExileController __instance) => SetPhantom.ExileControllerPostfix(__instance); + } + + [HarmonyPatch(typeof(ExileController), nameof(ExileController.WrapUp))] + public class SetPhantom + { + public static PlayerControl WillBePhantom; + public static Vector2 StartPosition; + + public static void ExileControllerPostfix(ExileController __instance) + { + if (WillBePhantom == null) return; + var exiled = __instance.exiled?.Object; + if (!WillBePhantom.Data.IsDead && (exiled.Is(Faction.NeutralKilling) || exiled.Is(Faction.NeutralOther)) && !exiled.IsLover()) WillBePhantom = exiled; + if (exiled == WillBePhantom && exiled.Is(RoleEnum.Jester)) return; + if (WillBePhantom.Data.Disconnected) return; + if (!WillBePhantom.Data.IsDead && WillBePhantom != exiled) return; + + if (!WillBePhantom.Is(RoleEnum.Phantom)) + { + var oldRole = Role.GetRole(WillBePhantom); + var killsList = (oldRole.Kills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); + Role.RoleDictionary.Remove(WillBePhantom.PlayerId); + if (PlayerControl.LocalPlayer == WillBePhantom) + { + var role = new Phantom(PlayerControl.LocalPlayer); + role.Kills = killsList.Kills; + role.CorrectAssassinKills = killsList.CorrectAssassinKills; + role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; + role.RegenTask(); + } + else + { + var role = new Phantom(WillBePhantom); + role.Kills = killsList.Kills; + role.CorrectAssassinKills = killsList.CorrectAssassinKills; + role.IncorrectAssassinKills = killsList.IncorrectAssassinKills; + } + + Utils.RemoveTasks(WillBePhantom); + if (!PlayerControl.LocalPlayer.Is(RoleEnum.Haunter)) WillBePhantom.MyPhysics.ResetMoveState(); + + WillBePhantom.gameObject.layer = LayerMask.NameToLayer("Players"); + } + + if (PlayerControl.LocalPlayer != WillBePhantom) return; + + if (Role.GetRole(PlayerControl.LocalPlayer).Caught) return; + var startingVent = + ShipStatus.Instance.AllVents[Random.RandomRangeInt(0, ShipStatus.Instance.AllVents.Count)]; + + var writer2 = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPos, SendOption.Reliable, -1); + writer2.Write(PlayerControl.LocalPlayer.PlayerId); + writer2.Write(startingVent.transform.position.x); + writer2.Write(startingVent.transform.position.y + 0.3636f); + AmongUsClient.Instance.FinishRpcImmediately(writer2); + + PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(new Vector2(startingVent.transform.position.x, startingVent.transform.position.y + 0.3636f)); + PlayerControl.LocalPlayer.MyPhysics.RpcEnterVent(startingVent.Id); + } + + public static void Postfix(ExileController __instance) => ExileControllerPostfix(__instance); + + [HarmonyPatch(typeof(Object), nameof(Object.Destroy), new Type[] { typeof(GameObject) })] + public static void Prefix(GameObject obj) + { + if (!SubmergedCompatibility.Loaded || GameOptionsManager.Instance.currentNormalGameOptions.MapId != 5) return; + if (obj.name.Contains("ExileCutscene")) ExileControllerPostfix(ExileControllerPatch.lastExiled); + } + } +} \ No newline at end of file diff --git a/source/Patches/NoButtons.cs b/source/Patches/NoButtons.cs new file mode 100644 index 000000000..e23f6e8bd --- /dev/null +++ b/source/Patches/NoButtons.cs @@ -0,0 +1,32 @@ +using HarmonyLib; + +namespace TownOfUs.Patches +{ + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetRole))] + public class NoButtons + { + public static void Postfix() + { + if (!CustomGameOptions.JesterButton) + if (PlayerControl.LocalPlayer.Is(RoleEnum.Jester)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; + if (!CustomGameOptions.ExecutionerButton) + if (PlayerControl.LocalPlayer.Is(RoleEnum.Executioner)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; + if (!CustomGameOptions.SwapperButton) + if (PlayerControl.LocalPlayer.Is(RoleEnum.Swapper)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; + } + } + + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.Start))] + public class NoButtonsHost + { + public static void Postfix() + { + if (!CustomGameOptions.JesterButton) + if (PlayerControl.LocalPlayer.Is(RoleEnum.Jester)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; + if (!CustomGameOptions.ExecutionerButton) + if (PlayerControl.LocalPlayer.Is(RoleEnum.Executioner)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; + if (!CustomGameOptions.SwapperButton) + if (PlayerControl.LocalPlayer.Is(RoleEnum.Swapper)) PlayerControl.LocalPlayer.RemainingEmergencies = 0; + } + } +} \ No newline at end of file diff --git a/source/Patches/Roles/Phantom.cs b/source/Patches/Roles/Phantom.cs index a29ec48ca..4889996b1 100644 --- a/source/Patches/Roles/Phantom.cs +++ b/source/Patches/Roles/Phantom.cs @@ -45,6 +45,7 @@ public void Fade() color.a = 0.07f + velocity / Player.MyPhysics.GhostSpeed * 0.13f; color.a = Mathf.Lerp(color.a, 0, distPercent); + if (Player.GetCustomOutfitType() != CustomPlayerOutfitType.PlayerNameOnly) { Player.SetOutfit(CustomPlayerOutfitType.PlayerNameOnly, new GameData.PlayerOutfit() @@ -56,7 +57,6 @@ public void Fade() PlayerName = "" }); } - Player.myRend().color = color; Player.nameText().color = Color.clear; Player.cosmetics.colorBlindText.color = Color.clear; diff --git a/source/Patches/Roles/Role.cs b/source/Patches/Roles/Role.cs index 412f7c764..988a423e6 100644 --- a/source/Patches/Roles/Role.cs +++ b/source/Patches/Roles/Role.cs @@ -12,7 +12,7 @@ using Random = UnityEngine.Random; using TownOfUs.Extensions; using AmongUs.GameOptions; -using TownOfUs.Patches; +using TownOfUs.ImpostorRoles.TraitorMod; namespace TownOfUs.Roles { @@ -638,7 +638,13 @@ public static bool Prefix(LogicGameFlowNormal __instance) var roleIsEnd = role.NeutralWin(__instance); var modifier = Modifier.GetModifier(role.Player); bool modifierIsEnd = true; - var traitorIsEnd = !ExilePatch.TraitorCanSpawn; + var alives = PlayerControl.AllPlayerControls.ToArray().Where(x => !x.Data.IsDead && !x.Data.Disconnected).ToList(); + var impsAlive = PlayerControl.AllPlayerControls.ToArray().Where(x => !x.Data.IsDead && !x.Data.Disconnected && x.Data.IsImpostor()).ToList(); + var traitorIsEnd = true; + if (SetTraitor.WillBeTraitor != null) + { + traitorIsEnd = SetTraitor.WillBeTraitor.Data.IsDead || SetTraitor.WillBeTraitor.Data.Disconnected || alives.Count < CustomGameOptions.LatestSpawn || impsAlive.Count * 2 >= alives.Count; + } if (modifier != null) modifierIsEnd = modifier.ModifierWin(__instance); if (!roleIsEnd || !modifierIsEnd || !traitorIsEnd) result = false; diff --git a/source/Patches/RpcHandling.cs b/source/Patches/RpcHandling.cs index 14d104262..7812bc4a4 100644 --- a/source/Patches/RpcHandling.cs +++ b/source/Patches/RpcHandling.cs @@ -18,6 +18,9 @@ using TownOfUs.NeutralRoles.GuardianAngelMod; using TownOfUs.ImpostorRoles.MinerMod; using TownOfUs.CrewmateRoles.HaunterMod; +using TownOfUs.NeutralRoles.PhantomMod; +using TownOfUs.ImpostorRoles.TraitorMod; +using TownOfUs.CrewmateRoles.ImitatorMod; using TownOfUs.Roles; using TownOfUs.Roles.Cultist; using TownOfUs.Roles.Modifiers; @@ -27,7 +30,6 @@ using PerformKillButton = TownOfUs.NeutralRoles.AmnesiacMod.PerformKillButton; using Random = UnityEngine.Random; //using Il2CppSystem; using TownOfUs.Patches; -using TownOfUs.CrewmateRoles.ImitatorMod; using AmongUs.GameOptions; namespace TownOfUs @@ -44,6 +46,9 @@ public static class RpcHandling private static readonly List<(Type, int, int)> ButtonModifiers = new List<(Type, int, int)>(); private static readonly List<(Type, int, int)> AssassinModifiers = new List<(Type, int, int)>(); private static readonly List<(Type, CustomRPC, int)> AssassinAbility = new List<(Type, CustomRPC, int)>(); + private static bool PhantomOn; + private static bool HaunterOn; + private static bool TraitorOn; internal static bool Check(int probability) { @@ -296,7 +301,70 @@ private static void GenEachRole(List infected) Role.GenModifier(type, canHaveModifier.TakeFirst(), id); } - var exeTargets = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && !x.Is(ModifierEnum.Lover) && !x.Is(RoleEnum.Mayor) && !x.Is(RoleEnum.Swapper) && !x.Is(RoleEnum.Vigilante)).ToList(); + + var toChooseFromCrew = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && !x.Is(ModifierEnum.Lover)).ToList(); + if (TraitorOn && toChooseFromCrew.Count != 0) + { + var rand = Random.RandomRangeInt(0, toChooseFromCrew.Count); + var pc = toChooseFromCrew[rand]; + + SetTraitor.WillBeTraitor = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetTraitor, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + else + { + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetTraitor, SendOption.Reliable, -1); + writer.Write(byte.MaxValue); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + + if (HaunterOn && toChooseFromCrew.Count != 0) + { + var rand = Random.RandomRangeInt(0, toChooseFromCrew.Count); + var pc = toChooseFromCrew[rand]; + + SetHaunter.WillBeHaunter = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + else + { + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); + writer.Write(byte.MaxValue); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + + var toChooseFromNeut = PlayerControl.AllPlayerControls.ToArray().Where(x => (x.Is(Faction.NeutralOther) || x.Is(Faction.NeutralKilling)) && !x.Is(ModifierEnum.Lover)).ToList(); + if (PhantomOn && toChooseFromNeut.Count != 0) + { + var rand = Random.RandomRangeInt(0, toChooseFromNeut.Count); + var pc = toChooseFromNeut[rand]; + + SetPhantom.WillBePhantom = pc; + + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); + writer.Write(pc.PlayerId); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + else + { + var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, + (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); + writer.Write(byte.MaxValue); + AmongUsClient.Instance.FinishRpcImmediately(writer); + } + + var exeTargets = PlayerControl.AllPlayerControls.ToArray().Where(x => x.Is(Faction.Crewmates) && !x.Is(ModifierEnum.Lover) && !x.Is(RoleEnum.Mayor) && !x.Is(RoleEnum.Swapper) && !x.Is(RoleEnum.Vigilante) && x != SetTraitor.WillBeTraitor).ToList(); foreach (var role in Role.GetRoles(RoleEnum.Executioner)) { var exe = (Executioner)role; @@ -763,7 +831,8 @@ public static void Postfix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) StartImitate.ImitatingPlayer = null; KillButtonTarget.DontRevive = byte.MaxValue; ReviveHudManagerUpdate.DontRevive = byte.MaxValue; - ExilePatch.AssassinatedPlayers.Clear(); + AddHauntPatch.AssassinatedPlayers.Clear(); + HudUpdate.Zooming = false; break; case CustomRPC.JanitorClean: @@ -966,15 +1035,6 @@ public static void Postfix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) case CustomRPC.Transport: Coroutines.Start(Transporter.TransportPlayers(reader.ReadByte(), reader.ReadByte(), reader.ReadBoolean())); break; - case CustomRPC.SetDelayRoles: - ExilePatch.PhantomOn = reader.ReadBoolean(); - ExilePatch.HaunterOn = reader.ReadBoolean(); - ExilePatch.TraitorOn = reader.ReadBoolean(); - ExilePatch.WillBePhantom = null; - ExilePatch.WillBeHaunter = null; - ExilePatch.WillBeTraitor = null; - ExilePatch.TraitorCanSpawn = false; - break; case CustomRPC.SetUntransportable: if (PlayerControl.LocalPlayer.Is(RoleEnum.Transporter)) { @@ -1156,44 +1216,48 @@ public static void Postfix([HarmonyArgument(0)] byte callId, [HarmonyArgument(1) break; case CustomRPC.SetPhantom: readByte = reader.ReadByte(); - ExilePatch.WillBePhantom = readByte == byte.MaxValue ? null : Utils.PlayerById(readByte); + SetPhantom.WillBePhantom = readByte == byte.MaxValue ? null : Utils.PlayerById(readByte); break; case CustomRPC.CatchPhantom: var phantomPlayer = Utils.PlayerById(reader.ReadByte()); Role.GetRole(phantomPlayer).Caught = true; if (PlayerControl.LocalPlayer == phantomPlayer) HudManager.Instance.AbilityButton.gameObject.SetActive(true); + phantomPlayer.Exiled(); break; case CustomRPC.PhantomWin: Role.GetRole(Utils.PlayerById(reader.ReadByte())).CompletedTasks = true; break; case CustomRPC.SetHaunter: readByte = reader.ReadByte(); - ExilePatch.WillBeHaunter = readByte == byte.MaxValue ? null : Utils.PlayerById(readByte); + SetHaunter.WillBeHaunter = readByte == byte.MaxValue ? null : Utils.PlayerById(readByte); break; case CustomRPC.CatchHaunter: var haunterPlayer = Utils.PlayerById(reader.ReadByte()); Role.GetRole(haunterPlayer).Caught = true; if (PlayerControl.LocalPlayer == haunterPlayer) HudManager.Instance.AbilityButton.gameObject.SetActive(true); + haunterPlayer.Exiled(); break; case CustomRPC.HaunterFinished: HighlightImpostors.UpdateMeeting(MeetingHud.Instance); break; case CustomRPC.SetTraitor: readByte = reader.ReadByte(); - ExilePatch.WillBeTraitor = Utils.PlayerById(readByte); - var traitor = ExilePatch.WillBeTraitor; + SetTraitor.WillBeTraitor = readByte == byte.MaxValue ? null : Utils.PlayerById(readByte); + break; + case CustomRPC.TraitorSpawn: + var traitor = SetTraitor.WillBeTraitor; if (traitor == StartImitate.ImitatingPlayer) StartImitate.ImitatingPlayer = null; var oldRole = Role.GetRole(traitor); - var killsList3 = (oldRole.CorrectKills, oldRole.IncorrectKills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); + var killsList = (oldRole.CorrectKills, oldRole.IncorrectKills, oldRole.CorrectAssassinKills, oldRole.IncorrectAssassinKills); Role.RoleDictionary.Remove(traitor.PlayerId); var traitorRole = new Traitor(traitor); traitorRole.formerRole = oldRole.RoleType; - traitorRole.CorrectKills = killsList3.CorrectKills; - traitorRole.IncorrectKills = killsList3.IncorrectKills; - traitorRole.CorrectAssassinKills = killsList3.CorrectAssassinKills; - traitorRole.IncorrectAssassinKills = killsList3.IncorrectAssassinKills; + traitorRole.CorrectKills = killsList.CorrectKills; + traitorRole.IncorrectKills = killsList.IncorrectKills; + traitorRole.CorrectAssassinKills = killsList.CorrectAssassinKills; + traitorRole.IncorrectAssassinKills = killsList.IncorrectAssassinKills; traitorRole.RegenTask(); - ExilePatch.SpawnTraitor(traitor); + SetTraitor.TurnImp(traitor); break; case CustomRPC.Escape: var escapist = Utils.PlayerById(reader.ReadByte()); @@ -1259,7 +1323,7 @@ public static void Postfix() ExileControllerPatch.lastExiled = null; PatchKillTimer.GameStarted = false; StartImitate.ImitatingPlayer = null; - ExilePatch.AssassinatedPlayers.Clear(); + AddHauntPatch.AssassinatedPlayers.Clear(); CrewmateRoles.Clear(); NeutralNonKillingRoles.Clear(); NeutralKillingRoles.Clear(); @@ -1274,6 +1338,7 @@ public static void Postfix() Murder.KilledPlayers.Clear(); KillButtonTarget.DontRevive = byte.MaxValue; ReviveHudManagerUpdate.DontRevive = byte.MaxValue; + HudUpdate.Zooming = false; var startWriter = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte) CustomRPC.Start, SendOption.Reliable, -1); @@ -1283,34 +1348,16 @@ public static void Postfix() if (CustomGameOptions.GameMode == GameMode.Classic || CustomGameOptions.GameMode == GameMode.AllAny) { - ExilePatch.PhantomOn = Check(CustomGameOptions.PhantomOn); - ExilePatch.HaunterOn = Check(CustomGameOptions.HaunterOn); - ExilePatch.TraitorOn = Check(CustomGameOptions.TraitorOn); - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetDelayRoles, SendOption.Reliable, -1); - writer.Write(ExilePatch.PhantomOn); - writer.Write(ExilePatch.HaunterOn); - writer.Write(ExilePatch.TraitorOn); - AmongUsClient.Instance.FinishRpcImmediately(writer); + PhantomOn = Check(CustomGameOptions.PhantomOn); + HaunterOn = Check(CustomGameOptions.HaunterOn); + TraitorOn = Check(CustomGameOptions.TraitorOn); } else { - ExilePatch.PhantomOn = false; - ExilePatch.HaunterOn = false; - ExilePatch.TraitorOn = false; - - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetDelayRoles, SendOption.Reliable, -1); - writer.Write(false); - writer.Write(false); - writer.Write(false); - AmongUsClient.Instance.FinishRpcImmediately(writer); + PhantomOn = false; + HaunterOn = false; + TraitorOn = false; } - ExilePatch.WillBePhantom = null; - ExilePatch.WillBeHaunter = null; - ExilePatch.WillBeTraitor = null; - ExilePatch.TraitorCanSpawn = false; if (CustomGameOptions.GameMode == GameMode.Classic || CustomGameOptions.GameMode == GameMode.AllAny) { diff --git a/source/Patches/SubmergedCompatibility.cs b/source/Patches/SubmergedCompatibility.cs index 926f8d5b3..0854adee5 100644 --- a/source/Patches/SubmergedCompatibility.cs +++ b/source/Patches/SubmergedCompatibility.cs @@ -323,7 +323,7 @@ public static void GhostRoleBegin() (byte)CustomRPC.SetPos, SendOption.Reliable, -1); writer2.Write(PlayerControl.LocalPlayer.PlayerId); writer2.Write(startingVent.transform.position.x); - writer2.Write(startingVent.transform.position.y); + writer2.Write(startingVent.transform.position.y + 0.3636f); AmongUsClient.Instance.FinishRpcImmediately(writer2); PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(new Vector2(startingVent.transform.position.x, startingVent.transform.position.y + 0.3636f)); @@ -347,7 +347,7 @@ public static void GhostRoleBegin() (byte)CustomRPC.SetPos, SendOption.Reliable, -1); writer2.Write(PlayerControl.LocalPlayer.PlayerId); writer2.Write(startingVent.transform.position.x); - writer2.Write(startingVent.transform.position.y); + writer2.Write(startingVent.transform.position.y + 0.3636f); AmongUsClient.Instance.FinishRpcImmediately(writer2); PlayerControl.LocalPlayer.NetTransform.RpcSnapTo(new Vector2(startingVent.transform.position.x, startingVent.transform.position.y + 0.3636f)); diff --git a/source/Patches/Utils.cs b/source/Patches/Utils.cs index 5bad71283..3d55a7a27 100644 --- a/source/Patches/Utils.cs +++ b/source/Patches/Utils.cs @@ -477,8 +477,6 @@ public static void MurderPlayer(PlayerControl killer, PlayerControl target, bool if (killer == PlayerControl.LocalPlayer) SoundManager.Instance.PlaySound(PlayerControl.LocalPlayer.KillSfx, false, 0.8f); - ExilePatch.CheckTraitorSpawn(target); - if (!killer.Is(Faction.Crewmates) && killer != target && GameOptionsManager.Instance.CurrentGameOptions.GameMode == GameModes.Normal) Role.GetRole(killer).Kills += 1; @@ -504,30 +502,6 @@ public static void MurderPlayer(PlayerControl killer, PlayerControl target, bool else if (killer != target) veteran.IncorrectKills += 1; } - if (AmongUsClient.Instance.AmHost && ExilePatch.HaunterOn && ExilePatch.WillBeHaunter == null) - { - if (target.Is(Faction.Crewmates) && !target.Is(ModifierEnum.Lover)) - { - ExilePatch.WillBeHaunter = target; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetHaunter, SendOption.Reliable, -1); - writer.Write(target.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - - if (AmongUsClient.Instance.AmHost && ExilePatch.PhantomOn && ExilePatch.WillBePhantom == null) - { - if ((target.Is(Faction.NeutralOther) || target.Is(Faction.NeutralKilling)) && !target.Is(ModifierEnum.Lover)) - { - ExilePatch.WillBePhantom = target; - var writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, - (byte)CustomRPC.SetPhantom, SendOption.Reliable, -1); - writer.Write(target.PlayerId); - AmongUsClient.Instance.FinishRpcImmediately(writer); - } - } - target.gameObject.layer = LayerMask.NameToLayer("Ghost"); target.Visible = false; @@ -603,18 +577,6 @@ public static void MurderPlayer(PlayerControl killer, PlayerControl target, bool if (MeetingHud.Instance) target.Exiled(); - if (target.IsLover() && CustomGameOptions.BothLoversDie) - { - var otherLover = Modifier.GetModifier(target).OtherLover.Player; - if (!otherLover.Is(RoleEnum.Pestilence) && !otherLover.Data.IsDead - && !otherLover.Data.Disconnected) MurderPlayer(otherLover, otherLover, true); - if (otherLover.Is(RoleEnum.Sheriff)) - { - var sheriff = Role.GetRole(otherLover); - sheriff.IncorrectKills -= 1; - } - } - if (!killer.AmOwner) return; if (target.Is(ModifierEnum.Bait)) @@ -881,6 +843,40 @@ public static IEnumerator FlashCoroutine(Color color, float waitfor = 1f, float return first.Zip(second, (x, y) => (x, y)); } + public static void RemoveTasks(PlayerControl player) + { + var totalTasks = GameOptionsManager.Instance.currentNormalGameOptions.NumCommonTasks + GameOptionsManager.Instance.currentNormalGameOptions.NumLongTasks + + GameOptionsManager.Instance.currentNormalGameOptions.NumShortTasks; + + + foreach (var task in player.myTasks) + if (task.TryCast() != null) + { + var normalPlayerTask = task.Cast(); + + var updateArrow = normalPlayerTask.taskStep > 0; + + normalPlayerTask.taskStep = 0; + normalPlayerTask.Initialize(); + if (normalPlayerTask.TaskType == TaskTypes.PickUpTowels) + foreach (var console in Object.FindObjectsOfType()) + console.Image.color = Color.white; + normalPlayerTask.taskStep = 0; + if (normalPlayerTask.TaskType == TaskTypes.UploadData) + normalPlayerTask.taskStep = 1; + if ((normalPlayerTask.TaskType == TaskTypes.EmptyGarbage || normalPlayerTask.TaskType == TaskTypes.EmptyChute) + && (GameOptionsManager.Instance.currentNormalGameOptions.MapId == 0 || + GameOptionsManager.Instance.currentNormalGameOptions.MapId == 3 || + GameOptionsManager.Instance.currentNormalGameOptions.MapId == 4)) + normalPlayerTask.taskStep = 1; + if (updateArrow) + normalPlayerTask.UpdateArrow(); + + var taskInfo = player.Data.FindTaskById(task.Id); + taskInfo.Complete = false; + } + } + public static void DestroyAll(this IEnumerable listie) { foreach (var item in listie) diff --git a/source/Resources/Hats/hats0451.png b/source/Resources/Hats/hats0451.png new file mode 100644 index 000000000..5009766d0 Binary files /dev/null and b/source/Resources/Hats/hats0451.png differ diff --git a/source/Resources/Hats/hats0452.png b/source/Resources/Hats/hats0452.png new file mode 100644 index 000000000..24ec04038 Binary files /dev/null and b/source/Resources/Hats/hats0452.png differ diff --git a/source/Resources/Hats/hats0453.png b/source/Resources/Hats/hats0453.png new file mode 100644 index 000000000..cb83caa32 Binary files /dev/null and b/source/Resources/Hats/hats0453.png differ diff --git a/source/Resources/Hats/hats0454.png b/source/Resources/Hats/hats0454.png new file mode 100644 index 000000000..57753172f Binary files /dev/null and b/source/Resources/Hats/hats0454.png differ diff --git a/source/Resources/Hats/hats0455.png b/source/Resources/Hats/hats0455.png new file mode 100644 index 000000000..6a31f91b6 Binary files /dev/null and b/source/Resources/Hats/hats0455.png differ diff --git a/source/Resources/Hats/hats0456.png b/source/Resources/Hats/hats0456.png new file mode 100644 index 000000000..027285b7f Binary files /dev/null and b/source/Resources/Hats/hats0456.png differ diff --git a/source/Resources/Hats/hats0457.png b/source/Resources/Hats/hats0457.png new file mode 100644 index 000000000..5940ff827 Binary files /dev/null and b/source/Resources/Hats/hats0457.png differ diff --git a/source/Resources/Hats/hats0458.png b/source/Resources/Hats/hats0458.png new file mode 100644 index 000000000..6b3e90bea Binary files /dev/null and b/source/Resources/Hats/hats0458.png differ diff --git a/source/Resources/Hats/hats0459.png b/source/Resources/Hats/hats0459.png new file mode 100644 index 000000000..afe53822d Binary files /dev/null and b/source/Resources/Hats/hats0459.png differ diff --git a/source/Resources/Hats/metadata.json b/source/Resources/Hats/metadata.json index f5e027604..1629a6025 100644 --- a/source/Resources/Hats/metadata.json +++ b/source/Resources/Hats/metadata.json @@ -2255,6 +2255,51 @@ "name": "Pikabubs hat", "artist": "Ophidian" }, + { + "id": "hats0451", + "name": "Slayed hat", + "artist": "Sarinjin" + }, + { + "id": "hats0452", + "name": "BlackCat hat", + "artist": "Ophidian" + }, + { + "id": "hats0453", + "name": "GingerCat hat", + "artist": "Ophidian" + }, + { + "id": "hats0454", + "name": "Crab hat", + "artist": "Ophidian" + }, + { + "id": "hats0455", + "name": "GooglyEyes hat", + "artist": "Ophidian" + }, + { + "id": "hats0456", + "name": "Qthulhu hat", + "artist": "Ophidian" + }, + { + "id": "hats0457", + "name": "Tiki hat", + "artist": "Ophidian" + }, + { + "id": "hats0458", + "name": "jb hat", + "artist": "Ophidian" + }, + { + "id": "hats0459", + "name": "WingsBodyBuilder hat", + "artist": "Ophidian" + }, { "id": "misc0000", "name": "ZeroXFusionz hat", diff --git a/source/Resources/HorseOff.png b/source/Resources/HorseOff.png deleted file mode 100644 index 051b1317b..000000000 Binary files a/source/Resources/HorseOff.png and /dev/null differ diff --git a/source/Resources/HorseOn.png b/source/Resources/HorseOn.png deleted file mode 100644 index f07930930..000000000 Binary files a/source/Resources/HorseOn.png and /dev/null differ diff --git a/source/Resources/Minus.png b/source/Resources/Minus.png new file mode 100644 index 000000000..292b92d92 Binary files /dev/null and b/source/Resources/Minus.png differ diff --git a/source/Resources/Plus.png b/source/Resources/Plus.png new file mode 100644 index 000000000..48ec6f872 Binary files /dev/null and b/source/Resources/Plus.png differ diff --git a/source/TownOfUs.cs b/source/TownOfUs.cs index 0db270043..f6efeded8 100644 --- a/source/TownOfUs.cs +++ b/source/TownOfUs.cs @@ -29,7 +29,7 @@ namespace TownOfUs public class TownOfUs : BasePlugin { public const string Id = "com.slushiegoose.townofus"; - public const string VersionString = "4.0.5"; + public const string VersionString = "4.0.6"; public static System.Version Version = System.Version.Parse(VersionString); public static Sprite JanitorClean; @@ -93,8 +93,9 @@ public class TownOfUs : BasePlugin public static Sprite UpdateTOUButton; public static Sprite UpdateSubmergedButton; - public static Sprite HorseEnabledImage; - public static Sprite HorseDisabledImage; + public static Sprite ZoomPlusButton; + public static Sprite ZoomMinusButton; + public static Vector3 ButtonPosition { get; private set; } = new Vector3(2.6f, 0.7f, -9f); private static DLoadImage _iCallLoadImage; @@ -175,8 +176,8 @@ public override void Load() UpdateTOUButton = CreateSprite("TownOfUs.Resources.UpdateToUButton.png"); UpdateSubmergedButton = CreateSprite("TownOfUs.Resources.UpdateSubmergedButton.png"); - HorseEnabledImage = CreateSprite("TownOfUs.Resources.HorseOn.png"); - HorseDisabledImage = CreateSprite("TownOfUs.Resources.HorseOff.png"); + ZoomPlusButton = CreateSprite("TownOfUs.Resources.Plus.png"); + ZoomMinusButton = CreateSprite("TownOfUs.Resources.Minus.png"); PalettePatch.Load(); ClassInjector.RegisterTypeInIl2Cpp(); diff --git a/source/TownOfUs.csproj b/source/TownOfUs.csproj index 6a374c6b1..5365ed750 100644 --- a/source/TownOfUs.csproj +++ b/source/TownOfUs.csproj @@ -1,7 +1,7 @@  net6.0 - 4.0.5 + 4.0.6 embedded latest