From 636b9f9dbeb7f8bb67c7fb628b2bde7b953c02e3 Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Fri, 23 Feb 2024 17:39:57 +0100 Subject: [PATCH] Half way! (50%) --- Modules/CustomRolesHelper.cs | 5 +- .../PlayerGameOptionsSender.cs | 26 +- Modules/Utils.cs | 16 +- Patches/HudPatch.cs | 12 - Patches/PetActionsPatch.cs | 49 +--- Patches/PlayerContorolPatch.cs | 85 +------ Patches/TaskAssignPatch.cs | 20 +- Patches/onGameStartedPatch.cs | 4 +- Roles/Crewmate/CandleLighter.cs | 44 ++-- Roles/Crewmate/Divinator.cs | 13 +- Roles/Crewmate/Escort.cs | 20 +- Roles/Crewmate/Express.cs | 21 +- Roles/Crewmate/Farseer.cs | 68 ++--- Roles/Crewmate/Gaulois.cs | 20 +- Roles/Crewmate/Grenadier.cs | 117 +++++++++ Roles/Crewmate/Guardian.cs | 23 ++ Roles/Crewmate/GuessManager.cs | 20 +- Roles/Crewmate/Insight.cs | 19 +- Roles/Crewmate/Jailer.cs | 82 +++--- Roles/Crewmate/Judge.cs | 157 ++++++------ Roles/Crewmate/Lighter.cs | 109 ++++++++ Roles/Crewmate/ParityCop.cs | 234 +++++++++--------- Roles/Neutral/Glitch.cs | 121 +++++---- Roles/RoleBase.cs | 4 + main.cs | 6 +- 25 files changed, 716 insertions(+), 579 deletions(-) create mode 100644 Roles/Crewmate/Grenadier.cs create mode 100644 Roles/Crewmate/Guardian.cs create mode 100644 Roles/Crewmate/Lighter.cs diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 9ab4d5229..2b004590c 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -118,16 +118,14 @@ internal static class CustomRolesHelper CustomRoles.Farseer => new Farseer(), CustomRoles.Divinator => new Divinator(), CustomRoles.Gaulois => new Gaulois(), - CustomRoles.Glitch => new Glitch(), CustomRoles.Grenadier => new Grenadier(), - CustomRoles.GuessManager => new GuessManager(), + CustomRoles.GuessManager => new GuessManagerRole(), CustomRoles.Guardian => new Guardian(), CustomRoles.Ignitor => new Ignitor(), CustomRoles.Insight => new Insight(), CustomRoles.ParityCop => new ParityCop(), CustomRoles.Jailor => new Jailor(), CustomRoles.Judge => new Judge(), - CustomRoles.Needy => new Needy(), CustomRoles.Lighter => new Lighter(), CustomRoles.Lookout => new Lookout(), CustomRoles.Luckey => new Luckey(), @@ -197,6 +195,7 @@ internal static class CustomRolesHelper CustomRoles.Enderman => new Enderman(), CustomRoles.Executioner => new Executioner(), CustomRoles.Totocalcio => new Totocalcio(), + CustomRoles.Glitch => new Glitch(), CustomRoles.God => new God(), CustomRoles.FFF => new FFF(), CustomRoles.HeadHunter => new HeadHunter(), diff --git a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs index e8adef4f3..bcbd9edc2 100644 --- a/Modules/GameOptionsSender/PlayerGameOptionsSender.cs +++ b/Modules/GameOptionsSender/PlayerGameOptionsSender.cs @@ -40,7 +40,7 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender public static void SetDirtyToAllV3() { - foreach (var sender in AllSenders.OfType().Where(sender => !sender.IsDirty && sender.player.IsAlive() && ((Main.GrenadierBlinding.Count > 0 && (sender.player.GetCustomRole().IsImpostor() || (sender.player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))) || (Main.MadGrenadierBlinding.Count > 0 && !sender.player.GetCustomRole().IsImpostorTeam() && !sender.player.Is(CustomRoles.Madmate)))).ToArray()) + foreach (var sender in AllSenders.OfType().Where(sender => !sender.IsDirty && sender.player.IsAlive() && ((Main.GrenadierBlinding.Count > 0 && (sender.player.GetCustomRole().IsImpostor() || (sender.player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool()))) || (Grenadier.MadGrenadierBlinding.Count > 0 && !sender.player.GetCustomRole().IsImpostorTeam() && !sender.player.Is(CustomRoles.Madmate)))).ToArray()) { sender.SetDirty(); } @@ -378,20 +378,10 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender AURoleOptions.EngineerCooldown = Options.VeteranSkillCooldown.GetFloat(); AURoleOptions.EngineerInVentMaxTime = 1; break; - case CustomRoles.Grenadier: - if (Options.UsePets.GetBool()) break; - AURoleOptions.EngineerCooldown = Options.GrenadierSkillCooldown.GetFloat(); - AURoleOptions.EngineerInVentMaxTime = 1; - break; /* case CustomRoles.Flashbang: AURoleOptions.ShapeshifterCooldown = Options.FlashbangSkillCooldown.GetFloat(); AURoleOptions.ShapeshifterDuration = Options.FlashbangSkillDuration.GetFloat(); break; */ - case CustomRoles.Lighter: - if (Options.UsePets.GetBool()) break; - AURoleOptions.EngineerInVentMaxTime = 1; - AURoleOptions.EngineerCooldown = Options.LighterSkillCooldown.GetFloat(); - break; case CustomRoles.SecurityGuard: if (Options.UsePets.GetBool()) break; AURoleOptions.EngineerInVentMaxTime = 1; @@ -640,13 +630,14 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender opt.SetFloat(FloatOptionNames.CrewLightMod, Options.BewilderVision.GetFloat()); opt.SetFloat(FloatOptionNames.ImpostorLightMod, Options.BewilderVision.GetFloat()); } + if ( (Main.GrenadierBlinding.Count > 0 && - (player.GetCustomRole().IsImpostor() || - (player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool())) + (player.GetCustomRole().IsImpostor() || + (player.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool())) ) || ( - Main.MadGrenadierBlinding.Count > 0 && !player.GetCustomRole().IsImpostorTeam() && !player.Is(CustomRoles.Madmate)) - ) + Grenadier.MadGrenadierBlinding.Count > 0 && !player.GetCustomRole().IsImpostorTeam() && !player.Is(CustomRoles.Madmate)) + ) { { opt.SetVision(false); @@ -657,11 +648,6 @@ public class PlayerGameOptionsSender(PlayerControl player) : GameOptionsSender switch (player.GetCustomRole()) { - case CustomRoles.Lighter when Main.Lighter.Count > 0: - opt.SetVisionV2(); - if (Utils.IsActive(SystemTypes.Electrical)) opt.SetFloat(FloatOptionNames.CrewLightMod, Options.LighterVisionOnLightsOut.GetFloat() * 5); - else opt.SetFloat(FloatOptionNames.CrewLightMod, Options.LighterVisionNormal.GetFloat()); - break; case CustomRoles.Alchemist when Alchemist.VisionPotionActive: opt.SetVisionV2(); if (Utils.IsActive(SystemTypes.Electrical)) opt.SetFloat(FloatOptionNames.CrewLightMod, Alchemist.VisionOnLightsOut.GetFloat() * 5); diff --git a/Modules/Utils.cs b/Modules/Utils.cs index 92588dfd4..82d846ef1 100644 --- a/Modules/Utils.cs +++ b/Modules/Utils.cs @@ -875,10 +875,6 @@ public static class Utils ProgressText.Append(GetTaskCount(playerId, comms)); ProgressText.Append(GetAbilityUseLimitDisplay(playerId, Main.VeteranInProtect.ContainsKey(playerId))); break; - case CustomRoles.Grenadier: - ProgressText.Append(GetTaskCount(playerId, comms)); - ProgressText.Append(GetAbilityUseLimitDisplay(playerId, Main.GrenadierBlinding.ContainsKey(playerId))); - break; case CustomRoles.TimeMaster: ProgressText.Append(GetTaskCount(playerId, comms)); ProgressText.Append(GetAbilityUseLimitDisplay(playerId, Main.TimeMasterInProtect.ContainsKey(playerId))); @@ -894,10 +890,6 @@ public static class Utils ProgressText.Append(GetTaskCount(playerId, comms)); ProgressText.Append(GetAbilityUseLimitDisplay(playerId, Chameleon.IsInvis(playerId))); break; - case CustomRoles.Lighter: - ProgressText.Append(GetTaskCount(playerId, comms)); - ProgressText.Append(GetAbilityUseLimitDisplay(playerId, Main.Lighter.ContainsKey(playerId))); - break; case CustomRoles.SecurityGuard: ProgressText.Append(GetTaskCount(playerId, comms)); ProgressText.Append(GetAbilityUseLimitDisplay(playerId, Main.BlockSabo.ContainsKey(playerId))); @@ -2358,7 +2350,7 @@ public static class Utils break; case CustomRoles.Farseer: - if (Main.FarseerTimer.TryGetValue(seer.PlayerId, out var ar_kvp2) && ar_kvp2.PLAYER == target) + if (Farseer.FarseerTimer.TryGetValue(seer.PlayerId, out var ar_kvp2) && ar_kvp2.PLAYER == target) { TargetMark.Append($"○"); } @@ -2936,12 +2928,6 @@ public static class Utils case CustomRoles.Veteran: id.SetAbilityUseLimit(Options.VeteranSkillMaxOfUseage.GetInt()); break; - case CustomRoles.Grenadier: - id.SetAbilityUseLimit(Options.GrenadierSkillMaxOfUseage.GetInt()); - break; - case CustomRoles.Lighter: - id.SetAbilityUseLimit(Options.LighterSkillMaxOfUseage.GetInt()); - break; case CustomRoles.SecurityGuard: id.SetAbilityUseLimit(Options.SecurityGuardSkillMaxOfUseage.GetInt()); break; diff --git a/Patches/HudPatch.cs b/Patches/HudPatch.cs index 0afa7e7ec..c6e0ad249 100644 --- a/Patches/HudPatch.cs +++ b/Patches/HudPatch.cs @@ -390,18 +390,6 @@ class HudManagerPatch else __instance.AbilityButton.buttonLabelText.text = GetString("TimeMasterVentButtonText"); break; - case CustomRoles.Grenadier: - if (Options.UsePets.GetBool()) - __instance.PetButton.buttonLabelText.text = GetString("GrenadierVentButtonText"); - else - __instance.AbilityButton.buttonLabelText.text = GetString("GrenadierVentButtonText"); - break; - case CustomRoles.Lighter: - if (Options.UsePets.GetBool()) - __instance.PetButton.buttonLabelText.text = GetString("LighterVentButtonText"); - else - __instance.AbilityButton.buttonLabelText.text = GetString("LighterVentButtonText"); - break; case CustomRoles.SecurityGuard: if (Options.UsePets.GetBool()) __instance.PetButton.buttonLabelText.text = GetString("SecurityGuardVentButtonText"); diff --git a/Patches/PetActionsPatch.cs b/Patches/PetActionsPatch.cs index 5385babf7..ad0bdd9da 100644 --- a/Patches/PetActionsPatch.cs +++ b/Patches/PetActionsPatch.cs @@ -160,51 +160,6 @@ class ExternalRpcPetPatch if (!NameNotifyManager.Notice.ContainsKey(pc.PlayerId)) pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); } - break; - case CustomRoles.Grenadier: - if (Main.GrenadierBlinding.ContainsKey(pc.PlayerId) || Main.MadGrenadierBlinding.ContainsKey(pc.PlayerId)) break; - if (pc.GetAbilityUseLimit() >= 1) - { - if (pc.Is(CustomRoles.Madmate)) - { - Main.MadGrenadierBlinding.Remove(pc.PlayerId); - Main.MadGrenadierBlinding.Add(pc.PlayerId, Utils.TimeStamp); - Main.AllPlayerControls.Where(x => x.IsModClient()).Where(x => !x.GetCustomRole().IsImpostorTeam() && !x.Is(CustomRoles.Madmate)).Do(x => x.RPCPlayCustomSound("FlashBang")); - } - else - { - Main.GrenadierBlinding.Remove(pc.PlayerId); - Main.GrenadierBlinding.Add(pc.PlayerId, Utils.TimeStamp); - Main.AllPlayerControls.Where(x => x.IsModClient()).Where(x => x.GetCustomRole().IsImpostor() || (x.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool())).Do(x => x.RPCPlayCustomSound("FlashBang")); - } - - pc.RPCPlayCustomSound("FlashBang"); - pc.Notify(GetString("GrenadierSkillInUse"), Options.GrenadierSkillDuration.GetFloat()); - pc.RpcRemoveAbilityUse(); - Utils.MarkEveryoneDirtySettingsV3(); - } - else - { - if (!NameNotifyManager.Notice.ContainsKey(pc.PlayerId)) pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); - } - - break; - case CustomRoles.Lighter: - if (Main.Lighter.ContainsKey(pc.PlayerId)) break; - if (pc.GetAbilityUseLimit() >= 1) - { - Main.Lighter.Remove(pc.PlayerId); - Main.Lighter.Add(pc.PlayerId, Utils.TimeStamp); - pc.Notify(GetString("LighterSkillInUse"), Options.LighterSkillDuration.GetFloat()); - pc.RpcRemoveAbilityUse(); - pc.MarkDirtySettings(); - } - else - { - if (!NameNotifyManager.Notice.ContainsKey(pc.PlayerId)) - pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); - } - break; case CustomRoles.SecurityGuard: if (Main.BlockSabo.ContainsKey(pc.PlayerId)) break; @@ -355,9 +310,9 @@ class ExternalRpcPetPatch break; case CustomRoles.Farseer when hasKillTarget: pc.AddAbilityCD(Farseer.FarseerRevealTime.GetInt()); - if (!Main.isRevealed[(pc.PlayerId, target.PlayerId)] && !Main.FarseerTimer.ContainsKey(pc.PlayerId)) + if (!Main.isRevealed[(pc.PlayerId, target.PlayerId)] && !Farseer.FarseerTimer.ContainsKey(pc.PlayerId)) { - Main.FarseerTimer.TryAdd(pc.PlayerId, (target, 0f)); + Farseer.FarseerTimer.TryAdd(pc.PlayerId, (target, 0f)); Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: target, ForceLoop: true); RPC.SetCurrentRevealTarget(pc.PlayerId, target.PlayerId); } diff --git a/Patches/PlayerContorolPatch.cs b/Patches/PlayerContorolPatch.cs index 74fee0dde..a409b9dc3 100644 --- a/Patches/PlayerContorolPatch.cs +++ b/Patches/PlayerContorolPatch.cs @@ -445,9 +445,9 @@ class CheckMurderPatch return false; case CustomRoles.Farseer: killer.SetKillCooldown(Farseer.FarseerRevealTime.GetFloat()); - if (!Main.isRevealed[(killer.PlayerId, target.PlayerId)] && !Main.FarseerTimer.ContainsKey(killer.PlayerId)) + if (!Main.isRevealed[(killer.PlayerId, target.PlayerId)] && !Farseer.FarseerTimer.ContainsKey(killer.PlayerId)) { - Main.FarseerTimer.TryAdd(killer.PlayerId, (target, 0f)); + Farseer.FarseerTimer.TryAdd(killer.PlayerId, (target, 0f)); NotifyRoles(SpecifySeer: __instance, SpecifyTarget: target, ForceLoop: true); RPC.SetCurrentRevealTarget(killer.PlayerId, target.PlayerId); } @@ -720,8 +720,6 @@ class CheckMurderPatch case CustomRoles.Medic: Medic.IsDead(target); break; - case CustomRoles.Guardian when target.AllTasksCompleted(): - return false; case CustomRoles.Monarch when killer.Is(CustomRoles.Knighted): return false; case CustomRoles.WeaponMaster when WeaponMaster.OnAttack(): @@ -1506,7 +1504,7 @@ class ReportDeadBodyPatch Main.LastVotedPlayerInfo = null; Main.AllKillers.Clear(); Main.ArsonistTimer.Clear(); - if (Farseer.isEnable) Main.FarseerTimer.Clear(); + if (Farseer.isEnable) Farseer.FarseerTimer.Clear(); Puppeteer.PuppeteerList.Clear(); Puppeteer.PuppeteerDelayList.Clear(); Main.TaglockedList.Clear(); @@ -1516,7 +1514,7 @@ class ReportDeadBodyPatch Main.Lighter.Clear(); Main.BlockSabo.Clear(); Main.BlockedVents.Clear(); - Main.MadGrenadierBlinding.Clear(); + Grenadier.MadGrenadierBlinding.Clear(); if (Divinator.IsEnable) Divinator.didVote.Clear(); if (Oracle.IsEnable) Oracle.didVote.Clear(); if (Bloodhound.IsEnable) Bloodhound.Clear(); @@ -2135,36 +2133,6 @@ class FixedUpdatePatch Express.OnFixedUpdate(player); break; - case CustomRoles.Grenadier when GameStates.IsInTask: - if (Main.GrenadierBlinding.TryGetValue(playerId, out var gtime) && gtime + Options.GrenadierSkillDuration.GetInt() < now) - { - Main.GrenadierBlinding.Remove(playerId); - player.RpcResetAbilityCooldown(); - player.Notify(string.Format(GetString("GrenadierSkillStop"), (int)player.GetAbilityUseLimit())); - MarkEveryoneDirtySettingsV3(); - } - - if (Main.MadGrenadierBlinding.TryGetValue(playerId, out var mgtime) && mgtime + Options.GrenadierSkillDuration.GetInt() < now) - { - Main.MadGrenadierBlinding.Remove(playerId); - player.RpcResetAbilityCooldown(); - player.Notify(string.Format(GetString("GrenadierSkillStop"), (int)player.GetAbilityUseLimit())); - MarkEveryoneDirtySettingsV3(); - } - - break; - - case CustomRoles.Lighter when GameStates.IsInTask: - if (Main.Lighter.TryGetValue(playerId, out var ltime) && ltime + Options.LighterSkillDuration.GetInt() < now) - { - Main.Lighter.Remove(playerId); - player.RpcResetAbilityCooldown(); - player.Notify(GetString("LighterSkillStop")); - player.MarkDirtySettings(); - } - - break; - case CustomRoles.SecurityGuard when GameStates.IsInTask: if (Main.BlockSabo.TryGetValue(playerId, out var stime) && stime + Options.SecurityGuardSkillDuration.GetInt() < now) { @@ -2921,51 +2889,6 @@ class EnterVentPatch pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); } - break; - case CustomRoles.Grenadier when !Options.UsePets.GetBool(): - if (pc.GetAbilityUseLimit() >= 1) - { - if (pc.Is(CustomRoles.Madmate)) - { - Main.MadGrenadierBlinding.Remove(pc.PlayerId); - Main.MadGrenadierBlinding.Add(pc.PlayerId, TimeStamp); - Main.AllPlayerControls.Where(x => x.IsModClient()).Where(x => !x.GetCustomRole().IsImpostorTeam() && !x.Is(CustomRoles.Madmate)).Do(x => x.RPCPlayCustomSound("FlashBang")); - } - else - { - Main.GrenadierBlinding.Remove(pc.PlayerId); - Main.GrenadierBlinding.Add(pc.PlayerId, TimeStamp); - Main.AllPlayerControls.Where(x => x.IsModClient()).Where(x => x.GetCustomRole().IsImpostor() || (x.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool())).Do(x => x.RPCPlayCustomSound("FlashBang")); - } - - //pc.RpcGuardAndKill(pc); - pc.RPCPlayCustomSound("FlashBang"); - pc.Notify(GetString("GrenadierSkillInUse"), Options.GrenadierSkillDuration.GetFloat()); - pc.AddAbilityCD(); - pc.RpcRemoveAbilityUse(); - MarkEveryoneDirtySettingsV3(); - } - else - { - pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); - } - - break; - case CustomRoles.Lighter when !Options.UsePets.GetBool(): - if (pc.GetAbilityUseLimit() >= 1) - { - Main.Lighter.Remove(pc.PlayerId); - Main.Lighter.Add(pc.PlayerId, TimeStamp); - pc.Notify(GetString("LighterSkillInUse"), Options.LighterSkillDuration.GetFloat()); - pc.AddAbilityCD(); - pc.RpcRemoveAbilityUse(); - pc.MarkDirtySettings(); - } - else - { - pc.Notify(GetString("OutOfAbilityUsesDoMoreTasks")); - } - break; case CustomRoles.SecurityGuard when !Options.UsePets.GetBool(): if (pc.GetAbilityUseLimit() >= 1) diff --git a/Patches/TaskAssignPatch.cs b/Patches/TaskAssignPatch.cs index 7f1b7f398..2b3d146f9 100644 --- a/Patches/TaskAssignPatch.cs +++ b/Patches/TaskAssignPatch.cs @@ -3,6 +3,7 @@ using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using TOHE.Roles.AddOns.Crewmate; +using TOHE.Roles.Impostor; using UnityEngine; namespace TOHE; @@ -171,22 +172,27 @@ class RpcSetTasksPatch (hasCommonTasks, NumLongTasks, NumShortTasks) = Workhorse.TaskData; //资本主义要祸害人咯~ - if (Main.CapitalismAssignTask.ContainsKey(playerId)) + if (Capitalism.CapitalismAssignTask.ContainsKey(playerId)) { - NumShortTasks += Main.CapitalismAssignTask[playerId]; - Main.CapitalismAssignTask.Remove(playerId); + NumShortTasks += Capitalism.CapitalismAssignTask[playerId]; + Capitalism.CapitalismAssignTask.Remove(playerId); } if (taskTypeIds.Length == 0) hasCommonTasks = false; //タスク再配布時はコモンを0に - if (!hasCommonTasks && NumLongTasks == 0 && NumShortTasks == 0) NumShortTasks = 1; //タスク0対策 - if (hasCommonTasks && NumLongTasks == Main.NormalOptions.NumLongTasks && NumShortTasks == Main.NormalOptions.NumShortTasks) return; //変更点がない場合 + switch (hasCommonTasks) + { + case false when NumLongTasks == 0 && NumShortTasks == 0: + NumShortTasks = 1; //タスク0対策 + break; + case true when NumLongTasks == Main.NormalOptions.NumLongTasks && NumShortTasks == Main.NormalOptions.NumShortTasks: + return; //変更点がない場合 + } //割り当て可能なタスクのIDが入ったリスト //本来のRpcSetTasksの第二引数のクローン List TasksList = new(); - for (int i1 = 0; i1 < taskTypeIds.Count; i1++) + foreach (var num in taskTypeIds) { - byte num = taskTypeIds[i1]; TasksList.Add(num); } diff --git a/Patches/onGameStartedPatch.cs b/Patches/onGameStartedPatch.cs index e652e357f..ca1e0e5db 100644 --- a/Patches/onGameStartedPatch.cs +++ b/Patches/onGameStartedPatch.cs @@ -53,7 +53,7 @@ internal class ChangeRoleSettings Main.RevolutionistCountdown = []; Main.TimeMasterBackTrack = []; Main.TimeMasterNum = []; - Main.FarseerTimer = []; + Farseer.FarseerTimer = []; Main.CursedPlayers = []; Main.MafiaRevenged = []; Main.RetributionistRevenged = []; @@ -100,7 +100,7 @@ internal class ChangeRoleSettings Main.Lighter = []; Main.BlockSabo = []; Main.BlockedVents = []; - Main.MadGrenadierBlinding = []; + Grenadier.MadGrenadierBlinding = []; Main.JinxSpellCount = []; Main.PuppeteerDelay = []; Main.PuppeteerMaxPuppets = []; diff --git a/Roles/Crewmate/CandleLighter.cs b/Roles/Crewmate/CandleLighter.cs index e3865840e..60fb34888 100644 --- a/Roles/Crewmate/CandleLighter.cs +++ b/Roles/Crewmate/CandleLighter.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using AmongUs.GameOptions; using UnityEngine; @@ -6,9 +7,9 @@ namespace TOHE.Roles.Crewmate { using static Options; - public static class Ignitor // Candle Lighter from TOHY + public class Ignitor : RoleBase // Candle Lighter from TOHY { - private static readonly int Id = 5280; + private const int Id = 5280; private static List playerIdList = []; private static OptionItem OptionTaskStartVision; @@ -18,13 +19,13 @@ namespace TOHE.Roles.Crewmate private static OptionItem OptionTaskTimeMoveMeeting; private static OptionItem OptionTasksFinishedVision; - private static float UpdateTime; - private static float ElapsedTime; - private static bool Active = true; + private float UpdateTime; + private float ElapsedTime; + private bool Active = true; public static void SetupCustomOption() { - SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Ignitor, 1); + SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Ignitor); OptionTaskStartVision = FloatOptionItem.Create(Id + 2, "CandleLighterStartVision", new(0.5f, 5f, 0.1f), 0.8f, TabGroup.CrewmateRoles, false) .SetParent(CustomRoleSpawnChances[CustomRoles.Ignitor]) .SetValueFormat(OptionFormat.Multiplier); @@ -44,18 +45,21 @@ namespace TOHE.Roles.Crewmate .SetValueFormat(OptionFormat.Multiplier); OverrideTasksData.Create(Id + 8, TabGroup.CrewmateRoles, CustomRoles.Ignitor); } - public static void Init() + + public override void Init() { playerIdList = []; Active = true; } - public static void Add(byte playerId) + + public override void Add(byte playerId) { playerIdList.Add(playerId); UpdateTime = 1.0f; ElapsedTime = OptionTaskEndVisionTime.GetInt() + OptionCountStartTime.GetInt(); } - public static void ApplyGameOptions(IGameOptions opt) + + public override void ApplyGameOptions(IGameOptions opt, byte id) { float Vision; if (!Active) Vision = OptionTasksFinishedVision.GetFloat(); @@ -68,19 +72,17 @@ namespace TOHE.Roles.Crewmate if (Utils.IsActive(SystemTypes.Electrical)) opt.SetFloat(FloatOptionNames.CrewLightMod, Vision * 5); } - public static bool IsEnable => playerIdList.Count > 0; - public static bool OnCompleteTask(PlayerControl pc) + + public override bool IsEnable => playerIdList.Count > 0; + + public override void OnTaskComplete(PlayerControl pc, int completedTaskCount, int totalTaskCount) { - ElapsedTime = OptionTaskEndVisionTime.GetInt(); - pc.MarkDirtySettings(); - return true; - } - public static void OnTasksFinished(PlayerControl pc) - { - Active = false; + if ((completedTaskCount + 1) >= totalTaskCount) Active = false; + else ElapsedTime = OptionTaskEndVisionTime.GetInt(); pc.MarkDirtySettings(); } - public static void OnFixedUpdate(PlayerControl player) + + public override void OnFixedUpdate(PlayerControl player) { if (!GameStates.IsInTask && !OptionTaskTimeMoveMeeting.GetBool()) return; if (!Active) return; @@ -92,7 +94,7 @@ namespace TOHE.Roles.Crewmate { ElapsedTime -= Time.fixedDeltaTime; - if (UpdateTime == 1.0f) player.MarkDirtySettings(); + if (Math.Abs(UpdateTime - 1.0f) < 0.01f) player.MarkDirtySettings(); } } } diff --git a/Roles/Crewmate/Divinator.cs b/Roles/Crewmate/Divinator.cs index 6da99d5b7..f2c9b8b27 100644 --- a/Roles/Crewmate/Divinator.cs +++ b/Roles/Crewmate/Divinator.cs @@ -5,9 +5,9 @@ using static TOHE.Translator; namespace TOHE.Roles.Crewmate; -public static class Divinator +public class Divinator : RoleBase { - private static readonly int Id = 6700; + private const int Id = 6700; private static List playerIdList = []; public static OptionItem CheckLimitOpt; @@ -39,12 +39,14 @@ public static class Divinator CancelVote = CreateVoteCancellingUseSetting(Id + 11, CustomRoles.Divinator, TabGroup.CrewmateRoles); OverrideTasksData.Create(Id + 21, TabGroup.CrewmateRoles, CustomRoles.Divinator); } - public static void Init() + + public override void Init() { playerIdList = []; AllPlayerRoleList = []; } - public static void Add(byte playerId) + + public override void Add(byte playerId) { playerIdList.Add(playerId); playerId.SetAbilityUseLimit(CheckLimitOpt.GetInt()); @@ -69,7 +71,8 @@ public static class Divinator } } } - public static bool IsEnable => playerIdList.Count > 0; + + public override bool IsEnable => playerIdList.Count > 0; public static bool OnVote(PlayerControl player, PlayerControl target) { diff --git a/Roles/Crewmate/Escort.cs b/Roles/Crewmate/Escort.cs index 532e59d53..54877f9a1 100644 --- a/Roles/Crewmate/Escort.cs +++ b/Roles/Crewmate/Escort.cs @@ -4,9 +4,9 @@ using static TOHE.Translator; namespace TOHE.Roles.Crewmate { - public static class Escort + public class Escort : RoleBase { - private static readonly int Id = 642300; + private const int Id = 642300; private static List playerIdList = []; private static OptionItem CD; @@ -25,12 +25,12 @@ namespace TOHE.Roles.Crewmate UsePet = Options.CreatePetUseSetting(Id + 12, CustomRoles.Escort); } - public static void Init() + public override void Init() { playerIdList = []; } - public static void Add(byte playerId) + public override void Add(byte playerId) { playerIdList.Add(playerId); @@ -41,23 +41,23 @@ namespace TOHE.Roles.Crewmate Main.ResetCamPlayerList.Add(playerId); } - public static bool IsEnable => playerIdList.Count > 0; + public override bool IsEnable => playerIdList.Count > 0; - public static void SetKillCooldown(byte playerId) + public override void SetKillCooldown(byte playerId) { Main.AllPlayerKillCooldown[playerId] = playerId.GetAbilityUseLimit() > 0 ? CD.GetFloat() : 300f; } - public static void OnCheckMurder(PlayerControl killer, PlayerControl target) + public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) { - if (!IsEnable || killer == null || target == null || killer.GetAbilityUseLimit() <= 0 || !killer.Is(CustomRoles.Escort)) return; + if (!IsEnable || killer == null || target == null || killer.GetAbilityUseLimit() <= 0) return false; killer.RpcRemoveAbilityUse(); killer.SetKillCooldown(); Glitch.hackedIdList.TryAdd(target.PlayerId, Utils.TimeStamp); killer.Notify(GetString("EscortTargetHacked")); - } - public static string GetProgressText(byte id) => $"- {id.GetAbilityUseLimit()}"; + return false; + } } } \ No newline at end of file diff --git a/Roles/Crewmate/Express.cs b/Roles/Crewmate/Express.cs index 7837d92b4..ae53393c2 100644 --- a/Roles/Crewmate/Express.cs +++ b/Roles/Crewmate/Express.cs @@ -2,12 +2,25 @@ namespace TOHE.Roles.Crewmate { - internal class Express + internal class Express : RoleBase { public static Dictionary SpeedUp = []; public static Dictionary SpeedNormal = []; - public static void OnTaskComplete(PlayerControl player) + public static bool On; + public override bool IsEnable => On; + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override void OnTaskComplete(PlayerControl player, int completedTaskCount, int totalTaskCount) { if (!SpeedUp.ContainsKey(player.PlayerId)) SpeedNormal[player.PlayerId] = Main.AllPlayerSpeed[player.PlayerId]; Main.AllPlayerSpeed[player.PlayerId] = Options.ExpressSpeed.GetFloat(); @@ -15,8 +28,10 @@ namespace TOHE.Roles.Crewmate player.MarkDirtySettings(); } - public static void OnFixedUpdate(PlayerControl player) + public override void OnFixedUpdate(PlayerControl player) { + if (!GameStates.IsInTask) return; + var playerId = player.PlayerId; var now = Utils.TimeStamp; if (SpeedUp.TryGetValue(playerId, out var etime) && etime + Options.ExpressSpeedDur.GetInt() < now) diff --git a/Roles/Crewmate/Farseer.cs b/Roles/Crewmate/Farseer.cs index 32a22bf8f..3b8b2560b 100644 --- a/Roles/Crewmate/Farseer.cs +++ b/Roles/Crewmate/Farseer.cs @@ -10,18 +10,20 @@ using static TOHE.Utils; namespace TOHE.Roles.Crewmate { - public static class Farseer + public class Farseer : RoleBase { - private static readonly int Id = 9700; + public static Dictionary FarseerTimer = []; - private static readonly string fontSize = "1.6"; + private const int Id = 9700; + + private const string FontSize = "1.6"; public static OptionItem FarseerCooldown; public static OptionItem FarseerRevealTime; public static OptionItem Vision; public static OptionItem UsePet; - private static List RandomRolesForTrickster => EnumHelper.GetAllValues().Where(x => x.IsCrewmate()).ToList(); + private static CustomRoles[] RandomRolesForTrickster => EnumHelper.GetAllValues().Where(x => x.IsCrewmate()).ToArray(); public static Dictionary RandomRole = []; @@ -39,62 +41,65 @@ namespace TOHE.Roles.Crewmate .SetValueFormat(OptionFormat.Multiplier); UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Farseer); } - public static void Init() + + public override void Init() { - isEnable = false; + On = false; } - public static void Add(byte playerId) + + public override void Add(byte playerId) { - isEnable = true; + On = true; if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return; if (!Main.ResetCamPlayerList.Contains(playerId)) Main.ResetCamPlayerList.Add(playerId); } - public static bool isEnable; - public static void SetCooldown(byte id) => Main.AllPlayerKillCooldown[id] = FarseerCooldown.GetFloat(); + public static bool On; + public override bool IsEnable => On; - public static void OnPostFix(PlayerControl player) + public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = FarseerCooldown.GetFloat(); + + public override void OnFixedUpdate(PlayerControl player) { - if (GameStates.IsInTask && Main.FarseerTimer.ContainsKey(player.PlayerId))//アーソニストが誰かを塗っているとき + if (GameStates.IsInTask && FarseerTimer.ContainsKey(player.PlayerId)) { if (!player.IsAlive() || Pelican.IsEaten(player.PlayerId)) { - Main.FarseerTimer.Remove(player.PlayerId); + FarseerTimer.Remove(player.PlayerId); NotifyRoles(SpecifySeer: player); RPC.ResetCurrentRevealTarget(player.PlayerId); } else { - var ar_target = Main.FarseerTimer[player.PlayerId].PLAYER;//塗られる人 - var ar_time = Main.FarseerTimer[player.PlayerId].TIMER;//塗った時間 - if (!ar_target.IsAlive()) + var ar_target = FarseerTimer[player.PlayerId].PLAYER; + var ar_time = FarseerTimer[player.PlayerId].TIMER; + if (!ExtendedPlayerControl.IsAlive(ar_target)) { - Main.FarseerTimer.Remove(player.PlayerId); + FarseerTimer.Remove(player.PlayerId); } - else if (ar_time >= FarseerRevealTime.GetFloat())//時間以上一緒にいて塗れた時 + else if (ar_time >= FarseerRevealTime.GetFloat()) { if (UsePets.GetBool()) player.AddKCDAsAbilityCD(); else player.SetKillCooldown(); - Main.FarseerTimer.Remove(player.PlayerId);//塗が完了したのでDictionaryから削除 - Main.isRevealed[(player.PlayerId, ar_target.PlayerId)] = true;//塗り完了 + FarseerTimer.Remove(player.PlayerId); + Main.isRevealed[(player.PlayerId, ar_target.PlayerId)] = true; player.RpcSetRevealtPlayer(ar_target, true); - NotifyRoles(SpecifySeer: player, SpecifyTarget: ar_target);//名前変更 + NotifyRoles(SpecifySeer: player, SpecifyTarget: ar_target); RPC.ResetCurrentRevealTarget(player.PlayerId); } else { - float range = NormalGameOptionsV07.KillDistances[Mathf.Clamp(player.Is(CustomRoles.Reach) ? 2 : Main.NormalOptions.KillDistance, 0, 2)] + 0.5f; - float dis = Vector2.Distance(player.transform.position, ar_target.transform.position);//距離を出す - if (dis <= range)//一定の距離にターゲットがいるならば時間をカウント + float dis = Vector2.Distance(player.transform.position, ar_target.transform.position); + if (dis <= range) { - Main.FarseerTimer[player.PlayerId] = (ar_target, ar_time + Time.fixedDeltaTime); + FarseerTimer[player.PlayerId] = (ar_target, ar_time + Time.fixedDeltaTime); } - else//それ以外は削除 + else { - Main.FarseerTimer.Remove(player.PlayerId); + FarseerTimer.Remove(player.PlayerId); NotifyRoles(SpecifySeer: player, SpecifyTarget: ar_target, ForceLoop: true); RPC.ResetCurrentRevealTarget(player.PlayerId); @@ -108,9 +113,9 @@ namespace TOHE.Roles.Crewmate public static string GetRandomCrewRoleString() { var rd = IRandom.Instance; - var randomRole = RandomRolesForTrickster[rd.Next(0, RandomRolesForTrickster.Count)]; + var randomRole = RandomRolesForTrickster[rd.Next(0, RandomRolesForTrickster.Length)]; - return $"{ColorString(GetRoleColor(randomRole), GetString(randomRole.ToString()))}"; + return $"{ColorString(GetRoleColor(randomRole), GetString(randomRole.ToString()))}"; } public static string GetTaskState() @@ -125,15 +130,14 @@ namespace TOHE.Roles.Crewmate var randomPlayer = playersWithTasks[rd.Next(0, playersWithTasks.Length)]; var taskState = randomPlayer.Value.TaskState; - Color TextColor; var TaskCompleteColor = Color.green; var NonCompleteColor = Color.yellow; var NormalColor = taskState.IsTaskFinished ? TaskCompleteColor : NonCompleteColor; - TextColor = Camouflager.IsActive ? Color.gray : NormalColor; + Color TextColor = Camouflager.IsActive ? Color.gray : NormalColor; string Completed = Camouflager.IsActive ? "?" : $"{taskState.CompletedTasksCount}"; - return $" " + ColorString(TextColor, $"({Completed}/{taskState.AllTasksCount})") + "\r\n"; + return $" " + ColorString(TextColor, $"({Completed}/{taskState.AllTasksCount})") + "\r\n"; } } } diff --git a/Roles/Crewmate/Gaulois.cs b/Roles/Crewmate/Gaulois.cs index abf24e0ec..34515ee34 100644 --- a/Roles/Crewmate/Gaulois.cs +++ b/Roles/Crewmate/Gaulois.cs @@ -3,9 +3,9 @@ using static TOHE.Options; namespace TOHE.Roles.Crewmate { - public static class Gaulois + public class Gaulois : RoleBase { - private static readonly int Id = 643070; + private const int Id = 643070; private static List playerIdList = []; private static OptionItem CD; @@ -30,13 +30,13 @@ namespace TOHE.Roles.Crewmate UsePet = CreatePetUseSetting(Id + 8, CustomRoles.Gaulois); } - public static void Init() + public override void Init() { playerIdList = []; IncreasedSpeedPlayerList = []; } - public static void Add(byte playerId) + public override void Add(byte playerId) { playerIdList.Add(playerId); playerId.SetAbilityUseLimit(UseLimitOpt.GetInt()); @@ -46,25 +46,25 @@ namespace TOHE.Roles.Crewmate Main.ResetCamPlayerList.Add(playerId); } - public static bool IsEnable => playerIdList.Count > 0; + public override bool IsEnable => playerIdList.Count > 0; - public static void SetKillCooldown(byte playerId) + public override void SetKillCooldown(byte playerId) { if (!IsEnable) return; Main.AllPlayerKillCooldown[playerId] = playerId.GetAbilityUseLimit() > 0 ? CD.GetFloat() : 300f; } - public static void OnCheckMurder(PlayerControl killer, PlayerControl target) + public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) { - if (!IsEnable || killer == null || target == null || killer.GetAbilityUseLimit() <= 0) return; + if (!IsEnable || killer == null || target == null || killer.GetAbilityUseLimit() <= 0) return false; Main.AllPlayerSpeed[target.PlayerId] += AdditionalSpeed.GetFloat(); IncreasedSpeedPlayerList.Add(target.PlayerId); killer.RpcRemoveAbilityUse(); killer.SetKillCooldown(); - } - public static string GetProgressText(byte playerId) => !IsEnable ? string.Empty : $" - {playerId.GetAbilityUseLimit()}"; + return false; + } } } \ No newline at end of file diff --git a/Roles/Crewmate/Grenadier.cs b/Roles/Crewmate/Grenadier.cs new file mode 100644 index 000000000..f10bb3ac6 --- /dev/null +++ b/Roles/Crewmate/Grenadier.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; +using System.Linq; +using AmongUs.GameOptions; +using System.Text; +using HarmonyLib; +using TOHE.Modules; + +namespace TOHE.Roles.Crewmate +{ + internal class Grenadier : RoleBase + { + public static Dictionary GrenadierBlinding = []; + public static Dictionary MadGrenadierBlinding = []; + + public static bool On; + public override bool IsEnable => On; + + public override void Add(byte playerId) + { + On = true; + playerId.SetAbilityUseLimit(Options.GrenadierSkillMaxOfUseage.GetInt()); + } + + public override void Init() + { + On = false; + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + if (Options.UsePets.GetBool()) return; + AURoleOptions.EngineerCooldown = Options.GrenadierSkillCooldown.GetFloat(); + AURoleOptions.EngineerInVentMaxTime = 1; + } + + public override string GetProgressText(byte playerId, bool comms) + { + var ProgressText = new StringBuilder(); + + ProgressText.Append(Utils.GetTaskCount(playerId, comms)); + ProgressText.Append(Utils.GetAbilityUseLimitDisplay(playerId, GrenadierBlinding.ContainsKey(playerId))); + + return ProgressText.ToString(); + } + + public override void SetButtonTexts(HudManager hud, byte id) + { + if (Options.UsePets.GetBool()) + hud.PetButton.buttonLabelText.text = Translator.GetString("GrenadierVentButtonText"); + else + hud.AbilityButton.buttonLabelText.text = Translator.GetString("GrenadierVentButtonText"); + } + + public override void OnPet(PlayerControl pc) + { + BlindPlayers(pc); + } + + public override void OnEnterVent(PlayerControl pc, Vent vent) + { + BlindPlayers(pc); + } + + public override void OnFixedUpdate(PlayerControl player) + { + if (!GameStates.IsInTask) return; + + var playerId = player.PlayerId; + var now = Utils.TimeStamp; + + if (GrenadierBlinding.TryGetValue(playerId, out var gtime) && gtime + Options.GrenadierSkillDuration.GetInt() < now) + { + GrenadierBlinding.Remove(playerId); + player.RpcResetAbilityCooldown(); + player.Notify(string.Format(Translator.GetString("GrenadierSkillStop"), (int)player.GetAbilityUseLimit())); + Utils.MarkEveryoneDirtySettingsV3(); + } + + if (MadGrenadierBlinding.TryGetValue(playerId, out var mgtime) && mgtime + Options.GrenadierSkillDuration.GetInt() < now) + { + MadGrenadierBlinding.Remove(playerId); + player.RpcResetAbilityCooldown(); + player.Notify(string.Format(Translator.GetString("GrenadierSkillStop"), (int)player.GetAbilityUseLimit())); + Utils.MarkEveryoneDirtySettingsV3(); + } + } + + static void BlindPlayers(PlayerControl pc) + { + if (GrenadierBlinding.ContainsKey(pc.PlayerId) || MadGrenadierBlinding.ContainsKey(pc.PlayerId)) return; + if (pc.GetAbilityUseLimit() >= 1) + { + if (pc.Is(CustomRoles.Madmate)) + { + MadGrenadierBlinding.Remove(pc.PlayerId); + MadGrenadierBlinding.Add(pc.PlayerId, Utils.TimeStamp); + Main.AllPlayerControls.Where(x => x.IsModClient()).Where(x => !x.GetCustomRole().IsImpostorTeam() && !x.Is(CustomRoles.Madmate)).Do(x => x.RPCPlayCustomSound("FlashBang")); + } + else + { + GrenadierBlinding.Remove(pc.PlayerId); + GrenadierBlinding.Add(pc.PlayerId, Utils.TimeStamp); + Main.AllPlayerControls.Where(x => x.IsModClient()).Where(x => x.GetCustomRole().IsImpostor() || (x.GetCustomRole().IsNeutral() && Options.GrenadierCanAffectNeutral.GetBool())).Do(x => x.RPCPlayCustomSound("FlashBang")); + } + + pc.RPCPlayCustomSound("FlashBang"); + pc.Notify(Translator.GetString("GrenadierSkillInUse"), Options.GrenadierSkillDuration.GetFloat()); + pc.RpcRemoveAbilityUse(); + Utils.MarkEveryoneDirtySettingsV3(); + } + else + { + if (!NameNotifyManager.Notice.ContainsKey(pc.PlayerId)) pc.Notify(Translator.GetString("OutOfAbilityUsesDoMoreTasks")); + } + } + } +} diff --git a/Roles/Crewmate/Guardian.cs b/Roles/Crewmate/Guardian.cs new file mode 100644 index 000000000..ba99443eb --- /dev/null +++ b/Roles/Crewmate/Guardian.cs @@ -0,0 +1,23 @@ +namespace TOHE.Roles.Crewmate +{ + internal class Guardian : RoleBase + { + public static bool On; + public override bool IsEnable => On; + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override bool OnCheckMurderAsTarget(PlayerControl killer, PlayerControl target) + { + return !target.AllTasksCompleted(); + } + } +} diff --git a/Roles/Crewmate/GuessManager.cs b/Roles/Crewmate/GuessManager.cs index 6cfa13ba2..34bccd905 100644 --- a/Roles/Crewmate/GuessManager.cs +++ b/Roles/Crewmate/GuessManager.cs @@ -3,23 +3,21 @@ using static TOHE.Translator; namespace TOHE.Roles.Crewmate { - public static class GuessManagerRole + public class GuessManagerRole : RoleBase { public static List playerIdList = []; + public static void SetupCustomOption() => Options.SetupRoleOptions(642640, TabGroup.CrewmateRoles, CustomRoles.GuessManager); - public static void Init() => playerIdList = []; - public static void Add(byte playerId) => playerIdList.Add(playerId); + + public override bool IsEnable => playerIdList.Count > 0; + public override void Init() => playerIdList = []; + public override void Add(byte playerId) => playerIdList.Add(playerId); + public static void OnGuess(PlayerControl dp, PlayerControl pc) { - foreach (var guessManager in playerIdList.ToArray()) + foreach (var guessManager in playerIdList) { - _ = new LateTask(() => - { - if (dp == pc) - Utils.SendMessage(string.Format(GetString("GuessManagerMessageAboutMisguess"), dp.GetRealName().Replace("\n", " + "))); - else - Utils.SendMessage(string.Format(GetString("GuessManagerMessageAboutGuessedRole"), dp.GetAllRoleName().Replace("\n", " + "))); - }, 1f, "Guess Manager Messages"); + _ = new LateTask(() => { Utils.SendMessage(dp == pc ? string.Format(GetString("GuessManagerMessageAboutMisguess"), dp.GetRealName().Replace("\n", " + ")) : string.Format(GetString("GuessManagerMessageAboutGuessedRole"), dp.GetAllRoleName().Replace("\n", " + ")), guessManager); }, 1f, "Guess Manager Messages"); } } } diff --git a/Roles/Crewmate/Insight.cs b/Roles/Crewmate/Insight.cs index f835b1463..26cad50c6 100644 --- a/Roles/Crewmate/Insight.cs +++ b/Roles/Crewmate/Insight.cs @@ -3,14 +3,27 @@ using System.Linq; namespace TOHE.Roles.Crewmate { - internal class Insight + internal class Insight : RoleBase { public static List KnownRolesOfPlayerIds = []; - public static void OnTaskComplete(PlayerControl player) + public static bool On; + public override bool IsEnable => On; + + public override void Add(byte playerId) + { + On = true; + } + + public override void Init() + { + On = false; + } + + public override void OnTaskComplete(PlayerControl player, int completedTaskCount, int totalTaskCount) { var list = Main.AllPlayerControls.Where(x => !KnownRolesOfPlayerIds.Contains(x.PlayerId) && !x.Is(CountTypes.OutOfGame) && !x.Is(CustomRoles.Insight) && !x.Is(CustomRoles.GM) && !x.Is(CustomRoles.NotAssigned))?.ToList(); - if (list != null && list.Count != 0) + if (list.Count != 0) { var target = list[IRandom.Instance.Next(0, list.Count)]; KnownRolesOfPlayerIds.Add(target.PlayerId); diff --git a/Roles/Crewmate/Jailer.cs b/Roles/Crewmate/Jailer.cs index 7b225d11e..4e406f365 100644 --- a/Roles/Crewmate/Jailer.cs +++ b/Roles/Crewmate/Jailer.cs @@ -5,14 +5,13 @@ using static TOHE.Translator; namespace TOHE.Roles.Crewmate; -public static class Jailor +public class Jailor : RoleBase { - private static readonly int Id = 63420; + private const int Id = 63420; public static List playerIdList = []; - public static Dictionary JailorTarget = []; - public static Dictionary JailorExeLimit = []; - public static Dictionary JailorHasExe = []; - public static Dictionary JailorDidVote = []; + + public byte JailorTarget; + public bool JailorDidVote; public static OptionItem JailCooldown; public static OptionItem notifyJailedOnMeeting; @@ -27,41 +26,36 @@ public static class Jailor UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Jailor); } - public static void Init() + public override void Init() { playerIdList = []; - JailorExeLimit = []; - JailorTarget = []; - JailorHasExe = []; - JailorDidVote = []; + JailorTarget = byte.MaxValue; + JailorDidVote = false; } - public static void Add(byte playerId) + + public override void Add(byte playerId) { playerIdList.Add(playerId); - JailorTarget.Add(playerId, byte.MaxValue); - JailorHasExe.Add(playerId, false); - JailorDidVote.Add(playerId, false); + JailorTarget = byte.MaxValue; + JailorDidVote = false; if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return; if (!Main.ResetCamPlayerList.Contains(playerId)) Main.ResetCamPlayerList.Add(playerId); } - public static bool IsEnable => playerIdList.Count > 0; - public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = Utils.GetPlayerById(id).IsAlive() ? JailCooldown.GetFloat() : 0f; - public static string GetProgressText(byte playerId) => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor).ShadeColor(0.25f), JailorExeLimit.TryGetValue(playerId, out var exeLimit) ? $"({exeLimit})" : "Invalid"); + public override bool IsEnable => playerIdList.Count > 0; + public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = Utils.GetPlayerById(id).IsAlive() ? JailCooldown.GetFloat() : 0f; - public static void SendRPC(byte jailerId, byte targetId = byte.MaxValue, bool setTarget = true) + void SendRPC(byte jailerId, byte targetId = byte.MaxValue, bool setTarget = true) { - if (!IsEnable || !Utils.DoRPC) return; + if (!Utils.DoRPC) return; MessageWriter writer; if (!setTarget) { writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SetJailorExeLimit, SendOption.Reliable); writer.Write(jailerId); - writer.Write(JailorExeLimit[jailerId]); - writer.Write(JailorHasExe[jailerId]); - writer.Write(JailorDidVote[jailerId]); + writer.Write(JailorDidVote); AmongUsClient.Instance.FinishRpcImmediately(writer); return; } @@ -75,35 +69,28 @@ public static class Jailor public static void ReceiveRPC(MessageReader reader, bool setTarget = true) { byte jailerId = reader.ReadByte(); + if (Main.PlayerStates[jailerId].Role is not Jailor jl) return; + if (!setTarget) { - _ = reader.ReadInt32(); - //if (JailorExeLimit.ContainsKey(jailerId)) JailorExeLimit[jailerId] = points; - //else JailorExeLimit.Add(jailerId, MaxExecution.GetInt()); - - bool executed = reader.ReadBoolean(); - if (!JailorHasExe.TryAdd(jailerId, false)) JailorHasExe[jailerId] = executed; - bool didvote = reader.ReadBoolean(); - if (!JailorDidVote.TryAdd(jailerId, false)) JailorDidVote[jailerId] = didvote; - - return; + jl.JailorDidVote = didvote; } byte targetId = reader.ReadByte(); - JailorTarget[jailerId] = targetId; + jl.JailorTarget = targetId; } - public static bool OnCheckMurder(PlayerControl killer, PlayerControl target) + public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) { - if (!killer.Is(CustomRoles.Jailor)) return true; if (killer == null || target == null) return true; - if (JailorTarget[killer.PlayerId] != byte.MaxValue) + if (JailorTarget != byte.MaxValue) { killer.Notify(GetString("JailorTargetAlreadySelected")); return false; } - JailorTarget[killer.PlayerId] = target.PlayerId; + + JailorTarget = target.PlayerId; killer.Notify(GetString("SuccessfullyJailed")); killer.ResetKillCooldown(); killer.SetKillCooldown(); @@ -111,21 +98,16 @@ public static class Jailor return false; } - public static void OnReportDeadBody() + public override void OnReportDeadBody() { if (!notifyJailedOnMeeting.GetBool()) return; - foreach (var targetId in JailorTarget.Values) + if (JailorTarget == byte.MaxValue) return; + var tpc = Utils.GetPlayerById(JailorTarget); + if (tpc == null) return; + + if (tpc.IsAlive()) { - if (targetId == byte.MaxValue) continue; - var tpc = Utils.GetPlayerById(targetId); - if (tpc == null) continue; - if (tpc.IsAlive()) - { - _ = new LateTask(() => - { - Utils.SendMessage(GetString("JailedNotifyMsg"), targetId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle"))); - }, 0.3f, "JailorNotifyJailed"); - } + _ = new LateTask(() => { Utils.SendMessage(GetString("JailedNotifyMsg"), JailorTarget, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle"))); }, 0.3f, "JailorNotifyJailed"); } } diff --git a/Roles/Crewmate/Judge.cs b/Roles/Crewmate/Judge.cs index 89263c005..387d98ae3 100644 --- a/Roles/Crewmate/Judge.cs +++ b/Roles/Crewmate/Judge.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Text.RegularExpressions; using HarmonyLib; using Hazel; @@ -9,9 +10,9 @@ using Object = UnityEngine.Object; namespace TOHE.Roles.Crewmate; -public static class Judge +public class Judge : RoleBase { - private static readonly int Id = 9300; + private const int Id = 9300; private static List playerIdList = []; public static OptionItem TrialLimitPerMeeting; private static OptionItem TryHideMsg; @@ -49,20 +50,20 @@ public static class Judge AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(Id + 20, "AbilityChargesWhenFinishedTasks", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]).SetValueFormat(OptionFormat.Times); } - public static void Init() + public override void Init() { playerIdList = []; } - public static void Add(byte playerId) + public override void Add(byte playerId) { playerIdList.Add(playerId); playerId.SetAbilityUseLimit(TrialLimitPerMeeting.GetInt()); } - public static bool IsEnable => playerIdList.Count > 0; + public override bool IsEnable => playerIdList.Count > 0; - public static void OnReportDeadBody() + public override void OnReportDeadBody() { byte[] list = [.. playerIdList]; foreach (byte pid in list) @@ -79,7 +80,7 @@ public static class Judge if (!GameStates.IsInGame || pc == null) return false; if (!pc.Is(CustomRoles.Judge)) return false; - int operate = 0; // 1:ID 2:猜测 + int operate; // 1:ID 2:猜测 msg = msg.ToLower().TrimStart().TrimEnd(); if (CheckCommand(ref msg, "id|guesslist|gl编号|玩家编号|玩家id|id列表|玩家列表|列表|所有id|全部id")) operate = 1; else if (CheckCommand(ref msg, "shoot|guess|bet|st|gs|bt|猜|赌|sp|jj|tl|trial|审判|判|审", false)) operate = 2; @@ -91,86 +92,86 @@ public static class Judge return true; } - if (operate == 1) + switch (operate) { - Utils.SendMessage(GuessManager.GetFormatString(), pc.PlayerId); - return true; - } - - if (operate == 2) - { - if (TryHideMsg.GetBool()) /*GuessManager.TryHideMsg();*/ ChatManager.SendPreviousMessagesToAll(); - else if (pc.AmOwner) Utils.SendMessage(originMsg, 255, pc.GetRealName()); - - if (!MsgToPlayerAndRole(msg, out byte targetId, out string error)) - { - Utils.SendMessage(error, pc.PlayerId); + case 1: + Utils.SendMessage(GuessManager.GetFormatString(), pc.PlayerId); return true; - } - - var target = Utils.GetPlayerById(targetId); - if (target != null) + case 2: { - Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 审判了 {target.GetNameWithRole().RemoveHtmlTags()}", "Judge"); - bool judgeSuicide = true; - if (pc.GetAbilityUseLimit() < 1) + if (TryHideMsg.GetBool()) /*GuessManager.TryHideMsg();*/ ChatManager.SendPreviousMessagesToAll(); + else if (pc.AmOwner) Utils.SendMessage(originMsg, 255, pc.GetRealName()); + + if (!MsgToPlayerAndRole(msg, out byte targetId, out string error)) { - if (!isUI) Utils.SendMessage(GetString("JudgeTrialMax"), pc.PlayerId); - else pc.ShowPopUp(GetString("JudgeTrialMax")); + Utils.SendMessage(error, pc.PlayerId); return true; } - if (Jailor.JailorTarget.ContainsValue(target.PlayerId)) + var target = Utils.GetPlayerById(targetId); + if (target != null) { - if (!isUI) Utils.SendMessage(GetString("CanNotTrialJailed"), pc.PlayerId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle"))); - else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle")) + "\n" + GetString("CanNotTrialJailed")); - return true; + Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} 审判了 {target.GetNameWithRole().RemoveHtmlTags()}", "Judge"); + bool judgeSuicide; + if (pc.GetAbilityUseLimit() < 1) + { + if (!isUI) Utils.SendMessage(GetString("JudgeTrialMax"), pc.PlayerId); + else pc.ShowPopUp(GetString("JudgeTrialMax")); + return true; + } + + if (Jailor.playerIdList.Any(x => Main.PlayerStates[x].Role is Jailor { IsEnable: true } jl && jl.JailorTarget == target.PlayerId)) + { + if (!isUI) Utils.SendMessage(GetString("CanNotTrialJailed"), pc.PlayerId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle"))); + else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jailor), GetString("JailorTitle")) + "\n" + GetString("CanNotTrialJailed")); + return true; + } + + if (pc.PlayerId == target.PlayerId) + { + if (!isUI) Utils.SendMessage(GetString("LaughToWhoTrialSelf"), pc.PlayerId, Utils.ColorString(Color.cyan, GetString("MessageFromKPD"))); + else pc.ShowPopUp(Utils.ColorString(Color.cyan, GetString("MessageFromKPD")) + "\n" + GetString("LaughToWhoTrialSelf")); + judgeSuicide = true; + } + else if (pc.Is(CustomRoles.Madmate)) judgeSuicide = false; + else if (pc.Is(CustomRoles.Charmed)) judgeSuicide = false; + else if (pc.Is(CustomRoles.Recruit)) judgeSuicide = false; + else if (pc.Is(CustomRoles.Contagious)) judgeSuicide = false; + else if (target.Is(CustomRoles.Rascal)) judgeSuicide = false; + else if (target.Is(CustomRoles.Pestilence)) judgeSuicide = true; + else if (target.Is(CustomRoles.Trickster)) judgeSuicide = true; + else if (target.Is(CustomRoles.Madmate) && CanTrialMadmate.GetBool()) judgeSuicide = false; + else if (target.Is(CustomRoles.Charmed) && CanTrialCharmed.GetBool()) judgeSuicide = false; + else if (target.GetCustomRole().IsCK() && CanTrialCrewKilling.GetBool()) judgeSuicide = false; + else if (target.GetCustomRole().IsNK() && CanTrialNeutralK.GetBool()) judgeSuicide = false; + else if (target.GetCustomRole().IsNB() && CanTrialNeutralB.GetBool()) judgeSuicide = false; + else if (target.GetCustomRole().IsNE() && CanTrialNeutralE.GetBool()) judgeSuicide = false; + else if (target.GetCustomRole().IsNC() && CanTrialNeutralC.GetBool()) judgeSuicide = false; + else if (target.GetCustomRole().IsImpostor()) judgeSuicide = false; + else if (target.GetCustomRole().IsMadmate() && CanTrialMadmate.GetBool()) judgeSuicide = false; + else judgeSuicide = true; + + var dp = judgeSuicide ? pc : target; + + string Name = dp.GetRealName(); + + pc.RpcRemoveAbilityUse(); + + _ = new LateTask(() => + { + Main.PlayerStates[dp.PlayerId].deathReason = PlayerState.DeathReason.Trialed; + dp.SetRealKiller(pc); + dp.RpcGuesserMurderPlayer(); + + Utils.AfterPlayerDeathTasks(dp, true); + + Utils.NotifyRoles(isForMeeting: false, NoCache: true); + + _ = new LateTask(() => { Utils.SendMessage(string.Format(GetString("TrialKill"), Name), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceGuesser), GetString("TrialKillTitle"))); }, 0.6f, "Guess Msg"); + }, 0.2f, "Trial Kill"); } - if (pc.PlayerId == target.PlayerId) - { - if (!isUI) Utils.SendMessage(GetString("LaughToWhoTrialSelf"), pc.PlayerId, Utils.ColorString(Color.cyan, GetString("MessageFromKPD"))); - else pc.ShowPopUp(Utils.ColorString(Color.cyan, GetString("MessageFromKPD")) + "\n" + GetString("LaughToWhoTrialSelf")); - judgeSuicide = true; - } - else if (pc.Is(CustomRoles.Madmate)) judgeSuicide = false; - else if (pc.Is(CustomRoles.Charmed)) judgeSuicide = false; - else if (pc.Is(CustomRoles.Recruit)) judgeSuicide = false; - else if (pc.Is(CustomRoles.Contagious)) judgeSuicide = false; - else if (target.Is(CustomRoles.Rascal)) judgeSuicide = false; - else if (target.Is(CustomRoles.Pestilence)) judgeSuicide = true; - else if (target.Is(CustomRoles.Trickster)) judgeSuicide = true; - else if (target.Is(CustomRoles.Madmate) && CanTrialMadmate.GetBool()) judgeSuicide = false; - else if (target.Is(CustomRoles.Charmed) && CanTrialCharmed.GetBool()) judgeSuicide = false; - else if (target.GetCustomRole().IsCK() && CanTrialCrewKilling.GetBool()) judgeSuicide = false; - else if (target.GetCustomRole().IsNK() && CanTrialNeutralK.GetBool()) judgeSuicide = false; - else if (target.GetCustomRole().IsNB() && CanTrialNeutralB.GetBool()) judgeSuicide = false; - else if (target.GetCustomRole().IsNE() && CanTrialNeutralE.GetBool()) judgeSuicide = false; - else if (target.GetCustomRole().IsNC() && CanTrialNeutralC.GetBool()) judgeSuicide = false; - else if (target.GetCustomRole().IsImpostor()) judgeSuicide = false; - else if (target.GetCustomRole().IsMadmate() && CanTrialMadmate.GetBool()) judgeSuicide = false; - else judgeSuicide = true; - - var dp = judgeSuicide ? pc : target; - target = dp; - - string Name = dp.GetRealName(); - - pc.RpcRemoveAbilityUse(); - - _ = new LateTask(() => - { - Main.PlayerStates[dp.PlayerId].deathReason = PlayerState.DeathReason.Trialed; - dp.SetRealKiller(pc); - dp.RpcGuesserMurderPlayer(); - - //死者检查 - Utils.AfterPlayerDeathTasks(dp, true); - - Utils.NotifyRoles(isForMeeting: false, NoCache: true); - - _ = new LateTask(() => { Utils.SendMessage(string.Format(GetString("TrialKill"), Name), 255, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceGuesser), GetString("TrialKillTitle"))); }, 0.6f, "Guess Msg"); - }, 0.2f, "Trial Kill"); + break; } } @@ -239,7 +240,7 @@ public static class Judge private static void SendRPC(byte playerId) { - if (!IsEnable || !Utils.DoRPC) return; + if (!Utils.DoRPC) return; MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.Judge, SendOption.Reliable); writer.Write(playerId); AmongUsClient.Instance.FinishRpcImmediately(writer); diff --git a/Roles/Crewmate/Lighter.cs b/Roles/Crewmate/Lighter.cs new file mode 100644 index 000000000..ed0234fbf --- /dev/null +++ b/Roles/Crewmate/Lighter.cs @@ -0,0 +1,109 @@ +using AmongUs.GameOptions; +using System.Text; + +namespace TOHE.Roles.Crewmate +{ + internal class Lighter : RoleBase + { + private bool IsAbilityActive; + private long ActivateTimeStamp; + + public static bool On; + public override bool IsEnable => On; + + public override void Add(byte playerId) + { + On = true; + playerId.SetAbilityUseLimit(Options.LighterSkillMaxOfUseage.GetInt()); + IsAbilityActive = false; + ActivateTimeStamp = 0; + } + + public override void Init() + { + On = false; + IsAbilityActive = false; + ActivateTimeStamp = 0; + } + + public override void ApplyGameOptions(IGameOptions opt, byte playerId) + { + if (Options.UsePets.GetBool()) return; + AURoleOptions.EngineerInVentMaxTime = 1; + AURoleOptions.EngineerCooldown = Options.LighterSkillCooldown.GetFloat(); + + if (IsAbilityActive) + { + opt.SetVisionV2(); + if (Utils.IsActive(SystemTypes.Electrical)) opt.SetFloat(FloatOptionNames.CrewLightMod, Options.LighterVisionOnLightsOut.GetFloat() * 5); + else opt.SetFloat(FloatOptionNames.CrewLightMod, Options.LighterVisionNormal.GetFloat()); + } + } + + public override string GetProgressText(byte playerId, bool comms) + { + var ProgressText = new StringBuilder(); + + ProgressText.Append(Utils.GetTaskCount(playerId, comms)); + ProgressText.Append(Utils.GetAbilityUseLimitDisplay(playerId, Main.Lighter.ContainsKey(playerId))); + + return ProgressText.ToString(); + } + + public override void SetButtonTexts(HudManager hud, byte id) + { + if (Options.UsePets.GetBool()) + hud.PetButton.buttonLabelText.text = Translator.GetString("LighterVentButtonText"); + else + hud.AbilityButton.buttonLabelText.text = Translator.GetString("LighterVentButtonText"); + } + + public override void OnPet(PlayerControl pc) + { + Light(pc); + } + + public override void OnEnterVent(PlayerControl pc, Vent vent) + { + Light(pc); + } + + void Light(PlayerControl pc) + { + if (IsAbilityActive) return; + if (pc.GetAbilityUseLimit() >= 1) + { + IsAbilityActive = true; + ActivateTimeStamp = Utils.TimeStamp; + + pc.Notify(Translator.GetString("LighterSkillInUse"), Options.LighterSkillDuration.GetFloat()); + pc.RpcRemoveAbilityUse(); + pc.MarkDirtySettings(); + } + else + { + if (!NameNotifyManager.Notice.ContainsKey(pc.PlayerId)) + pc.Notify(Translator.GetString("OutOfAbilityUsesDoMoreTasks")); + } + } + + public override void OnReportDeadBody() + { + IsAbilityActive = false; + ActivateTimeStamp = 0; + } + + public override void OnFixedUpdate(PlayerControl player) + { + if (!GameStates.IsInTask) return; + + if (IsAbilityActive && ActivateTimeStamp + Options.LighterSkillDuration.GetInt() < Utils.TimeStamp) + { + IsAbilityActive = false; + player.RpcResetAbilityCooldown(); + player.Notify(Translator.GetString("LighterSkillStop")); + player.MarkDirtySettings(); + } + } + } +} diff --git a/Roles/Crewmate/ParityCop.cs b/Roles/Crewmate/ParityCop.cs index 4e757b21b..132d1a33a 100644 --- a/Roles/Crewmate/ParityCop.cs +++ b/Roles/Crewmate/ParityCop.cs @@ -9,14 +9,14 @@ using Object = UnityEngine.Object; namespace TOHE.Roles.Crewmate; -public static class ParityCop +public class ParityCop : RoleBase { - private static readonly int Id = 6900; + private const int Id = 6900; private static List playerIdList = []; public static Dictionary RoundCheckLimit = []; public static Dictionary FirstPick = []; - public static readonly string[] pcEgoistCountMode = + public static readonly string[] PcEgoistCountMode = [ "EgoistCountMode.Original", "EgoistCountMode.Neutral", @@ -42,7 +42,7 @@ public static class ParityCop .SetValueFormat(OptionFormat.Times); ParityCheckLimitPerMeeting = IntegerOptionItem.Create(Id + 12, "ParityCheckLimitPerMeeting", new(1, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop]) .SetValueFormat(OptionFormat.Times); - ParityCheckEgoistCountType = StringOptionItem.Create(Id + 13, "ParityCheckEgoistickCountMode", pcEgoistCountMode, 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop]); + ParityCheckEgoistCountType = StringOptionItem.Create(Id + 13, "ParityCheckEgoistickCountMode", PcEgoistCountMode, 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop]); ParityCheckBaitCountType = BooleanOptionItem.Create(Id + 14, "ParityCheckBaitCountMode", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop]); ParityCheckTargetKnow = BooleanOptionItem.Create(Id + 15, "ParityCheckTargetKnow", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.ParityCop]); ParityCheckOtherTargetKnow = BooleanOptionItem.Create(Id + 16, "ParityCheckOtherTargetKnow", true, TabGroup.CrewmateRoles, false).SetParent(ParityCheckTargetKnow); @@ -58,23 +58,23 @@ public static class ParityCop public static int ParityCheckEgoistInt() => ParityCheckEgoistCountType.GetString() == "EgoistCountMode.Original" ? 0 : 1; - public static void Init() + public override void Init() { playerIdList = []; RoundCheckLimit = []; FirstPick = []; } - public static void Add(byte playerId) + public override void Add(byte playerId) { playerIdList.Add(playerId); playerId.SetAbilityUseLimit(ParityCheckLimitMax.GetInt()); RoundCheckLimit.Add(playerId, ParityCheckLimitPerMeeting.GetInt()); } - public static bool IsEnable => playerIdList.Count > 0; + public override bool IsEnable => playerIdList.Count > 0; - public static void OnReportDeadBody() + public override void OnReportDeadBody() { RoundCheckLimit.Clear(); foreach (byte pc in playerIdList.ToArray()) @@ -91,7 +91,7 @@ public static class ParityCop if (!GameStates.IsInGame || pc == null) return false; if (!pc.Is(CustomRoles.ParityCop)) return false; - int operate = 0; // 1:ID 2:猜测 + int operate; // 1:ID 2:Check msg = msg.ToLower().TrimStart().TrimEnd(); if (CheckCommand(ref msg, "id|guesslist|gl编号|玩家编号|玩家id|id列表|玩家列表|列表|所有id|全部id")) operate = 1; else if (CheckCommand(ref msg, "compare|cp|cmp|比较", false)) operate = 2; @@ -103,137 +103,139 @@ public static class ParityCop return true; } - if (operate == 1) + switch (operate) { - Utils.SendMessage(GuessManager.GetFormatString(), pc.PlayerId); - return true; - } - - if (operate == 2) - { - if (TryHideMsg.GetBool()) /*TryHideMsgForCompare();*/ ChatManager.SendPreviousMessagesToAll(); - else if (pc.AmOwner) Utils.SendMessage(originMsg, 255, pc.GetRealName()); - - if (!MsgToPlayerAndRole(msg, out byte targetId1, out byte targetId2, out string error)) - { - Utils.SendMessage(error, pc.PlayerId); + case 1: + Utils.SendMessage(GuessManager.GetFormatString(), pc.PlayerId); return true; - } - - var target1 = Utils.GetPlayerById(targetId1); - var target2 = Utils.GetPlayerById(targetId2); - if (target1 != null && target2 != null) + case 2: { - Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} checked {target1.GetNameWithRole().RemoveHtmlTags()} and {target2.GetNameWithRole().RemoveHtmlTags()}", "ParityCop"); + if (TryHideMsg.GetBool()) /*TryHideMsgForCompare();*/ ChatManager.SendPreviousMessagesToAll(); + else if (pc.AmOwner) Utils.SendMessage(originMsg, 255, pc.GetRealName()); - if (pc.GetAbilityUseLimit() < 1 || RoundCheckLimit[pc.PlayerId] < 1) + if (!MsgToPlayerAndRole(msg, out byte targetId1, out byte targetId2, out string error)) { - if (pc.GetAbilityUseLimit() < 1) + Utils.SendMessage(error, pc.PlayerId); + return true; + } + + var target1 = Utils.GetPlayerById(targetId1); + var target2 = Utils.GetPlayerById(targetId2); + if (target1 != null && target2 != null) + { + Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} checked {target1.GetNameWithRole().RemoveHtmlTags()} and {target2.GetNameWithRole().RemoveHtmlTags()}", "ParityCop"); + + if (pc.GetAbilityUseLimit() < 1 || RoundCheckLimit[pc.PlayerId] < 1) + { + if (pc.GetAbilityUseLimit() < 1) + { + _ = new LateTask(() => + { + if (!isUI) Utils.SendMessage(GetString("ParityCheckMax"), pc.PlayerId); + else pc.ShowPopUp(GetString("ParityCheckMax")); + Logger.Msg("Check attempted at max checks per game", "Parity Cop"); + }, 0.2f, "ParityCop"); + } + else + { + _ = new LateTask(() => + { + if (!isUI) Utils.SendMessage(GetString("ParityCheckRound"), pc.PlayerId); + else pc.ShowPopUp(GetString("ParityCheckRound")); + Logger.Msg("Check attempted at max checks per meeting", "Parity Cop"); + }, 0.2f, "ParityCop"); + } + + return true; + } + + if (pc.PlayerId == target1.PlayerId || pc.PlayerId == target2.PlayerId) { _ = new LateTask(() => { - if (!isUI) Utils.SendMessage(GetString("ParityCheckMax"), pc.PlayerId); - else pc.ShowPopUp(GetString("ParityCheckMax")); - Logger.Msg("Check attempted at max checks per game", "Parity Cop"); + if (!isUI) Utils.SendMessage(GetString("ParityCheckSelf"), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckSelf")) + "\n" + GetString("ParityCheckTitle")); + Logger.Msg("Check attempted on self", "Parity Cop"); + }, 0.2f, "ParityCop"); + return true; + } + + if (target1.GetCustomRole().IsRevealingRole(target1) || target1.GetCustomSubRoles().Any(role => role.IsRevealingRole(target1)) || target2.GetCustomRole().IsRevealingRole(target2) || target2.GetCustomSubRoles().Any(role => role.IsRevealingRole(target2))) + { + _ = new LateTask(() => + { + if (!isUI) Utils.SendMessage(GetString("ParityCheckReveal"), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckReveal")) + "\n" + GetString("ParityCheckTitle")); + Logger.Msg("Check attempted on revealed role", "Parity Cop"); + }, 0.2f, "ParityCop"); + return true; + } + + if (((target1.Is(Team.Impostor) || target1.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) && (target2.Is(Team.Impostor) || target2.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3()))) || + ((target1.Is(Team.Neutral) || target1.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) && (target2.Is(Team.Neutral) || target2.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2()))) || + (target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (target1.GetCustomSubRoles().Count == 0)) && target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || target2.GetCustomSubRoles().Count == 0))) + { + _ = new LateTask(() => + { + if (!isUI) Utils.SendMessage(string.Format(GetString("ParityCheckTrue"), target1.GetRealName(), target2.GetRealName()), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTrue")) + "\n" + GetString("ParityCheckTitle")); + Logger.Msg("Check attempt, result TRUE", "Parity Cop"); }, 0.2f, "ParityCop"); } else { _ = new LateTask(() => { - if (!isUI) Utils.SendMessage(GetString("ParityCheckRound"), pc.PlayerId); - else pc.ShowPopUp(GetString("ParityCheckRound")); - Logger.Msg("Check attempted at max checks per meeting", "Parity Cop"); + if (!isUI) Utils.SendMessage(string.Format(GetString("ParityCheckFalse"), target1.GetRealName(), target2.GetRealName()), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckFalse")) + "\n" + GetString("ParityCheckTitle")); + Logger.Msg("Check attempt, result FALSE", "Parity Cop"); }, 0.2f, "ParityCop"); } - return true; - } - - if (pc.PlayerId == target1.PlayerId || pc.PlayerId == target2.PlayerId) - { - _ = new LateTask(() => + if (ParityCheckTargetKnow.GetBool()) { - if (!isUI) Utils.SendMessage(GetString("ParityCheckSelf"), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckSelf")) + "\n" + GetString("ParityCheckTitle")); - Logger.Msg("Check attempted on self", "Parity Cop"); - }, 0.2f, "ParityCop"); - return true; - } - - if (target1.GetCustomRole().IsRevealingRole(target1) || target1.GetCustomSubRoles().Any(role => role.IsRevealingRole(target1)) || target2.GetCustomRole().IsRevealingRole(target2) || target2.GetCustomSubRoles().Any(role => role.IsRevealingRole(target2))) - { - _ = new LateTask(() => - { - if (!isUI) Utils.SendMessage(GetString("ParityCheckReveal"), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckReveal")) + "\n" + GetString("ParityCheckTitle")); - Logger.Msg("Check attempted on revealed role", "Parity Cop"); - }, 0.2f, "ParityCop"); - return true; - } - - if (((target1.Is(Team.Impostor) || target1.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) && (target2.Is(Team.Impostor) || target2.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3()))) || - ((target1.Is(Team.Neutral) || target1.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) && (target2.Is(Team.Neutral) || target2.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2()))) || - (target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (target1.GetCustomSubRoles().Count == 0)) && target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || target2.GetCustomSubRoles().Count == 0))) - { - _ = new LateTask(() => - { - if (!isUI) Utils.SendMessage(string.Format(GetString("ParityCheckTrue"), target1.GetRealName(), target2.GetRealName()), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTrue")) + "\n" + GetString("ParityCheckTitle")); - Logger.Msg("Check attempt, result TRUE", "Parity Cop"); - }, 0.2f, "ParityCop"); - } - else - { - _ = new LateTask(() => - { - if (!isUI) Utils.SendMessage(string.Format(GetString("ParityCheckFalse"), target1.GetRealName(), target2.GetRealName()), pc.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - else pc.ShowPopUp(Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckFalse")) + "\n" + GetString("ParityCheckTitle")); - Logger.Msg("Check attempt, result FALSE", "Parity Cop"); - }, 0.2f, "ParityCop"); - } - - if (ParityCheckTargetKnow.GetBool()) - { - string textToSend = $"{target1.GetRealName()}"; - if (ParityCheckOtherTargetKnow.GetBool()) - textToSend += $" and {target2.GetRealName()}"; - textToSend += GetString("ParityCheckTargetMsg"); - - string textToSend1 = $"{target2.GetRealName()}"; - if (ParityCheckOtherTargetKnow.GetBool()) - textToSend1 += $" and {target1.GetRealName()}"; - textToSend1 += GetString("ParityCheckTargetMsg"); - _ = new LateTask(() => - { - Utils.SendMessage(textToSend, target1.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - Utils.SendMessage(textToSend1, target2.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - Logger.Msg("Check attempt, target1 notified", "Parity Cop"); - Logger.Msg("Check attempt, target2 notified", "Parity Cop"); - }, 0.2f, "ParityCop"); - - if (ParityCheckRevealTargetTeam.GetBool() && pc.AllTasksCompleted()) - { - string roleT1 = string.Empty, roleT2 = string.Empty; - if (target1.Is(Team.Impostor) || target1.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) roleT1 = "Impostor"; - else if (target1.Is(Team.Neutral) || target1.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) roleT1 = "Neutral"; - else if (target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (target1.GetCustomSubRoles().Count == 0))) - - if (target2.Is(Team.Impostor) || target2.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) roleT2 = "Impostor"; - else if (target2.Is(Team.Neutral) || target2.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) roleT2 = "Neutral"; - else if (target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || target2.GetCustomSubRoles().Count == 0)) roleT2 = "Crewmate"; + string textToSend = $"{target1.GetRealName()}"; + if (ParityCheckOtherTargetKnow.GetBool()) + textToSend += $" and {target2.GetRealName()}"; + textToSend += GetString("ParityCheckTargetMsg"); + string textToSend1 = $"{target2.GetRealName()}"; + if (ParityCheckOtherTargetKnow.GetBool()) + textToSend1 += $" and {target1.GetRealName()}"; + textToSend1 += GetString("ParityCheckTargetMsg"); _ = new LateTask(() => { - Utils.SendMessage(string.Format(GetString("ParityCopTargetReveal"), target2.GetRealName(), roleT2), target1.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - Utils.SendMessage(string.Format(GetString("ParityCopTargetReveal"), target1.GetRealName(), roleT1), target2.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); - Logger.Msg($"check attempt, target1 notified target2 as {roleT2} and target2 notified target1 as {roleT1}", "Parity Cop"); - }, 0.3f, "ParityCop"); + Utils.SendMessage(textToSend, target1.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + Utils.SendMessage(textToSend1, target2.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + Logger.Msg("Check attempt, target1 notified", "Parity Cop"); + Logger.Msg("Check attempt, target2 notified", "Parity Cop"); + }, 0.2f, "ParityCop"); + + if (ParityCheckRevealTargetTeam.GetBool() && pc.AllTasksCompleted()) + { + string roleT1 = string.Empty, roleT2 = string.Empty; + if (target1.Is(Team.Impostor) || target1.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) roleT1 = "Impostor"; + else if (target1.Is(Team.Neutral) || target1.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) roleT1 = "Neutral"; + else if (target1.Is(Team.Crewmate) && (target1.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || (target1.GetCustomSubRoles().Count == 0))) + + if (target2.Is(Team.Impostor) || target2.GetCustomSubRoles().Any(role => role.IsImpostorTeamV3())) roleT2 = "Impostor"; + else if (target2.Is(Team.Neutral) || target2.GetCustomSubRoles().Any(role => role.IsNeutralTeamV2())) roleT2 = "Neutral"; + else if (target2.Is(Team.Crewmate) && (target2.GetCustomSubRoles().Any(role => role.IsCrewmateTeamV2()) || target2.GetCustomSubRoles().Count == 0)) roleT2 = "Crewmate"; + + _ = new LateTask(() => + { + Utils.SendMessage(string.Format(GetString("ParityCopTargetReveal"), target2.GetRealName(), roleT2), target1.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + Utils.SendMessage(string.Format(GetString("ParityCopTargetReveal"), target1.GetRealName(), roleT1), target2.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.ParityCop), GetString("ParityCheckTitle"))); + Logger.Msg($"check attempt, target1 notified target2 as {roleT2} and target2 notified target1 as {roleT1}", "Parity Cop"); + }, 0.3f, "ParityCop"); + } } + + pc.RpcRemoveAbilityUse(); + RoundCheckLimit[pc.PlayerId]--; } - pc.RpcRemoveAbilityUse(); - RoundCheckLimit[pc.PlayerId]--; + break; } } diff --git a/Roles/Neutral/Glitch.cs b/Roles/Neutral/Glitch.cs index f56050112..99dac8462 100644 --- a/Roles/Neutral/Glitch.cs +++ b/Roles/Neutral/Glitch.cs @@ -8,9 +8,9 @@ using static TOHE.Options; namespace TOHE.Roles.Neutral; -public static class Glitch +public class Glitch : RoleBase { - private static readonly int Id = 18125; + private const int Id = 18125; public static List playerIdList = []; public static Dictionary hackedIdList = []; @@ -24,15 +24,18 @@ public static class Glitch public static OptionItem CanVote; private static OptionItem HasImpostorVision; - public static int HackCDTimer; - public static int KCDTimer; - public static int MimicCDTimer; - public static int MimicDurTimer; - public static long LastHack; - public static long LastKill; - public static long LastMimic; + private byte GlitchId; - private static bool isShifted; + public int HackCDTimer; + public int KCDTimer; + public int MimicCDTimer; + public int MimicDurTimer; + + public long LastHack; + public long LastKill; + public long LastMimic; + + private bool isShifted; public static void SetupCustomOption() { @@ -51,14 +54,18 @@ public static class Glitch CanVote = BooleanOptionItem.Create(Id + 17, "CanVote", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Glitch]); HasImpostorVision = BooleanOptionItem.Create(Id + 13, "ImpostorVision", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Glitch]); } - public static void Init() + + public override void Init() { playerIdList = []; hackedIdList = []; + GlitchId = byte.MaxValue; } - public static void Add(byte playerId) + + public override void Add(byte playerId) { playerIdList.Add(playerId); + GlitchId = playerId; HackCDTimer = 10; KCDTimer = 10; @@ -73,25 +80,23 @@ public static class Glitch LastHack = ts; LastMimic = ts; - _ = new LateTask(() => - { - SendRPCSyncTimers(); - }, 7f, "Glitch RPCs"); - if (!AmongUsClient.Instance.AmHost) return; if (!Main.ResetCamPlayerList.Contains(playerId)) Main.ResetCamPlayerList.Add(playerId); } - public static void SetHudActive(HudManager __instance) + + public override void SetButtonTexts(HudManager hud, byte id) { - __instance.SabotageButton.ToggleVisible(true); + hud.SabotageButton.ToggleVisible(true); } - public static bool IsEnable => playerIdList.Count > 0; - public static void SendRPCSyncTimers() + public override bool IsEnable => playerIdList.Count > 0; + + void SendRPCSyncTimers() { if (!IsEnable || !Utils.DoRPC) return; MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncGlitchTimers, SendOption.Reliable); + writer.Write(GlitchId); writer.Write(MimicCDTimer); writer.Write(MimicDurTimer); writer.Write(HackCDTimer); @@ -100,16 +105,19 @@ public static class Glitch } public static void ReceiveRPCSyncTimers(MessageReader reader) { - if (AmongUsClient.Instance.AmHost) return; + byte id = reader.ReadByte(); + if (Main.PlayerStates[id].Role is not Glitch gc) return; - MimicCDTimer = reader.ReadInt32(); - MimicDurTimer = reader.ReadInt32(); - HackCDTimer = reader.ReadInt32(); - KCDTimer = reader.ReadInt32(); + gc.MimicCDTimer = reader.ReadInt32(); + gc.MimicDurTimer = reader.ReadInt32(); + gc.HackCDTimer = reader.ReadInt32(); + gc.KCDTimer = reader.ReadInt32(); } - public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = 1f; - public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool()); - public static void Mimic(PlayerControl pc) + + public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = 1f; + public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool()); + + void Mimic(PlayerControl pc) { if (pc == null || !pc.Is(CustomRoles.Glitch) || !pc.IsAlive() || MimicCDTimer > 0 || isShifted) return; @@ -130,7 +138,18 @@ public static class Glitch Logger.Error(ex.ToString(), "Glitch.Mimic.RpcShapeshift"); } } - public static bool OnCheckMurder(PlayerControl killer, PlayerControl target) + + public override void OnPet(PlayerControl pc) + { + Mimic(pc); + } + + public override void OnSabotage(PlayerControl pc) + { + Mimic(pc); + } + + public override bool OnCheckMurder(PlayerControl killer, PlayerControl target) { if (killer == null || target == null || (KCDTimer > 0 && HackCDTimer > 0)) return false; @@ -155,12 +174,13 @@ public static class Glitch return false; } - public static void UpdateHackCooldown(PlayerControl player) + + public override void OnFixedUpdate(PlayerControl player) { - if (HackCDTimer > 180 || HackCDTimer < 0) HackCDTimer = 0; - if (KCDTimer > 180 || KCDTimer < 0) KCDTimer = 0; - if (MimicCDTimer > 180 || MimicCDTimer < 0) MimicCDTimer = 0; - if (MimicDurTimer > 180 || MimicDurTimer < 0) MimicDurTimer = 0; + if (HackCDTimer is > 180 or < 0) HackCDTimer = 0; + if (KCDTimer is > 180 or < 0) KCDTimer = 0; + if (MimicCDTimer is > 180 or < 0) MimicCDTimer = 0; + if (MimicDurTimer is > 180 or < 0) MimicDurTimer = 0; bool change = false; foreach (var pc in hackedIdList) @@ -173,9 +193,11 @@ public static class Glitch } if (player == null) return; - if (!player.Is(CustomRoles.Glitch)) return; - if (change) { Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player); } + if (change) + { + Utils.NotifyRoles(SpecifySeer: player); + } if (!player.IsAlive()) { @@ -213,15 +235,18 @@ public static class Glitch try { HackCDTimer = (int)(HackCooldown.GetInt() - (Utils.TimeStamp - LastHack)); } catch { HackCDTimer = 0; } - if (HackCDTimer > 180 || HackCDTimer < 0) HackCDTimer = 0; + + if (HackCDTimer is > 180 or < 0) HackCDTimer = 0; try { KCDTimer = (int)(KillCooldown.GetInt() - (Utils.TimeStamp - LastKill)); } catch { KCDTimer = 0; } - if (KCDTimer > 180 || KCDTimer < 0) KCDTimer = 0; + + if (KCDTimer is > 180 or < 0) KCDTimer = 0; try { MimicCDTimer = (int)(MimicCooldown.GetInt() + MimicDuration.GetInt() - (Utils.TimeStamp - LastMimic)); } catch { MimicCDTimer = 0; } - if (MimicCDTimer > 180 || MimicCDTimer < 0) MimicCDTimer = 0; + + if (MimicCDTimer is > 180 or < 0) MimicCDTimer = 0; if (!player.IsModClient()) { @@ -241,20 +266,20 @@ public static class Glitch } public static string GetHudText(PlayerControl player) { - if (player == null) return string.Empty; - if (!player.Is(CustomRoles.Glitch)) return string.Empty; - if (!player.IsAlive()) return string.Empty; + if (player == null || !player.IsAlive()) return string.Empty; + if (Main.PlayerStates[player.PlayerId].Role is not Glitch gc) return string.Empty; var sb = new StringBuilder(); - if (MimicDurTimer > 0) sb.Append($"{string.Format(Translator.GetString("MimicDur"), MimicDurTimer)}\n"); - if (MimicCDTimer > 0 && MimicDurTimer <= 0) sb.Append($"{string.Format(Translator.GetString("MimicCD"), MimicCDTimer)}\n"); - if (HackCDTimer > 0) sb.Append($"{string.Format(Translator.GetString("HackCD"), HackCDTimer)}\n"); - if (KCDTimer > 0) sb.Append($"{string.Format(Translator.GetString("KCD"), KCDTimer)}\n"); + if (gc.MimicDurTimer > 0) sb.Append($"{string.Format(Translator.GetString("MimicDur"), gc.MimicDurTimer)}\n"); + if (gc.MimicCDTimer > 0 && gc.MimicDurTimer <= 0) sb.Append($"{string.Format(Translator.GetString("MimicCD"), gc.MimicCDTimer)}\n"); + if (gc.HackCDTimer > 0) sb.Append($"{string.Format(Translator.GetString("HackCD"), gc.HackCDTimer)}\n"); + if (gc.KCDTimer > 0) sb.Append($"{string.Format(Translator.GetString("KCD"), gc.KCDTimer)}\n"); return sb.ToString(); } - public static void AfterMeetingTasks() + + public override void AfterMeetingTasks() { var timestamp = Utils.TimeStamp; LastKill = timestamp; diff --git a/Roles/RoleBase.cs b/Roles/RoleBase.cs index 24c1d1d6d..f813727b2 100644 --- a/Roles/RoleBase.cs +++ b/Roles/RoleBase.cs @@ -60,6 +60,10 @@ namespace TOHE { } + public virtual void OnSabotage(PlayerControl pc) + { + } + public virtual bool OnCheckMurder(PlayerControl killer, PlayerControl target) { return target != null && killer != null; diff --git a/main.cs b/main.cs index f3c4565cd..00f457cf1 100644 --- a/main.cs +++ b/main.cs @@ -163,7 +163,6 @@ public class Main : BasePlugin public static Dictionary<(byte, byte), bool> isRevealed = []; public static Dictionary ArsonistTimer = []; public static Dictionary RevolutionistTimer = []; - public static Dictionary FarseerTimer = []; public static Dictionary RevolutionistStart = []; public static Dictionary RevolutionistLastTime = []; public static Dictionary RevolutionistCountdown = []; @@ -174,10 +173,7 @@ public class Main : BasePlugin public static Dictionary MarioVentCount = []; public static Dictionary VeteranInProtect = []; public static Dictionary AllKillers = []; - public static Dictionary GrenadierBlinding = []; - public static Dictionary Lighter = []; public static Dictionary BlockSabo = []; - public static Dictionary MadGrenadierBlinding = []; public static Dictionary JinxSpellCount = []; public static Dictionary SleuthMsgs = []; public static int AliveImpostorCount; @@ -770,7 +766,6 @@ public enum CustomRoles Farseer, Divinator, // Fortune Teller Gaulois, - Glitch, Grenadier, GuessManager, Guardian, @@ -849,6 +844,7 @@ public enum CustomRoles Enderman, Executioner, Totocalcio, // Follower + Glitch, God, FFF, // Hater HeadHunter,