diff --git a/NewMod/Buttons/Overload/OverloadButton.cs b/NewMod/Buttons/Overload/OverloadButton.cs index c2352ce..87cba08 100644 --- a/NewMod/Buttons/Overload/OverloadButton.cs +++ b/NewMod/Buttons/Overload/OverloadButton.cs @@ -82,7 +82,7 @@ public class OverloadButton : CustomActionButton /// /// The icon displayed on the button. /// - public override LoadableAsset Sprite => absorbedSprite; + public override LoadableAsset Sprite => MiraAssets.Empty; /// /// Copies functionality and appearance from another role's button. diff --git a/NewMod/CustomRPC.cs b/NewMod/CustomRPC.cs index 88d1919..c340bf9 100644 --- a/NewMod/CustomRPC.cs +++ b/NewMod/CustomRPC.cs @@ -15,6 +15,7 @@ public enum CustomRPC WitnessTrap, NotifyChampion, SummonNPC, + RequestSummon, BeaconPulse, DeployZone } \ No newline at end of file diff --git a/NewMod/ModCompatibility.cs b/NewMod/ModCompatibility.cs index 0a037e5..ecfb158 100644 --- a/NewMod/ModCompatibility.cs +++ b/NewMod/ModCompatibility.cs @@ -52,18 +52,5 @@ public static void DisableRole(string roleName, string pluginGuid) } } } - public static bool IsRoleActive(string roleName) - { - foreach (var roles in RoleManager.Instance.AllRoles) - { - CustomRoleManager.GetCustomRoleBehaviour(roles.Role, out var customRole); - - if (customRole != null && customRole.RoleName.Equals(roleName, StringComparison.OrdinalIgnoreCase)) - { - return customRole.GetChance() > 0 && customRole.GetCount() > 0; - } - } - return false; - } } } diff --git a/NewMod/Modifiers/StickyModifier.cs b/NewMod/Modifiers/StickyModifier.cs index ab721ff..1d0382d 100644 --- a/NewMod/Modifiers/StickyModifier.cs +++ b/NewMod/Modifiers/StickyModifier.cs @@ -1,6 +1,9 @@ using System.Collections; using System.Collections.Generic; +using MiraAPI.Events; +using MiraAPI.Events.Vanilla.Gameplay; using MiraAPI.GameOptions; +using MiraAPI.Modifiers; using MiraAPI.Modifiers.Types; using NewMod.Options; using NewMod.Options.Modifiers; @@ -15,6 +18,7 @@ public class StickyModifier : GameModifier public override bool HideOnUi => false; public override bool ShowInFreeplay => true; public static List linkedPlayers = []; + public static bool _IsActive = false; public override int GetAmountPerGame() { return (int)OptionGroupSingleton.Instance.StickyAmount; @@ -29,8 +33,8 @@ public override int GetAssignmentChance() } public override string GetDescription() { - float distance = OptionGroupSingleton.Instance.StickyDistance.Value; - float duration = OptionGroupSingleton.Instance.StickyDuration.Value; + float distance = (int)OptionGroupSingleton.Instance.StickyDistance; + float duration = (int)OptionGroupSingleton.Instance.StickyDuration; return $"{ModifierName}: Pulls nearby players within {distance} units for {duration} seconds."; } @@ -38,53 +42,65 @@ public override void FixedUpdate() { base.FixedUpdate(); - if (!Player.CanMove) return; + if (_IsActive) return; + + if (!Player.CanMove || Player.Data.IsDead) return; foreach (var player in PlayerControl.AllPlayerControls) { - if (player == Player || linkedPlayers.Contains(player)) continue; + if (player == Player) continue; - float distance = OptionGroupSingleton.Instance.StickyDistance.Value; + float distance = (int)OptionGroupSingleton.Instance.StickyDistance; if (Vector2.Distance(player.GetTruePosition(), Player.GetTruePosition()) < distance) { + _IsActive = true; linkedPlayers.Add(player); Coroutines.Start(CoFollowStickyPlayer(player)); + break; } } } public IEnumerator CoFollowStickyPlayer(PlayerControl player) { - var info = new StickyState + float duration = (int)OptionGroupSingleton.Instance.StickyDuration; + float timer = 0f; + float pullStrength = (int)OptionGroupSingleton.Instance.PullStrength; + float stopDistance = 1f; + + while (timer < duration) { - StickyOwner = Player, - LinkedPlayer = player, - velocity = Vector3.zero, - }; + if (player.Data.IsDead || player.Data.Disconnected) break; - yield return HudManager.Instance.StartCoroutine( - Effects.Overlerp(0.5f, new System.Action((t) => - { - Vector3 targetPos = info.LinkedPlayer.transform.position; - Vector3 currentPos = info.StickyOwner.transform.position; + timer += Time.deltaTime; - info.LinkedPlayer.transform.position = Vector3.SmoothDamp( - targetPos, - currentPos, - ref info.velocity, - t - ); - }) - )); + var ownerPos = Player.transform.position; + var targetPos = player.transform.position; + float distance = Vector3.Distance(ownerPos, targetPos); + + if (distance > stopDistance) + { + Vector3 direction = (ownerPos - targetPos).normalized; + Vector3 leashPoint = ownerPos - (direction * stopDistance); + + player.transform.position = Vector3.Lerp(targetPos, leashPoint, Time.deltaTime * pullStrength); + } + yield return null; + } linkedPlayers.Remove(player); - } - } - class StickyState - { - public PlayerControl StickyOwner; - public PlayerControl LinkedPlayer; - public Vector3 velocity; + _IsActive = true; + + if (Player.AmOwner) + { + PlayerControl.LocalPlayer.RpcRemoveModifier(); + } + } + [RegisterEvent] + public static void OnRoundStart(RoundStartEvent evt) + { + linkedPlayers.Clear(); + } } } diff --git a/NewMod/NewMod.cs b/NewMod/NewMod.cs index 3aeaacf..4822c30 100644 --- a/NewMod/NewMod.cs +++ b/NewMod/NewMod.cs @@ -47,7 +47,7 @@ public override void Load() { Instance = this; AddComponent(); - ReactorCredits.Register(ReactorCredits.AlwaysShow); + ReactorCredits.Register("NewMod", "v1.2.9 Hotfix 1", true, ReactorCredits.AlwaysShow); Harmony.PatchAll(); NewModEventHandler.RegisterEventsLogs(); diff --git a/NewMod/Options/Modifiers/StickyModifierOptions.cs b/NewMod/Options/Modifiers/StickyModifierOptions.cs index 3654ec5..e997cbb 100644 --- a/NewMod/Options/Modifiers/StickyModifierOptions.cs +++ b/NewMod/Options/Modifiers/StickyModifierOptions.cs @@ -26,5 +26,14 @@ public class StickyModifierOptions : AbstractOptionGroup increment: 0.5f, suffixType: MiraNumberSuffixes.None ); + public ModdedNumberOption PullStrength { get; } = + new( + "Pull Strength", + 1f, + min: 1f, + max: 5f, + increment: 1f, + suffixType: MiraNumberSuffixes.None + ); } } diff --git a/NewMod/Options/ModifiersOptions.cs b/NewMod/Options/ModifiersOptions.cs index 6bccf5a..02aa181 100644 --- a/NewMod/Options/ModifiersOptions.cs +++ b/NewMod/Options/ModifiersOptions.cs @@ -12,24 +12,24 @@ public class ModifiersOptions : AbstractOptionGroup public override Color GroupColor => Color.blue; public override bool ShowInModifiersMenu => true; - [ModdedNumberOption("Sticky Amount", min:0f, max:6)] - public float StickyAmount { get; set; } = 10f; + [ModdedNumberOption("Sticky Amount", min:0f, max:2f)] + public float StickyAmount { get; set; } = 1f; public ModdedNumberOption StickyChance { get; } = new("Sticky Chance", 50f, 0, 100f, 10f, MiraNumberSuffixes.Percent) { Visible = () => OptionGroupSingleton.Instance.StickyAmount > 0 }; - [ModdedNumberOption("Drowsy Amount", min:0f, max:6f)] - public float DrowsyAmount { get; set; } = 10f; + [ModdedNumberOption("Drowsy Amount", min:0f, max:2f)] + public float DrowsyAmount { get; set; } = 1f; public ModdedNumberOption DrowsyChance { get; } =new("Drowsy Chance", 50f, 0, 100f, 10f, MiraNumberSuffixes.Percent) { Visible = () => OptionGroupSingleton.Instance.DrowsyAmount > 0f }; - [ModdedNumberOption("Adrenaline Amount", min:0f, max:6f)] - public float AdrenalineAmount { get; set; } = 10f; + [ModdedNumberOption("Adrenaline Amount", min:0f, max:2f)] + public float AdrenalineAmount { get; set; } = 1f; public ModdedNumberOption AdrenalineChance { get; } =new("Adrenaline Chance", 50f, 0, 100f, 10f, MiraNumberSuffixes.Percent) { diff --git a/NewMod/Patches/ChatPatch.cs b/NewMod/Patches/ChatPatch.cs new file mode 100644 index 0000000..b6c88ef --- /dev/null +++ b/NewMod/Patches/ChatPatch.cs @@ -0,0 +1,43 @@ +using AmongUs.Data; +using HarmonyLib; +using InnerNet; + +namespace NewMod.Patches +{ + [HarmonyPatch(typeof(ChatController), nameof(ChatController.SendChat))] + public static class ChatPatch + { + public static bool Prefix(ChatController __instance) + { + __instance.timeSinceLastMessage = 0f; + + if (__instance.quickChatMenu.CanSend) + { + __instance.SendQuickChat(); + } + else + { + if (__instance.quickChatMenu.IsOpen || string.IsNullOrWhiteSpace(__instance.freeChatField.Text) || DataManager.Settings.Multiplayer.ChatMode != QuickChatModes.FreeChatOrQuickChat) + { + return false; + } + __instance.SendFreeChat(); + } + + __instance.timeSinceLastMessage = 0f; + __instance.freeChatField.Clear(); + __instance.quickChatMenu.Clear(); + __instance.quickChatField.Clear(); + __instance.UpdateChatMode(); + + return false; + } + [HarmonyPatch(typeof(TextBoxTMP), nameof(TextBoxTMP.Start))] + [HarmonyPostfix] + public static void StartPostfix(TextBoxTMP __instance) + { + __instance.AllowSymbols = true; + __instance.allowAllCharacters = true; + } + } +} \ No newline at end of file diff --git a/NewMod/Patches/Compatibility/StartGamePatch.cs b/NewMod/Patches/Compatibility/StartGamePatch.cs index e5fce8c..6392857 100644 --- a/NewMod/Patches/Compatibility/StartGamePatch.cs +++ b/NewMod/Patches/Compatibility/StartGamePatch.cs @@ -1,6 +1,7 @@ using HarmonyLib; using MiraAPI.GameOptions; using NewMod.Options; +using NewMod.Utilities; namespace NewMod.Patches.Compatibility { @@ -15,8 +16,8 @@ public static bool Prefix(AmongUsClient __instance) if (!settings.AllowRevenantHitmanCombo) { - var hitman = ModCompatibility.IsRoleActive("Hitman"); - var revenant = ModCompatibility.IsRoleActive("Revenant"); + var hitman = Utils.IsRoleActive("Hitman"); + var revenant = Utils.IsRoleActive("Revenant"); if (hitman && revenant) { diff --git a/NewMod/Patches/RolePatch.cs b/NewMod/Patches/RolePatch.cs index 64f4099..94c010f 100644 --- a/NewMod/Patches/RolePatch.cs +++ b/NewMod/Patches/RolePatch.cs @@ -1,54 +1,65 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using AmongUs.GameOptions; using HarmonyLib; +using Hazel; using MiraAPI.GameOptions; using MiraAPI.Roles; using MiraAPI.Utilities; -using NewMod; using NewMod.Options; using NewMod.Roles; using Reactor.Utilities; using UnityEngine; -using Hazel; namespace NewMod.Patches { [HarmonyPatch(typeof(RoleManager), nameof(RoleManager.SelectRoles))] public static class SelectRolePatch { - public static bool Prefix(RoleManager __instance) + [HarmonyPostfix] + [HarmonyPriority(Priority.Last)] + public static void Postfix(RoleManager __instance) { - if (!AmongUsClient.Instance.AmHost) - return true; + if (!AmongUsClient.Instance.AmHost) return; + if (GameManager.Instance.IsHideAndSeek()) return; + + Coroutines.Start(CoAdjustNeutrals()); + } - Logger.Instance.LogMessage("-------------- SELECT ROLES: START --------------"); - Logger.Instance.LogMessage($"Running as host (clientId={AmongUsClient.Instance.ClientId})"); + private static IEnumerator CoAdjustNeutrals() + { + yield return null; + yield return new WaitForSeconds(0.05f); var opts = OptionGroupSingleton.Instance; int target = Mathf.RoundToInt(opts.TotalNeutrals); - Logger.Instance.LogMessage($"Settings -> TotalNeutrals={opts.TotalNeutrals} → target={target}, KeepCrewMajority={opts.KeepCrewMajority}, PreferVariety={opts.PreferVariety}"); - var allPlayers = GameData.Instance.AllPlayers.ToArray() - .Where(p => p?.Object && !p.IsDead && !p.Disconnected) + var allInfos = GameData.Instance.AllPlayers.ToArray() + .Where(p => p != null && p.Object != null && !p.Disconnected) .ToList(); - Logger.Instance.LogMessage($"Eligible players: {allPlayers.Count}"); + var allPlayers = allInfos.Select(p => p.Object).ToList(); + + Logger.Instance.LogMessage("-------------- NEUTRAL ADJUST: START --------------"); + Logger.Instance.LogMessage($"Players={allPlayers.Count}, TotalNeutrals={opts.TotalNeutrals} target={target}, KeepCrewMajority={opts.KeepCrewMajority}, PreferVariety={opts.PreferVariety}"); var neutrals = allPlayers - .Where(p => p?.Object?.Data?.Role is ICustomRole cr && cr is INewModRole nm && - (nm.Faction == NewModFaction.Apex || nm.Faction == NewModFaction.Entropy)) - .Select(p => p.Object) + .Where(pc => + { + var rb = pc.Data?.Role; + if (rb is ICustomRole cr && cr is INewModRole nm) + return nm.Faction == NewModFaction.Apex || nm.Faction == NewModFaction.Entropy; + return false; + }) .ToList(); - Logger.Instance.LogMessage($"Currently neutral (Apex/Entropy): {neutrals.Count}"); - if (opts.KeepCrewMajority) { - int crewCount = allPlayers.Count(p => + int crewCount = allPlayers.Count(pc => { - var rb = p?.Object?.Data?.Role; + var rb = pc.Data?.Role; if (rb == null) return false; return rb is CrewmateRole || (!rb.IsImpostor && rb.TeamType == RoleTeamTypes.Crewmate); }); @@ -60,41 +71,43 @@ public static bool Prefix(RoleManager __instance) } int have = neutrals.Count; + Logger.Instance.LogMessage($"Currently neutrals={have}"); + if (have == target) { - Logger.Instance.LogMessage("No change needed; exiting cleanly."); - Logger.Instance.LogMessage("-------------- SELECT ROLES: END (no-op) --------------"); - return false; + Logger.Instance.LogMessage("No change needed."); + Logger.Instance.LogMessage("-------------- NEUTRAL ADJUST: END (no-op) --------------"); + yield break; } if (have > target) { int remove = have - target; - Logger.Instance.LogMessage($"Too many neutrals; demoting {remove}"); - neutrals.Shuffle(); + Logger.Instance.LogMessage($"Too many neutrals, demoting {remove}"); + neutrals.Shuffle(); for (int i = 0; i < remove && i < neutrals.Count; i++) { - var ply = neutrals[i]; - if (ply == null) continue; + var pc = neutrals[i]; + if (pc == null) continue; - Logger.Instance.LogMessage($"→ Demoting {ply.Data.PlayerName} to Crewmate"); - ply.RpcSetRole(RoleTypes.Crewmate); + Logger.Instance.LogMessage($"→ Demoting {pc.Data.PlayerName} to Crewmate"); + pc.RpcSetRole(RoleTypes.Crewmate, true); } - Logger.Instance.LogMessage("Demotion complete."); - Logger.Instance.LogMessage("-------------- SELECT ROLES: END (demotions) --------------"); - return false; + Logger.Instance.LogMessage("-------------- NEUTRAL ADJUST: END (demotions) --------------"); + yield break; } int need = target - have; Logger.Instance.LogMessage($"Need to assign {need} more neutrals."); var crewElig = allPlayers - .Where(p => + .Where(pc => { - var rb = p?.Object?.Data?.Role; + var rb = pc.Data?.Role; if (rb == null) return false; + bool isCrew = rb is CrewmateRole || (!rb.IsImpostor && rb.TeamType == RoleTeamTypes.Crewmate); if (!isCrew) return false; @@ -103,16 +116,14 @@ public static bool Prefix(RoleManager __instance) return true; }) - .Select(p => p.Object) .ToList(); Logger.Instance.LogMessage($"Crew eligible for neutral conversion: {crewElig.Count}"); - if (crewElig.Count == 0) { - Logger.Instance.LogMessage("No eligible crew found; aborting neutral assignment."); - Logger.Instance.LogMessage("-------------- SELECT ROLES: END (no candidates) --------------"); - return false; + Logger.Instance.LogMessage("No eligible crew found, aborting."); + Logger.Instance.LogMessage("-------------- NEUTRAL ADJUST: END (no candidates) --------------"); + yield break; } var active = CustomRoleUtils.GetActiveRoles().ToList(); @@ -141,14 +152,15 @@ public static bool Prefix(RoleManager __instance) } Logger.Instance.LogMessage($"Built neutral candidate list: {candidates.Count}"); - if (candidates.Count == 0) { - Logger.Instance.LogMessage("No candidates available; exiting."); - return false; + Logger.Instance.LogMessage("No candidates available, exiting."); + Logger.Instance.LogMessage("-------------- NEUTRAL ADJUST: END --------------"); + yield break; } var picks = new List(); + if (opts.PreferVariety) { var ordered = candidates.OrderByDescending(x => x.Weight).ToList(); @@ -171,16 +183,12 @@ public static bool Prefix(RoleManager __instance) float total = available.Sum(c => c.Weight); float rnum = UnityEngine.Random.Range(0f, total); float acc = 0f; - var chosen = available.First(); + var chosen = available[0]; foreach (var c in available) { acc += c.Weight; - if (rnum <= acc) - { - chosen = c; - break; - } + if (rnum <= acc) { chosen = c; break; } } picks.Add(chosen.Role); @@ -199,19 +207,19 @@ public static bool Prefix(RoleManager __instance) foreach (var role in picks) { if (crewElig.Count == 0) break; + int idx = HashRandom.FastNext(crewElig.Count); var pc = crewElig[idx]; crewElig.RemoveAt(idx); var rt = (RoleTypes)RoleId.Get(role.GetType()); - Logger.Instance.LogMessage($"Assigning {role.GetType().Name} → {pc.Data.PlayerName}"); - pc.RpcSetRole(rt); + pc.RpcSetRole(rt, true); } Logger.Instance.LogMessage("Neutral assignment complete."); - Logger.Instance.LogMessage("-------------- SELECT ROLES: END --------------"); - return false; + Logger.Instance.LogMessage("-------------- NEUTRAL ADJUST: END --------------"); } + public struct Candidate { public ICustomRole Role; @@ -220,23 +228,17 @@ public struct Candidate public RoleTypes RoleType; } } - - // Inspired by https://github.com/AU-Avengers/TOU-Mira/blob/main/TownOfUs/Patches/RoleManagerPatches.cs#L747C3-L768C1 - [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RpcSetRole))] - public static class RpcSetRolePatch + // Thanks to:https://github.com/AU-Avengers/TOU-Mira/blob/main/TownOfUs/Patches/RoleManagerPatches.cs#L1070 + [HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.CoSetRole))] + public static class CoSetRoleOverridePatch { - public static bool Prefix(PlayerControl __instance, [HarmonyArgument(0)] RoleTypes roleType, [HarmonyArgument(1)] bool canOverrideRole = false) + [HarmonyPrefix] + public static void Prefix(PlayerControl __instance, [HarmonyArgument(0)] RoleTypes role, [HarmonyArgument(1)] bool canOverrideRole) { - if (AmongUsClient.Instance.AmClient) - __instance.StartCoroutine(__instance.CoSetRole(roleType, canOverrideRole)); - - var writer = AmongUsClient.Instance.StartRpcImmediately(__instance.NetId, (byte)RpcCalls.SetRole, SendOption.Reliable); - writer.Write((ushort)roleType); - writer.Write(canOverrideRole); - AmongUsClient.Instance.FinishRpcImmediately(writer); - - Logger.Instance.LogMessage($"RpcSetRole: {__instance.Data.PlayerName} ({roleType})"); - return false; + if (canOverrideRole) + { + __instance.roleAssigned = false; + } } } } diff --git a/NewMod/Patches/Roles/MeetingHudPatch.cs b/NewMod/Patches/Roles/MeetingHudPatch.cs index ad05f64..479f17d 100644 --- a/NewMod/Patches/Roles/MeetingHudPatch.cs +++ b/NewMod/Patches/Roles/MeetingHudPatch.cs @@ -1,17 +1,9 @@ -using System; -using UnityEngine; -using Object = UnityEngine.Object; -using UnityEngine.Events; using System.Collections.Generic; using HarmonyLib; using NewMod.Utilities; -using MiraAPI.Roles; -using MiraAPI.Hud; -using Reactor.Utilities; using System.Linq; using Il2CppInterop.Runtime.InteropTypes.Arrays; using AmongUs.GameOptions; -using NewMod.Roles.NeutralRoles; namespace NewMod.Patches.Roles { @@ -30,6 +22,8 @@ public static class MeetingHud_CoIntro_Patch { public static bool Prefix(ref Il2CppReferenceArray deadBodies) { + if (!Utils.IsRoleActive("Prankster")) return true; + List pranksterBodies = PranksterUtilities.FindAllPranksterBodies(); deadBodies = new Il2CppReferenceArray( deadBodies @@ -44,6 +38,8 @@ public static class MeetingHud_PopulateButtons_Patch { public static bool Prefix(MeetingHud __instance, byte reporter) { + if (!Utils.IsRoleActive("Prankster")) return true; + var fakeBodies = PranksterUtilities.FindAllPranksterBodies(); var realPlayers = GameData.Instance.AllPlayers .ToArray() diff --git a/NewMod/Patches/Roles/Visionary/VisionaryPatches.cs b/NewMod/Patches/Roles/Visionary/VisionaryPatches.cs index d96d924..de4be38 100644 --- a/NewMod/Patches/Roles/Visionary/VisionaryPatches.cs +++ b/NewMod/Patches/Roles/Visionary/VisionaryPatches.cs @@ -13,6 +13,8 @@ public static class VisionaryVentPatch [RegisterEvent] public static void OnEnterVent(EnterVentEvent evt) { + if (!Utils.IsRoleActive("The Visionary")) return; + PlayerControl player = evt.Player; var chancePercentage = (int)(0.2f * 100); @@ -31,6 +33,8 @@ public static void OnEnterVent(EnterVentEvent evt) [HarmonyPatch(typeof(PlayerPhysics), nameof(PlayerPhysics.RpcExitVent))] public static void Postfix(PlayerPhysics __instance, int ventId) { + if (!Utils.IsRoleActive("The Visionary")) return; + var chancePercentage = (int)(0.2f * 100); if (Helpers.CheckChance(chancePercentage)) { @@ -53,6 +57,8 @@ public static class VisionaryMurderPatch [RegisterEvent] public static void OnBeforeMurder(BeforeMurderEvent evt) { + if (!Utils.IsRoleActive("The Visionary")) return; + PlayerControl source = evt.Source; int chancePercentage = (int)(0.2f * 100); diff --git a/NewMod/Patches/StatsPopupPatch.cs b/NewMod/Patches/StatsPopupPatch.cs index f446d70..eaee3e1 100644 --- a/NewMod/Patches/StatsPopupPatch.cs +++ b/NewMod/Patches/StatsPopupPatch.cs @@ -14,7 +14,7 @@ namespace NewMod.Patches { public static class CustomStatsManager { - private static readonly string SavePath = Path.Combine(Application.consoleLogPath, "customStats.dat"); + private static readonly string SavePath = Path.Combine(Application.persistentDataPath, "customStats.dat"); public static Dictionary CustomRoleWins = new(); public static bool _loaded = false; public static void SaveCustomStats() @@ -74,6 +74,12 @@ public static void LoadCustomStats() ); using var reader = new BinaryReader(fs); + if (reader.BaseStream.Length == 0) + { + NewMod.Instance.Log.LogError("Stats file is empty."); + return; + } + int count = reader.ReadInt32(); for (int i = 0; i < count; i++) { diff --git a/NewMod/Roles/NeutralRoles/Tyrant.cs b/NewMod/Roles/NeutralRoles/Tyrant.cs index ad5e146..82eea6b 100644 --- a/NewMod/Roles/NeutralRoles/Tyrant.cs +++ b/NewMod/Roles/NeutralRoles/Tyrant.cs @@ -109,6 +109,8 @@ public enum ThroneOutcome { None, ChampionSideWin } [RegisterEvent] public static void OnAfterMurderEvent(AfterMurderEvent evt) { + if (!Utils.IsRoleActive("Tyrant")) return; + var tyrant = evt.Source.Data.Role as Tyrant; tyrant._kills++; @@ -185,18 +187,14 @@ public static IEnumerator CoShowTyrantForChampion(MeetingHud hud) [RegisterEvent] public static void OnHandleVote(HandleVoteEvent evt) { + if (!Utils.IsRoleActive("Tyrant")) return; + var voter = evt.VoteData.Owner; var allPlayers = PlayerControl.AllPlayerControls.ToArray(); foreach (var player in allPlayers) { - var role = player.Data?.Role; - if (role is not Tyrant tyrant) - { - continue; - } - if (voter.PlayerId != _championId) { continue; @@ -238,6 +236,8 @@ public static void OnHandleVote(HandleVoteEvent evt) [RegisterEvent] public static void OnProcessVotes(ProcessVotesEvent evt) { + if (!Utils.IsRoleActive("Tyrant")) return; + if (PendingBetrayals.Count == 0) return; var first = default(byte); diff --git a/NewMod/Utilities/Utils.cs b/NewMod/Utilities/Utils.cs index 498b518..8aead77 100644 --- a/NewMod/Utilities/Utils.cs +++ b/NewMod/Utilities/Utils.cs @@ -698,7 +698,6 @@ public static void RpcMissionSuccess(PlayerControl source, PlayerControl target) } } } - } [MethodRpc((uint)CustomRPC.MissionFails)] @@ -1179,5 +1178,18 @@ public static GameObject CreateCircle(string name, Vector3 pos, float radius, Co Coroutines.Start(CoroutinesHelper.DespawnCircle(go, duration)); return go; } + public static bool IsRoleActive(string roleName) + { + foreach (var roles in RoleManager.Instance.AllRoles) + { + CustomRoleManager.GetCustomRoleBehaviour(roles.Role, out var customRole); + + if (customRole != null && customRole.RoleName.Equals(roleName, System.StringComparison.OrdinalIgnoreCase)) + { + return customRole.GetChance() > 0 && customRole.GetCount() > 0; + } + } + return false; + } } }