From 0223ee11c3048f9830056629997bcd8ca0861684 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Thu, 6 Mar 2025 23:50:57 +0800 Subject: [PATCH 01/43] global methods to check if target can be recruited and global method to get a player's betrayal addon --- Modules/CustomRolesHelper.cs | 74 +++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 2 deletions(-) diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 986fea442f..5ecb7d6a6d 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -5,6 +5,7 @@ using TOHE.Roles.AddOns.Impostor; using TOHE.Roles.Core; using TOHE.Roles.Crewmate; +using TOHE.Roles.Double; using TOHE.Roles.Impostor; using TOHE.Roles.Neutral; using static TOHE.Roles.Core.CustomRoleManager; @@ -317,11 +318,22 @@ public static bool IsAbleToBeSidekicked(this CustomRoles role) public static bool IsRecruitingRole(this CustomRoles role) => role is - CustomRoles.Jackal or + //Crewmate + CustomRoles.Admirer or + CustomRoles.ChiefOfPolice or + + //Impostor + CustomRoles.Gangster or + CustomRoles.Godfather or + + //Neutral CustomRoles.Cultist or - CustomRoles.Necromancer or + CustomRoles.Infectious or + CustomRoles.Jackal or CustomRoles.Virus or CustomRoles.Spiritcaller or + + //Coven CustomRoles.Ritualist; public static bool IsMadmate(this CustomRoles role) @@ -413,6 +425,64 @@ CustomRoles.Circumvent or CustomRoles.Swift; } + public static CustomRoles GetBetrayalAddon(this PlayerControl pc, bool forRecruiter = false) + { + //Soulless and Egoist are excluded because they don't actually change player's team. + List BTAddonList = pc.GetCustomSubRoles().Where(x => x.IsBetrayalAddonV2() && x is not CustomRoles.Soulless and not CustomRoles.Egoist).ToList(); + + //Get player's betrayal add-on,NotAssigned if player doesn't have betrayal addon + var addon = BTAddonList.Any() ? BTAddonList.FirstOrDefault() : CustomRoles.NotAssigned; + + //for recruiting roles to get their respective betrayal add-on + if (forRecruiter) + { + if (addon is CustomRoles.NotAssigned) + return pc.GetCustomRole() switch //default addon for recruiting roles + { + CustomRoles.Admirer => CustomRoles.Admired, + CustomRoles.Gangster or CustomRoles.Godfather => CustomRoles.Madmate, + CustomRoles.CursedSoul => CustomRoles.Soulless, + CustomRoles.Cultist => CustomRoles.Charmed, + CustomRoles.Infectious => CustomRoles.Infected, + CustomRoles.Jackal => CustomRoles.Recruit, + CustomRoles.Virus => CustomRoles.Contagious, + CustomRoles.Ritualist => CustomRoles.Enchanted, + _ => addon + }; + } + + return addon; + } + + public static bool CanBeRecruitedBy(this PlayerControl target, PlayerControl recruiter) + { + var addon = recruiter.GetBetrayalAddon(forRecruiter: true); + //Mini shouldn't be recruited + if (target.GetCustomRole() is CustomRoles.NiceMini or CustomRoles.EvilMini && Mini.Age < 18) return false; + + //loyal can't be recruited + if (target.Is(CustomRoles.Loyal)) return false; + + //target already has this addon + else if (target.Is(addon)) return false; + + //settings disabled,hurried cant be recruited + else if (target.Is(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) return false; + + return addon switch + { + CustomRoles.Charmed => Cultist.CanBeCharmed(target), + CustomRoles.Madmate => recruiter.Is(CustomRoles.Gangster) ? target.CanBeMadmate(forGangster: true) : target.CanBeMadmate(forAdmirer: true), + CustomRoles.Admired => Admirer.CanBeAdmired(target, recruiter), + CustomRoles.Enchanted => Ritualist.CanBeConverted(target), + CustomRoles.Recruit => Jackal.CanBeSidekick(target), + CustomRoles.Infected => Infectious.CanBeBitten(target), + CustomRoles.Contagious => target.CanBeInfected(), + CustomRoles.Soulless => CursedSoul.CanBeSoulless(target),//Cursed Soul recruits players to Soulless by default + _ => false + }; + } + public static bool IsPlayerImpostorTeam(this PlayerControl player, bool onlyMainRole = false) => Main.PlayerStates.TryGetValue(player.PlayerId, out var state) && state.IsPlayerImpostorTeam(onlyMainRole); public static bool IsPlayerImpostorTeam(this PlayerState player, bool onlyMainRole = false) { From 94250d59a34da3c50b9e361e08d2a7f42f88b84a Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Thu, 6 Mar 2025 23:58:13 +0800 Subject: [PATCH 02/43] admirer --- Roles/Crewmate/Admirer.cs | 65 ++++++--------------------------------- 1 file changed, 10 insertions(+), 55 deletions(-) diff --git a/Roles/Crewmate/Admirer.cs b/Roles/Crewmate/Admirer.cs index ba583a142d..65145a0a3f 100644 --- a/Roles/Crewmate/Admirer.cs +++ b/Roles/Crewmate/Admirer.cs @@ -16,7 +16,7 @@ internal class Admirer : RoleBase //===========================SETUP================================\\ public override CustomRoles Role => CustomRoles.Admirer; private const int Id = 24800; - public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.Admired); + public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.Admirer); public override bool IsDesyncRole => true; public override CustomRoles ThisRoleBase => CustomRoles.Impostor; public override Custom_RoleType ThisRoleType => Custom_RoleType.CrewmatePower; @@ -82,7 +82,8 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t if (!AdmiredList.ContainsKey(killer.PlayerId)) AdmiredList.Add(killer.PlayerId, []); - if (CanBeAdmired(target, killer)) + var addon = killer.GetBetrayalAddon(true); + if (killer.GetAbilityUseLimit() > 0) { if (KnowTargetRole.GetBool()) { @@ -90,55 +91,12 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list } - if (!killer.Is(CustomRoles.Madmate) && !killer.Is(CustomRoles.Recruit) && !killer.Is(CustomRoles.Charmed) - && !killer.Is(CustomRoles.Infected) && !killer.Is(CustomRoles.Contagious) && !killer.Is(CustomRoles.Enchanted)) + if (target.CanBeRecruitedBy(killer)) { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Admired.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Admired); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admirer), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admirer), GetString("AdmirerAdmired"))); - } - else if (killer.Is(CustomRoles.Madmate) && target.CanBeMadmate(forAdmirer: true)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Madmate.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Madmate); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetString("AdmirerAdmired"))); - } - else if (killer.Is(CustomRoles.Enchanted) && Ritualist.CanBeConverted(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Enchanted.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Enchanted); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Enchanted), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Enchanted), GetString("AdmirerAdmired"))); - } - else if (killer.Is(CustomRoles.Recruit) && Jackal.CanBeSidekick(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Recruit.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Recruit); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Recruit), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Recruit), GetString("AdmirerAdmired"))); - } - else if (killer.Is(CustomRoles.Charmed) && Cultist.CanBeCharmed(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Charmed.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Charmed); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Charmed), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Charmed), GetString("AdmirerAdmired"))); - } - else if (killer.Is(CustomRoles.Infected) && target.CanBeInfected()) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Infected.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Infected); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infected), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infected), GetString("AdmirerAdmired"))); - } - else if (killer.Is(CustomRoles.Contagious) && target.CanBeInfected()) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Contagious.ToString(), "Admirer Assign"); - target.RpcSetCustomRole(CustomRoles.Contagious); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Contagious), GetString("AdmiredPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Contagious), GetString("AdmirerAdmired"))); + Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + addon.ToString(), "Admirer Assign"); + target.RpcSetCustomRole(addon); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("AdmiredPlayer"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("AdmirerAdmired"))); } else goto AdmirerFailed; @@ -160,7 +118,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t AdmirerFailed: - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admirer), GetString("AdmirerInvalidTarget"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("AdmirerInvalidTarget"))); return false; } @@ -191,10 +149,7 @@ public static bool CanBeAdmired(PlayerControl pc, PlayerControl admirer) } else AdmiredList.Add(admirer.PlayerId, []); - return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || pc.GetCustomRole().IsNeutral() || pc.GetCustomRole().IsCoven()) - && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Lovers) && !pc.Is(CustomRoles.Loyal) - && !((pc.Is(CustomRoles.NiceMini) || pc.Is(CustomRoles.EvilMini)) && Mini.Age < 18) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()); + return pc != null; } public override void SetAbilityButtonText(HudManager hud, byte playerId) From 181af650ae8573e1ecd1ec518e01279183153b5a Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 00:05:23 +0800 Subject: [PATCH 03/43] gangster --- Roles/Impostor/Gangster.cs | 64 +++++++------------------------------- 1 file changed, 12 insertions(+), 52 deletions(-) diff --git a/Roles/Impostor/Gangster.cs b/Roles/Impostor/Gangster.cs index e131b681df..e157509198 100644 --- a/Roles/Impostor/Gangster.cs +++ b/Roles/Impostor/Gangster.cs @@ -74,60 +74,20 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t return true; } + var addon = killer.GetBetrayalAddon(true); if (CanRecruit(killer.PlayerId)) { - if (!killer.Is(CustomRoles.Admired) && !killer.Is(CustomRoles.Recruit) && !killer.Is(CustomRoles.Charmed) - && !killer.Is(CustomRoles.Infected) && !killer.Is(CustomRoles.Contagious) && !killer.Is(CustomRoles.Enchanted) && target.CanBeMadmate(forGangster: true) - && CanBeGansterRecruit(target)) + if (target.CanBeRecruitedBy(killer)) { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Madmate.ToString(), "Ganster Assign"); - target.RpcSetCustomRole(CustomRoles.Madmate); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetString("BeRecruitedByGangster"))); - } - else if (killer.Is(CustomRoles.Admired) && Admirer.CanBeAdmired(target, killer)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Admired.ToString(), "Ganster Assign"); - target.RpcSetCustomRole(CustomRoles.Admired); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admired), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admired), GetString("BeRecruitedByGangster"))); - Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); - Admirer.SendRPC(killer.PlayerId, target.PlayerId); - } - else if (killer.Is(CustomRoles.Enchanted) && Ritualist.CanBeConverted(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Enchanted.ToString(), "Gangster Assign"); - target.RpcSetCustomRole(CustomRoles.Enchanted); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Enchanted), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Enchanted), GetString("BeRecruitedByGangster"))); - } - else if (killer.Is(CustomRoles.Recruit) && Jackal.CanBeSidekick(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Recruit.ToString(), "Ganster Assign"); - target.RpcSetCustomRole(CustomRoles.Recruit); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Recruit), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Recruit), GetString("BeRecruitedByGangster"))); - } - else if (killer.Is(CustomRoles.Charmed) && Cultist.CanBeCharmed(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Charmed.ToString(), "Ganster Assign"); - target.RpcSetCustomRole(CustomRoles.Charmed); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Charmed), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Charmed), GetString("BeRecruitedByGangster"))); - } - else if (killer.Is(CustomRoles.Infected) && Infectious.CanBeBitten(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Infected.ToString(), "Ganster Assign"); - target.RpcSetCustomRole(CustomRoles.Infected); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infected), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infected), GetString("BeRecruitedByGangster"))); - } - else if (killer.Is(CustomRoles.Contagious) && target.CanBeInfected()) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Contagious.ToString(), "Ganster Assign"); - target.RpcSetCustomRole(CustomRoles.Contagious); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Contagious), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Contagious), GetString("BeRecruitedByGangster"))); + Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + addon.ToString(), "Gangster Assign"); + target.RpcSetCustomRole(addon); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("GangsterSuccessfullyRecruited"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("BeRecruitedByGangster"))); + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); + } } else goto GangsterFailed; @@ -145,7 +105,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t GangsterFailed: - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Gangster), GetString("GangsterRecruitmentFailure"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("GangsterRecruitmentFailure"))); Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer, ForceLoop: true); return true; From db7d8a6da6385e70c5d371a4a0596b56fe612e4b Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 00:23:02 +0800 Subject: [PATCH 04/43] godfather --- Roles/Impostor/Godfather.cs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/Roles/Impostor/Godfather.cs b/Roles/Impostor/Godfather.cs index 19d0674e43..a4da36cee0 100644 --- a/Roles/Impostor/Godfather.cs +++ b/Roles/Impostor/Godfather.cs @@ -1,4 +1,5 @@ using TOHE.Roles.Core; +using TOHE.Roles.Double; using static TOHE.Translator; using static TOHE.Utils; @@ -52,39 +53,49 @@ public override void Remove(byte playerId) private void CheckDeadBody(PlayerControl killer, PlayerControl target, bool inMeeting) { var godfather = _Player; - List BTAddonList = godfather.GetCustomSubRoles().Where(x => x.IsBetrayalAddonV2()).ToList(); - //this list will only contain 1 element,or just be an empty list... - var ChangeRole = BTAddonList.Any() ? BTAddonList.FirstOrDefault() switch + var ChangeAddon = godfather.GetBetrayalAddon(true); + var ChangeRole = ChangeAddon switch { CustomRoles.Admired => CustomRoles.Sheriff, CustomRoles.Recruit => CustomRoles.Sidekick, _ => CustomRoles.Refugee - } - : CustomRoles.Refugee; - var ChangeAddon = BTAddonList.Any() ? BTAddonList.FirstOrDefault() : CustomRoles.Madmate; + }; + if (GodfatherTarget.Contains(target.PlayerId)) { - if (!killer.IsAlive()) return; + if (!killer.IsAlive() || killer == godfather) return; if (GodfatherChangeOpt.GetValue() == 0) { + if ((killer.GetCustomRole() + is CustomRoles.NiceMini + or CustomRoles.EvilMini && Mini.Age < 18) + || killer.Is(CustomRoles.Loyal)) return; + killer.RpcChangeRoleBasis(ChangeRole); killer.GetRoleClass()?.OnRemove(killer.PlayerId); killer.RpcSetCustomRole(ChangeRole); killer.GetRoleClass()?.OnAdd(killer.PlayerId); if (ChangeRole is CustomRoles.Refugee - && (ChangeAddon is not CustomRoles.Madmate || godfather.Is(CustomRoles.Madmate)))//Can Godfather become Madmate? + && godfather.GetBetrayalAddon() != CustomRoles.NotAssigned) killer.RpcSetCustomRole(ChangeAddon); } else { + if (!killer.CanBeRecruitedBy(godfather)) return; killer.RpcSetCustomRole(ChangeAddon); } + if (ChangeAddon is CustomRoles.Admired) + { + AdmiredList[killer.PlayerId].Add(target.PlayerId); + SendRPC(killer.PlayerId, target.PlayerId);// make sure Admired Godfather can see Sheriff/Admired + } + killer.RpcGuardAndKill(); killer.ResetKillCooldown(); killer.SetKillCooldown(); - killer.Notify(ColorString(GetRoleColor(CustomRoles.Godfather), GetString("GodfatherRefugeeMsg"))); + killer.Notify(ColorString(GetRoleColor(addon), GetString("GodfatherRefugeeMsg"))); NotifyRoles(killer); } } From e009a17b4651b8380e041b3884a5f8124949743b Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 00:47:30 +0800 Subject: [PATCH 05/43] cultist --- Roles/Neutral/Cultist.cs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/Roles/Neutral/Cultist.cs b/Roles/Neutral/Cultist.cs index 308eac1553..0b17f960fd 100644 --- a/Roles/Neutral/Cultist.cs +++ b/Roles/Neutral/Cultist.cs @@ -1,6 +1,7 @@ using TOHE.Modules; using TOHE.Roles.AddOns.Crewmate; using TOHE.Roles.Core; +using TOHE.Roles.Crewmate; using TOHE.Roles.Double; using UnityEngine; using static TOHE.Options; @@ -68,27 +69,35 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cultist), GetString("CantRecruit"))); return false; } - else if (CanBeCharmed(target) && Mini.Age == 18 || CanBeCharmed(target) && Mini.Age < 18 && !(target.Is(CustomRoles.NiceMini) || target.Is(CustomRoles.EvilMini))) + + else if (target.CanBeRecruitedBy(killer)) { + var addon = killer.GetBetrayalAddon(true); killer.RpcRemoveAbilityUse(); - target.RpcSetCustomRole(CustomRoles.Charmed); + target.RpcSetCustomRole(addon); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cultist), GetString("CultistCharmedPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cultist), GetString("CharmedByCultist"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("CultistCharmedPlayer"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("CharmedByCultist"))); Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer, ForceLoop: true); + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); + } + killer.ResetKillCooldown(); killer.SetKillCooldown(); if (!DisableShieldAnimations.GetBool()) killer.RpcGuardAndKill(target); target.RpcGuardAndKill(killer); target.RpcGuardAndKill(target); - Logger.Info(target?.Data?.PlayerName + " = " + target.GetCustomRole().ToString() + " + " + CustomRoles.Charmed.ToString(), "Assign " + CustomRoles.Charmed.ToString()); + Logger.Info(target?.Data?.PlayerName + " = " + target.GetCustomRole().ToString() + " + " + addon.ToString(), "Assign " + addon.ToString()); return false; } - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cultist), GetString("CultistInvalidTarget"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("CultistInvalidTarget"))); return false; } public static bool TargetKnowOtherTargets => TargetKnowOtherTarget.GetBool(); @@ -107,10 +116,8 @@ public static bool CanBeCharmed(PlayerControl pc) { return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || (CanCharmNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || - (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Charmed) - && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Infectious) - && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Enchanted) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()); + (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) + && (!pc.Is(CustonRoles.Cultist) || pc.GetBetrayalAddon(true) != CustomRoles.Charmed); } public static bool NameRoleColor(PlayerControl seer, PlayerControl target) { From 17239b0f9ae2e99b34b5dd6f5cd918fc77120dd5 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 00:51:46 +0800 Subject: [PATCH 06/43] cursed soul --- Roles/Neutral/CursedSoul.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Roles/Neutral/CursedSoul.cs b/Roles/Neutral/CursedSoul.cs index 5e8a8cd96a..8af200b53a 100644 --- a/Roles/Neutral/CursedSoul.cs +++ b/Roles/Neutral/CursedSoul.cs @@ -1,4 +1,5 @@ using TOHE.Modules; +using TOHE.Roles.Crewmate; using TOHE.Roles.Double; using UnityEngine; using static TOHE.Options; @@ -51,13 +52,20 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cultist), GetString("CantRecruit"))); return false; } - if (CanBeSoulless(target)) + if (target.CanBeRecruitedBy(killer)) { + var addon = killer.GetBetrayalAddon(true)) killer.RpcRemoveAbilityUse(); - target.RpcSetCustomRole(CustomRoles.Soulless); + target.RpcSetCustomRole(addon); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.CursedSoul), GetString("CursedSoulSoullessPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.CursedSoul), GetString("SoullessByCursedSoul"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("CursedSoulSoullessPlayer"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("SoullessByCursedSoul"))); + + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + } Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer, ForceLoop: true); Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true); @@ -68,7 +76,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t if (!DisableShieldAnimations.GetBool()) killer.RpcGuardAndKill(target); - Logger.Info($"{target?.Data?.PlayerName} = {target.GetCustomRole()} + {CustomRoles.Soulless}", $"Assign {CustomRoles.Soulless}"); + Logger.Info($"{target?.Data?.PlayerName} = {target.GetCustomRole()} + {addon}", $"Assign {addon}"); return false; } killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.CursedSoul), GetString("CursedSoulInvalidTarget"))); @@ -84,7 +92,7 @@ private static bool CanBeSoulless(PlayerControl pc) { return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || (CanCurseNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || - (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Loyal); + (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From 0e16c9d0591ff67a08edced9c5e97cc6d62aa4b1 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 01:27:17 +0800 Subject: [PATCH 07/43] jackal --- Roles/Neutral/Jackal.cs | 146 +++++++++++++++++++++++++--------------- 1 file changed, 90 insertions(+), 56 deletions(-) diff --git a/Roles/Neutral/Jackal.cs b/Roles/Neutral/Jackal.cs index 82815276ed..fdd9d28ca8 100644 --- a/Roles/Neutral/Jackal.cs +++ b/Roles/Neutral/Jackal.cs @@ -1,6 +1,8 @@ using AmongUs.GameOptions; using TOHE.Modules; +using TOHE.Roles.Crewmate; using TOHE.Roles.Core; +using TOHE.Roles.Double; using static TOHE.Options; using static TOHE.Translator; @@ -107,17 +109,16 @@ public override void Init() } public override void Add(byte playerId) { - playerId.SetAbilityUseLimit(0); + playerId.SetAbilityUseLimit(SidekickRecruitLimitOpt.GetInt()); hasConverted = false; - if (Playerids.Count == 0 || RestoreLimitOnNewJackal.GetBool()) - { - playerId.SetAbilityUseLimit(CanRecruitSidekick.GetBool() ? SidekickRecruitLimitOpt.GetInt() : 0); - } - if (!Playerids.Contains(playerId)) Playerids.Add(playerId); + if ((Playerids.Count > 1 && !RestoreLimitOnNewJackal.GetBool()) + || !CanRecruitSidekick.GetBool()) + playerId.SetAbilityUseLimit(0); + if (AmongUsClient.Instance.AmHost) { CustomRoleManager.CheckDeadBodyOthers.Add(OthersPlayersDead); @@ -171,56 +172,65 @@ private void OthersPlayersDead(PlayerControl killer, PlayerControl target, bool public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl target) { + var addon = killer.GetBetrayalAddon(true); + var role = addon switch + { + CustomRoles.Admired => CustomRoles.Sheriff, + CustomRoles.Madmate => CustomRoles.Refugee, + _ => CustomRoles.Sidekick + }; + if (target.Is(CustomRoles.Jackal)) return false; - if ((target.Is(CustomRoles.Recruit) || target.Is(CustomRoles.Sidekick))) return JackalCanKillSidekick.GetBool(); + if (target.Is(addon) || target.Is(role)) return JackalCanKillSidekick.GetBool(); + if (!CanRecruitSidekick.GetBool() || !CanRecruit()) { Logger.Info("Jackal run out of recruits or Recruit disabled?", "Jackal"); return true; } - if (!CanRecruitCoven.GetBool() && target.IsPlayerCovenTeam() || !CanRecruitNeutral.GetBool() && target.IsPlayerNeutralTeam() || !CanRecruitImpostor.GetBool() && target.IsPlayerImpostorTeam() || target.IsNeutralApocalypse()) - { - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("Jackal_RecruitFailed"))); - Logger.Info("Jackal can not recruit this target", "Jackal"); - return true; - } - if (target.Is(CustomRoles.Loyal) - || SidekickAssignMode.GetInt() == 2 && (target.Is(CustomRoles.Cleansed) || target.Is(CustomRoles.Stubborn))) - { - // Loyal or Only Recruit & can not get addon - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("Jackal_RecruitFailed"))); - return true; - } - - if (target.IsAnySubRole(x => (x.IsConverted() || x == CustomRoles.Admired) && x != CustomRoles.Recruit)) - { - // Remove other team converted roles first - foreach (var x in target.GetCustomSubRoles()) - { - if (x.IsConverted() && x != CustomRoles.Recruit) - { - Main.PlayerStates[target.PlayerId].RemoveSubRole(x); - Main.PlayerStates[target.PlayerId].SubRoles.Remove(CustomRoles.Rascal); - Main.PlayerStates[target.PlayerId].SubRoles.Remove(CustomRoles.Admired); - } - } - } + bool TargetCanBeSidekick = (CanRecruitCoven.GetBool() && target.IsPlayerCovenTeam()) + || (CanRecruitNeutral.GetBool() && target.IsPlayerNeutralTeam() && !target.GetCustomRole().IsNA()) + || (CanRecruitImpostor.GetBool() && target.IsPlayerImpostorTeam()) + || target.IsPlayerCrewmateTeam(); switch (SidekickAssignMode.GetInt()) { case 1: // Only SideKick - + if (!TargetCanBeSidekick) + { + killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("Jackal_RecruitFailed"))); + return true; + } killer.RpcRemoveAbilityUse(); - Logger.Info($"Jackal {killer.GetNameWithRole()} assigned SideKick to {target.GetNameWithRole()}", "Jackal"); + Logger.Info($"Jackal {killer.GetNameWithRole()} assigned {role} to {target.GetNameWithRole()}", "Jackal"); + + // Remove other team converted roles first + foreach (var x in target.GetCustomSubRoles()) + { + if (x.IsBetrayalAddonV2() && x != addon) + { + Main.PlayerStates[target.PlayerId].RemoveSubRole(x); + Main.PlayerStates[target.PlayerId].SubRoles.Remove(CustomRoles.Rascal); + } + } target.GetRoleClass()?.OnRemove(target.PlayerId); - target.RpcChangeRoleBasis(CustomRoles.Sidekick); - target.RpcSetCustomRole(CustomRoles.Sidekick); + target.RpcChangeRoleBasis(role); + target.RpcSetCustomRole(role); target.GetRoleClass()?.OnAdd(target.PlayerId); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("BeRecruitedByJackal"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(role), GetString("GangsterSuccessfullyRecruited"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(role), GetString("BeRecruitedByJackal"))); + + if (role is CustomRoles.Sheriff) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + } // if this doesnt exist ,Admired Jackal may not be able to see Sheriff recruited by them + + if (role is CustomRoles.Sidekick && killer.GetBetrayalAddon() != CustomRoles.NotAssigned) + target.RpcSetCustomRole(addon); Utils.NotifyRoles(killer, target, true); Utils.NotifyRoles(target, killer, true); @@ -231,18 +241,24 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t killer.SetKillCooldown(forceAnime: !DisableShieldAnimations.GetBool()); break; case 2: // Only Recruit - if (target.GetCustomRole().IsNeutral() && target.HasImpKillButton() || target.Is(CustomRoles.Lawyer)) + if (!target.CanBeRecruitedBy(killer)) { killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("Jackal_RecruitFailed"))); return true; } killer.RpcRemoveAbilityUse(); - Logger.Info($"Jackal {killer.GetNameWithRole()} assigned Recruit to {target.GetNameWithRole()}", "Jackal"); - target.RpcSetCustomRole(CustomRoles.Recruit); + Logger.Info($"Jackal {killer.GetNameWithRole()} assigned {addon} to {target.GetNameWithRole()}", "Jackal"); + target.RpcSetCustomRole(addon); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("BeRecruitedByJackal"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("GangsterSuccessfullyRecruited"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("BeRecruitedByJackal"))); + + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + } Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer, ForceLoop: true); @@ -252,24 +268,45 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t target.ResetKillCooldown(); target.SetKillCooldown(forceAnime: true); - Main.PlayerStates[target.PlayerId].taskState.hasTasks = false; break; case 0: // SideKick when failed Recruit - if (target.GetCustomRole().IsNeutral() && target.HasImpKillButton() || target.Is(CustomRoles.Lawyer)) + if (TargetCanBeSidekick) { + // Remove other team converted roles first + foreach (var x in target.GetCustomSubRoles()) + { + if (x.IsBetrayalAddonV2() && x != addon) + { + Main.PlayerStates[target.PlayerId].RemoveSubRole(x); + Main.PlayerStates[target.PlayerId].SubRoles.Remove(CustomRoles.Rascal); + } + } target.GetRoleClass()?.OnRemove(target.PlayerId); - target.RpcChangeRoleBasis(CustomRoles.Sidekick); - target.RpcSetCustomRole(CustomRoles.Sidekick); + target.RpcChangeRoleBasis(role); + target.RpcSetCustomRole(role); target.GetRoleClass()?.OnAdd(target.PlayerId); + if (role is CustomRoles.Sidekick && killer.GetBetrayalAddon() != CustomRoles.NotAssigned) + target.RpcSetCustomRole(addon); + } + else if (!target.CanBeRecruitedBy(killer)) + { + killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("Jackal_RecruitFailed"))); + return true; } else { - target.RpcSetCustomRole(CustomRoles.Recruit); + target.RpcSetCustomRole(addon); } killer.RpcRemoveAbilityUse(); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("GangsterSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Jackal), GetString("BeRecruitedByJackal"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("GangsterSuccessfullyRecruited"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("BeRecruitedByJackal"))); + + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + } Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer, ForceLoop: true); @@ -358,10 +395,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t // very very Long Dog shit lmao public static bool CanBeSidekick(PlayerControl pc) { - return pc != null && !pc.Is(CustomRoles.Sidekick) && !pc.Is(CustomRoles.Recruit) - && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Rascal) && !pc.Is(CustomRoles.Madmate) - && !pc.Is(CustomRoles.Charmed) && !pc.Is(CustomRoles.Infected) && !pc.Is(CustomRoles.Paranoia) - && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Enchanted) && pc.GetCustomRole().IsAbleToBeSidekicked(); + return pc != null && !pc.Is(CustomRoles.Sidekick); } public override void OnMurderPlayerAsTarget(PlayerControl killer, PlayerControl target, bool inMeeting, bool isSuidice) From d748dd8883035c6fe890712444f689aedc3f8859 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 01:36:53 +0800 Subject: [PATCH 08/43] infectious --- Roles/Neutral/Infectious.cs | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/Roles/Neutral/Infectious.cs b/Roles/Neutral/Infectious.cs index ffeb0783b8..6302b5c57c 100644 --- a/Roles/Neutral/Infectious.cs +++ b/Roles/Neutral/Infectious.cs @@ -1,5 +1,6 @@ using AmongUs.GameOptions; using TOHE.Modules; +using TOHE.Roles.Crewmate; using TOHE.Roles.Double; using static TOHE.Options; using static TOHE.Translator; @@ -62,16 +63,23 @@ public override void Add(byte playerId) private static bool InfectOrMurder(PlayerControl killer, PlayerControl target) { - if (CanBeBitten(target)) + var addon = killer.GetBetrayalAddon(true); + if (target.CanBeRecruitedBy(killer)) { killer.RpcRemoveAbilityUse(); - target.RpcSetCustomRole(CustomRoles.Infected); + target.RpcSetCustomRole(addon); + + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + } Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target, ForceLoop: true); Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer, ForceLoop: true); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infectious), GetString("InfectiousBittenPlayer"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infectious), GetString("BittenByInfectious"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("InfectiousBittenPlayer"))); + target.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("BittenByInfectious"))); killer.ResetKillCooldown(); killer.SetKillCooldown(); @@ -81,7 +89,7 @@ private static bool InfectOrMurder(PlayerControl killer, PlayerControl target) target.RpcGuardAndKill(killer); target.RpcGuardAndKill(target); - Logger.Info("设置职业:" + target?.Data?.PlayerName + " = " + target.GetCustomRole().ToString() + " + " + CustomRoles.Infected.ToString(), "Assign " + CustomRoles.Infected.ToString()); + Logger.Info("设置职业:" + target?.Data?.PlayerName + " = " + target.GetCustomRole().ToString() + " + " + addon.ToString(), "Assign " + addon.ToString()); if (killer.GetAbilityUseLimit() < 0) { @@ -91,7 +99,7 @@ private static bool InfectOrMurder(PlayerControl killer, PlayerControl target) return true; } - if (!CanBeBitten(target) && !target.Is(CustomRoles.Infected) && !target.IsTransformedNeutralApocalypse()) + if (!target.CanBeRecruitedBy(killer) && !target.Is(addon) && !target.IsTransformedNeutralApocalypse()) { killer.RpcMurderPlayer(target); } @@ -127,13 +135,13 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t } public override void OnPlayerExiled(PlayerControl player, NetworkedPlayerInfo exiled) { - if (!player.IsAlive()) + if (!player.IsAlive() && player.GetBetrayalAddon(true) is CustomRoles.Infected) { foreach (var alivePlayer in Main.AllAlivePlayerControls.Where(pc => pc.Is(CustomRoles.Infected))) { alivePlayer.SetDeathReason(PlayerState.DeathReason.Infected); alivePlayer.RpcMurderPlayer(alivePlayer); - alivePlayer.SetRealKiller(Utils.GetPlayerById(PlayerIds.First())); + alivePlayer.SetRealKiller(player); } } } @@ -157,14 +165,11 @@ public static bool InfectedKnowColorOthersInfected(PlayerControl player, PlayerC public static bool CanBeBitten(PlayerControl pc) { return pc != null && (pc.GetCustomRole().IsCrewmate() - || pc.GetCustomRole().IsImpostor() + || pc.GetCustomRole().IsImpostorTeamV3() || pc.GetCustomRole().IsNK() - || pc.GetCustomRole().IsCoven()) && !pc.Is(CustomRoles.Infected) - && !pc.Is(CustomRoles.Admired) - && !pc.Is(CustomRoles.Loyal) - && !pc.Is(CustomRoles.Cultist) - && !pc.Is(CustomRoles.Enchanted) - && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Virus) && !pc.IsTransformedNeutralApocalypse(); + || pc.GetCustomRole().IsCoven()) + (&& !pc.Is(CustomRoles.Infectious) || pc.GetBetrayalAddon(true) != CustomRoles.Infected) + && !pc.IsTransformedNeutralApocalypse(); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From ae346163f35a5b24c3fb11f37300b6a3f0a27a95 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 01:46:01 +0800 Subject: [PATCH 09/43] virus --- Roles/Neutral/Virus.cs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Roles/Neutral/Virus.cs b/Roles/Neutral/Virus.cs index 3e9df7623a..d41de001b1 100644 --- a/Roles/Neutral/Virus.cs +++ b/Roles/Neutral/Virus.cs @@ -3,6 +3,7 @@ using TOHE.Modules; using TOHE.Roles.AddOns.Crewmate; using TOHE.Roles.Core; +using TOHE.Roles.Crewmate; using static TOHE.MeetingHudStartPatch; using static TOHE.Options; using static TOHE.Translator; @@ -83,19 +84,30 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t public override void OnReportDeadBody(PlayerControl reporter, NetworkedPlayerInfo target) { if (target == null || !InfectedBodies.Contains(target.PlayerId)) return; - if (_Player == null || !reporter.CanBeInfected()) return; - - _Player.RpcRemoveAbilityUse(); + if (_Player == null) return; if (KillInfectedPlayerAfterMeeting.GetBool()) { + if (!reporter.CanBeInfected()) return; + + _Player.RpcRemoveAbilityUse(); InfectedPlayer.Add(reporter.PlayerId); VirusNotify[reporter.PlayerId] = GetString("VirusNoticeMessage2"); } else { - reporter.RpcSetCustomRole(CustomRoles.Contagious); + if (!reporter.CanBeRecruitedBy(_Player)) return; + + var addon = _Player.GetBetrayalAddon(true); + _Player.RpcRemoveAbilityUse(); + reporter.RpcSetCustomRole(addon); VirusNotify[reporter.PlayerId] = GetString("VirusNoticeMessage"); + + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + } } Logger.Info("Setting up a career:" + reporter?.Data?.PlayerName + " = " + reporter.GetCustomRole().ToString() + " + " + CustomRoles.Contagious.ToString(), "Assign " + CustomRoles.Contagious.ToString()); @@ -159,8 +171,7 @@ public static class VirusPlayerControls { public static bool CanBeInfected(this PlayerControl pc) { - return true && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Loyal) - && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Specter) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()); + return pc != null && !pc.Is(CustomRoles.Virus) + && !pc.GetCustomRole().IsTNA(); } } From ad75c32f7903111997c511815791a8f1fe92ad9a Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 01:57:13 +0800 Subject: [PATCH 10/43] build error --- Roles/Neutral/CursedSoul.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Neutral/CursedSoul.cs b/Roles/Neutral/CursedSoul.cs index 8af200b53a..b018cc6be3 100644 --- a/Roles/Neutral/CursedSoul.cs +++ b/Roles/Neutral/CursedSoul.cs @@ -54,7 +54,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t } if (target.CanBeRecruitedBy(killer)) { - var addon = killer.GetBetrayalAddon(true)) + var addon = killer.GetBetrayalAddon(true); killer.RpcRemoveAbilityUse(); target.RpcSetCustomRole(addon); From 31f3c66bedde0b402cf67de046e7832760969864 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 01:59:03 +0800 Subject: [PATCH 11/43] build error v2 --- Roles/Neutral/Infectious.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Neutral/Infectious.cs b/Roles/Neutral/Infectious.cs index 6302b5c57c..7c6c587452 100644 --- a/Roles/Neutral/Infectious.cs +++ b/Roles/Neutral/Infectious.cs @@ -168,7 +168,7 @@ public static bool CanBeBitten(PlayerControl pc) || pc.GetCustomRole().IsImpostorTeamV3() || pc.GetCustomRole().IsNK() || pc.GetCustomRole().IsCoven()) - (&& !pc.Is(CustomRoles.Infectious) || pc.GetBetrayalAddon(true) != CustomRoles.Infected) + && !pc.Is(CustomRoles.Infectious) && !pc.IsTransformedNeutralApocalypse(); } public override void SetAbilityButtonText(HudManager hud, byte playerId) From 74f1d59b96ed43ea254669dd755776bfc520961b Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:01:00 +0800 Subject: [PATCH 12/43] why does Jackal.HasEnabled check Jailer? --- Roles/Neutral/Jackal.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Neutral/Jackal.cs b/Roles/Neutral/Jackal.cs index fdd9d28ca8..167f668b75 100644 --- a/Roles/Neutral/Jackal.cs +++ b/Roles/Neutral/Jackal.cs @@ -13,7 +13,7 @@ internal class Jackal : RoleBase //===========================SETUP================================\\ public override CustomRoles Role => CustomRoles.Jackal; private const int Id = 16700; - public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.Jailer); + public static bool HasEnabled => CustomRoleManager.HasEnabled(CustomRoles.Jackal); public static readonly HashSet Playerids = []; public override bool IsDesyncRole => true; public override CustomRoles ThisRoleBase => CustomRoles.Impostor; From 8e26ce98466d1e9306ba4a1a7b75ceef75545fd8 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:06:14 +0800 Subject: [PATCH 13/43] Update Virus.cs --- Roles/Neutral/Virus.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Roles/Neutral/Virus.cs b/Roles/Neutral/Virus.cs index d41de001b1..198f5d8fda 100644 --- a/Roles/Neutral/Virus.cs +++ b/Roles/Neutral/Virus.cs @@ -105,8 +105,8 @@ public override void OnReportDeadBody(PlayerControl reporter, NetworkedPlayerInf if (addon is CustomRoles.Admired) { - Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); - Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list + Admirer.AdmiredList[_Player.PlayerId].Add(repprter.PlayerId); + Admirer.SendRPC(_Player.PlayerId, reporter.PlayerId); //Sync playerId list } } From 145e302586d169f471d5298f3fdecabf627749ad Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:08:49 +0800 Subject: [PATCH 14/43] Update CustomRolesHelper.cs --- Modules/CustomRolesHelper.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 5ecb7d6a6d..078ba9cce1 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -4,6 +4,7 @@ using TOHE.Roles.AddOns.Crewmate; using TOHE.Roles.AddOns.Impostor; using TOHE.Roles.Core; +using TOHE.Roles.Coven; using TOHE.Roles.Crewmate; using TOHE.Roles.Double; using TOHE.Roles.Impostor; From fec017e5f130c2bcbb9962586643084b1d19df86 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:18:52 +0800 Subject: [PATCH 15/43] Update Cultist.cs --- Roles/Neutral/Cultist.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Roles/Neutral/Cultist.cs b/Roles/Neutral/Cultist.cs index 0b17f960fd..3aaf5e7a31 100644 --- a/Roles/Neutral/Cultist.cs +++ b/Roles/Neutral/Cultist.cs @@ -97,7 +97,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t Logger.Info(target?.Data?.PlayerName + " = " + target.GetCustomRole().ToString() + " + " + addon.ToString(), "Assign " + addon.ToString()); return false; } - killer.Notify(Utils.ColorString(Utils.GetRoleColor(addon), GetString("CultistInvalidTarget"))); + killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cultist), GetString("CultistInvalidTarget"))); return false; } public static bool TargetKnowOtherTargets => TargetKnowOtherTarget.GetBool(); @@ -117,7 +117,7 @@ public static bool CanBeCharmed(PlayerControl pc) return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || (CanCharmNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) - && (!pc.Is(CustonRoles.Cultist) || pc.GetBetrayalAddon(true) != CustomRoles.Charmed); + && (!pc.Is(CustomRoles.Cultist) || pc.GetBetrayalAddon(true) != CustomRoles.Charmed); } public static bool NameRoleColor(PlayerControl seer, PlayerControl target) { From 0bdc386780a0b6080dc2cc26be16269527045c6f Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:20:06 +0800 Subject: [PATCH 16/43] Update CursedSoul.cs --- Roles/Neutral/CursedSoul.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Neutral/CursedSoul.cs b/Roles/Neutral/CursedSoul.cs index b018cc6be3..dd73955e73 100644 --- a/Roles/Neutral/CursedSoul.cs +++ b/Roles/Neutral/CursedSoul.cs @@ -88,7 +88,7 @@ public override bool KnowRoleTarget(PlayerControl player, PlayerControl target) public override string PlayerKnowTargetColor(PlayerControl seer, PlayerControl target) => KnowRoleTarget(seer, target) ? Main.roleColors[CustomRoles.Soulless] : string.Empty; - private static bool CanBeSoulless(PlayerControl pc) + public static bool CanBeSoulless(PlayerControl pc) { return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || (CanCurseNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || From f28f42ce3a44f2aa48e695b3c499480e7a8485e6 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:22:05 +0800 Subject: [PATCH 17/43] Update Godfather.cs --- Roles/Impostor/Godfather.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Roles/Impostor/Godfather.cs b/Roles/Impostor/Godfather.cs index a4da36cee0..b67df4c33e 100644 --- a/Roles/Impostor/Godfather.cs +++ b/Roles/Impostor/Godfather.cs @@ -1,4 +1,5 @@ using TOHE.Roles.Core; +using TOHE.Roles.Crewmate; using TOHE.Roles.Double; using static TOHE.Translator; using static TOHE.Utils; @@ -88,8 +89,8 @@ is CustomRoles.NiceMini if (ChangeAddon is CustomRoles.Admired) { - AdmiredList[killer.PlayerId].Add(target.PlayerId); - SendRPC(killer.PlayerId, target.PlayerId);// make sure Admired Godfather can see Sheriff/Admired + Admirer.AdmiredList[godfather.PlayerId].Add(killer.PlayerId); + Admirer.SendRPC(godfather.PlayerId, killer.PlayerId);// make sure Admired Godfather can see Sheriff/Admired } killer.RpcGuardAndKill(); From 10380c0c6b510a16032d13d6ee68fc984906b9f8 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:28:53 +0800 Subject: [PATCH 18/43] Update Virus.cs --- Roles/Neutral/Virus.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Neutral/Virus.cs b/Roles/Neutral/Virus.cs index 198f5d8fda..915fc13f17 100644 --- a/Roles/Neutral/Virus.cs +++ b/Roles/Neutral/Virus.cs @@ -105,7 +105,7 @@ public override void OnReportDeadBody(PlayerControl reporter, NetworkedPlayerInf if (addon is CustomRoles.Admired) { - Admirer.AdmiredList[_Player.PlayerId].Add(repprter.PlayerId); + Admirer.AdmiredList[_Player.PlayerId].Add(reporter.PlayerId); Admirer.SendRPC(_Player.PlayerId, reporter.PlayerId); //Sync playerId list } } From 75ce4566a6e126dfeb207558fd578ea346a4b266 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:30:08 +0800 Subject: [PATCH 19/43] Update Godfather.cs --- Roles/Impostor/Godfather.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Impostor/Godfather.cs b/Roles/Impostor/Godfather.cs index b67df4c33e..fff7f913bb 100644 --- a/Roles/Impostor/Godfather.cs +++ b/Roles/Impostor/Godfather.cs @@ -96,7 +96,7 @@ is CustomRoles.NiceMini killer.RpcGuardAndKill(); killer.ResetKillCooldown(); killer.SetKillCooldown(); - killer.Notify(ColorString(GetRoleColor(addon), GetString("GodfatherRefugeeMsg"))); + killer.Notify(ColorString(GetRoleColor(ChangeAddon), GetString("GodfatherRefugeeMsg"))); NotifyRoles(killer); } } From 10ec7341a8ad8d43f78f58cac2f1fd319e7f2c98 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 02:38:56 +0800 Subject: [PATCH 20/43] ritualist --- Roles/Coven/Ritualist.cs | 68 +++++++--------------------------------- 1 file changed, 12 insertions(+), 56 deletions(-) diff --git a/Roles/Coven/Ritualist.cs b/Roles/Coven/Ritualist.cs index 608e43cd8e..ad54a1c95f 100644 --- a/Roles/Coven/Ritualist.cs +++ b/Roles/Coven/Ritualist.cs @@ -132,7 +132,7 @@ public static bool RitualistMsgCheck(PlayerControl pc, string msg, bool isUI = f RitualLimit[pc.PlayerId] = 0; return true; } - if (!CanBeConverted(target)) + if (!target.CanBeRecruitedBy(pc)) { pc.ShowInfoMessage(isUI, GetString("RitualistRitualImpossible")); return true; @@ -207,59 +207,17 @@ public override void AfterMeetingTasks() } public void ConvertRole(PlayerControl killer, PlayerControl target) { - if (!killer.Is(CustomRoles.Admired) && !killer.Is(CustomRoles.Recruit) && !killer.Is(CustomRoles.Charmed) - && !killer.Is(CustomRoles.Infected) && !killer.Is(CustomRoles.Contagious) && !killer.Is(CustomRoles.Madmate) - && CanBeConverted(target)) + var addon = killer.GetBetrayalAddon(true); + if (target.CanBeRecruitedBy(killer)) { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Enchanted.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Enchanted); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Enchanted), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Enchanted), GetString("BeRecruitedByRitualist"))); - } - else if (killer.Is(CustomRoles.Admired) && Admirer.CanBeAdmired(target, killer)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Admired.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Admired); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admired), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Admired), GetString("BeRecruitedByRitualist"))); - Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); - Admirer.SendRPC(killer.PlayerId, target.PlayerId); - } - else if (killer.Is(CustomRoles.Recruit) && Jackal.CanBeSidekick(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Recruit.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Recruit); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Recruit), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Recruit), GetString("BeRecruitedByRitualist"))); - } - else if (killer.Is(CustomRoles.Madmate) && target.CanBeMadmate(forAdmirer: true)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Madmate.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Madmate); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetString("BeRecruitedByRitualist"))); - } - else if (killer.Is(CustomRoles.Charmed) && Cultist.CanBeCharmed(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Charmed.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Charmed); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Charmed), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Charmed), GetString("BeRecruitedByRitualist"))); - } - else if (killer.Is(CustomRoles.Infected) && Infectious.CanBeBitten(target)) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Infected.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Infected); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infected), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Infected), GetString("BeRecruitedByRitualist"))); - } - else if (killer.Is(CustomRoles.Contagious) && target.CanBeInfected()) - { - Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + CustomRoles.Contagious.ToString(), "Ritualist Assign"); - target.RpcSetCustomRole(CustomRoles.Contagious); - killer.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Contagious), GetString("RitualistSuccessfullyRecruited"))); - target.Notify(Utils.ColorString(Utils.GetRoleColor(CustomRoles.Contagious), GetString("BeRecruitedByRitualist"))); - } + Logger.Info("Set converted: " + target.GetNameWithRole().RemoveHtmlTags() + " to " + addon.ToString(), "Ritualist Assign"); + target.RpcSetCustomRole(addon); + if (addon is CustomRoles.Admired) + { + Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); + Admirer.SendRPC(killer.PlayerId, target.PlayerId); + } + } } private static bool MsgToPlayerAndRole(string msg, out byte id, out CustomRoles role, out string error) { @@ -324,8 +282,6 @@ public static bool CheckCommond(ref string msg, string command, bool exact = tru } public static bool CanBeConverted(PlayerControl pc) { - return pc != null && (!pc.GetCustomRole().IsCovenTeam() && !pc.IsTransformedNeutralApocalypse()) && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Lovers) && !pc.Is(CustomRoles.Loyal) - && !((pc.Is(CustomRoles.NiceMini) || pc.Is(CustomRoles.EvilMini)) && Mini.Age < 18) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()); + return pc != null && (!pc.GetCustomRole().IsCovenTeam() && !pc.IsTransformedNeutralApocalypse()); } } From c47460379ef66a00a0afb5e34f69bd73f7292992 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 23:01:36 +0800 Subject: [PATCH 21/43] Update CheckGameEndPatch.cs --- Patches/CheckGameEndPatch.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Patches/CheckGameEndPatch.cs b/Patches/CheckGameEndPatch.cs index 184ac25457..162c3a2911 100644 --- a/Patches/CheckGameEndPatch.cs +++ b/Patches/CheckGameEndPatch.cs @@ -142,7 +142,8 @@ public static bool Prefix() } break; case CustomWinner.Cultist: - if ((pc.Is(CustomRoles.Charmed) || pc.Is(CustomRoles.Cultist)) && !WinnerIds.Contains(pc.PlayerId)) + if ((pc.Is(CustomRoles.Cultist) && (countType == CountTypes.Cultist || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) || + pc.Is(CustomRoles.Charmed) && !WinnerIds.Contains(pc.PlayerId)) { WinnerIds.Add(pc.PlayerId); } @@ -154,7 +155,8 @@ public static bool Prefix() } break; case CustomWinner.Infectious: - if ((pc.Is(CustomRoles.Infected) || pc.Is(CustomRoles.Infectious)) && !WinnerIds.Contains(pc.PlayerId)) + if ((pc.Is(CustomRoles.Infectious) && (countType == CountTypes.Infectious || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) || + pc.Is(CustomRoles.Infected) && !WinnerIds.Contains(pc.PlayerId)) { WinnerIds.Add(pc.PlayerId); } @@ -166,13 +168,15 @@ public static bool Prefix() } break; case CustomWinner.Virus: - if ((pc.Is(CustomRoles.Contagious) || pc.Is(CustomRoles.Virus)) && !WinnerIds.Contains(pc.PlayerId)) + if ((pc.Is(CustomRoles.Virus) && (countType == CountTypes.Virus || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) || + pc.Is(CustomRoles.Contagious) && !WinnerIds.Contains(pc.PlayerId)) { WinnerIds.Add(pc.PlayerId); } break; case CustomWinner.Jackal: - if ((pc.Is(CustomRoles.Sidekick) || pc.Is(CustomRoles.Recruit) || pc.Is(CustomRoles.Jackal)) && !WinnerIds.Contains(pc.PlayerId)) + if (((pc.Is(CustomRoles.Sidekick) || pc.Is(CustomRoles.Jackal)) && (countType == CountTypes.Cultist || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) || + pc.Is(CustomRoles.Recruit) && !WinnerIds.Contains(pc.PlayerId)) { WinnerIds.Add(pc.PlayerId); } From 0db19bb5a99c5e3532e47f832bea3e7a8df33d78 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Fri, 7 Mar 2025 23:08:32 +0800 Subject: [PATCH 22/43] cv moment --- Patches/CheckGameEndPatch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Patches/CheckGameEndPatch.cs b/Patches/CheckGameEndPatch.cs index 162c3a2911..e4708d84c8 100644 --- a/Patches/CheckGameEndPatch.cs +++ b/Patches/CheckGameEndPatch.cs @@ -175,7 +175,7 @@ public static bool Prefix() } break; case CustomWinner.Jackal: - if (((pc.Is(CustomRoles.Sidekick) || pc.Is(CustomRoles.Jackal)) && (countType == CountTypes.Cultist || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) || + if (((pc.Is(CustomRoles.Sidekick) || pc.Is(CustomRoles.Jackal)) && (countType == CountTypes.Jackal || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) || pc.Is(CustomRoles.Recruit) && !WinnerIds.Contains(pc.PlayerId)) { WinnerIds.Add(pc.PlayerId); From cf1dce9a669537abe8893ce4e17ccef3edf32ba1 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Thu, 13 Mar 2025 23:23:14 +0800 Subject: [PATCH 23/43] proved not working --- Roles/Neutral/Jackal.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Roles/Neutral/Jackal.cs b/Roles/Neutral/Jackal.cs index 167f668b75..68575be2da 100644 --- a/Roles/Neutral/Jackal.cs +++ b/Roles/Neutral/Jackal.cs @@ -223,12 +223,6 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t killer.Notify(Utils.ColorString(Utils.GetRoleColor(role), GetString("GangsterSuccessfullyRecruited"))); target.Notify(Utils.ColorString(Utils.GetRoleColor(role), GetString("BeRecruitedByJackal"))); - if (role is CustomRoles.Sheriff) - { - Admirer.AdmiredList[killer.PlayerId].Add(target.PlayerId); - Admirer.SendRPC(killer.PlayerId, target.PlayerId); //Sync playerId list - } // if this doesnt exist ,Admired Jackal may not be able to see Sheriff recruited by them - if (role is CustomRoles.Sidekick && killer.GetBetrayalAddon() != CustomRoles.NotAssigned) target.RpcSetCustomRole(addon); From 5c1191d8f8cc7f50e9d793ce529efeaeca8c2888 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 11:51:36 +0800 Subject: [PATCH 24/43] changes + add some more checks to IsPlayerXTeam --- Modules/CustomRolesHelper.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Modules/CustomRolesHelper.cs b/Modules/CustomRolesHelper.cs index 078ba9cce1..5d562eb681 100644 --- a/Modules/CustomRolesHelper.cs +++ b/Modules/CustomRolesHelper.cs @@ -469,6 +469,9 @@ public static bool CanBeRecruitedBy(this PlayerControl target, PlayerControl rec //settings disabled,hurried cant be recruited else if (target.Is(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) return false; + + //Coven Leader cant be recruited when they have the necronomicon + else if (CovenManager.HasNecronomicon(target.PlayerId) && target.Is(CustomRoles.CovenLeader)) return false; return addon switch { @@ -488,9 +491,12 @@ public static bool CanBeRecruitedBy(this PlayerControl target, PlayerControl rec public static bool IsPlayerImpostorTeam(this PlayerState player, bool onlyMainRole = false) { if (!onlyMainRole) + { + if (player.SubRoles.Contains(CustomRoles.Madmate)) return true; if (player.SubRoles.Any(x => (x.IsConverted() || x is CustomRoles.Admired) && x is not CustomRoles.Madmate)) return false; + } - return player.MainRole.IsImpostor() || player.MainRole.GetCustomRoleType() is Custom_RoleType.Madmate; + return (player.MainRole.IsImpostor() || player.MainRole.GetCustomRoleType() is Custom_RoleType.Madmate) && !player.IsNecromancer; } public static bool IsPlayerCrewmateTeam(this PlayerControl player, bool onlyMainRole = false) => Main.PlayerStates.TryGetValue(player.PlayerId, out var state) && state.IsPlayerCrewmateTeam(onlyMainRole); @@ -502,7 +508,7 @@ public static bool IsPlayerCrewmateTeam(this PlayerState player, bool onlyMainRo if (player.SubRoles.Any(x => (x.IsConverted()))) return false; } - return player.MainRole.IsCrewmate(); + return player.MainRole.IsCrewmate() && !player.IsNecromancer; } public static bool IsPlayerNeutralTeam(this PlayerControl player, bool onlyMainRole = false) => Main.PlayerStates.TryGetValue(player.PlayerId, out var state) && state.IsPlayerNeutralTeam(onlyMainRole); @@ -511,11 +517,12 @@ public static bool IsPlayerNeutralTeam(this PlayerState player, bool onlyMainRol if (!onlyMainRole) { if (player.SubRoles.Contains(CustomRoles.Admired)) return false; + if (player.SubRoles.Contains(CustomRoles.Enchanted) || player.SubRoles.Contains(CustomRoles.Madmate)) return false; if (player.SubRoles.Any(x => (x.IsConverted() && x is not CustomRoles.Madmate or CustomRoles.Enchanted))) return true; } // Imp roles like crewposter and parasite is counted as netural, but should be treated as impostor team in general - return player.MainRole.IsNeutral() && player.MainRole.GetCustomRoleType() is not Custom_RoleType.Madmate; + return player.MainRole.IsNeutral() && player.MainRole.GetCustomRoleType() is not Custom_RoleType.Madmate && !player.IsNecromancer; } public static bool IsPlayerCovenTeam(this PlayerControl player, bool onlyMainRole = false) => Main.PlayerStates.TryGetValue(player.PlayerId, out var state) && state.IsPlayerCovenTeam(onlyMainRole); @@ -528,7 +535,7 @@ public static bool IsPlayerCovenTeam(this PlayerState player, bool onlyMainRole if (player.SubRoles.Any(x => (x.IsConverted() && x is not CustomRoles.Enchanted))) return false; } - return player.MainRole.IsCoven(); + return player.MainRole.IsCoven() || player.IsNecromancer; } public static bool CheckAddonConfilct(CustomRoles role, PlayerControl pc, bool checkLimitAddons = true, bool checkConditions = true) { From bffc060c8202522bdb604ab1cc567deb8c6624ff Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 11:55:38 +0800 Subject: [PATCH 25/43] Update Admirer.cs --- Roles/Crewmate/Admirer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Roles/Crewmate/Admirer.cs b/Roles/Crewmate/Admirer.cs index 65145a0a3f..44d3a14737 100644 --- a/Roles/Crewmate/Admirer.cs +++ b/Roles/Crewmate/Admirer.cs @@ -149,7 +149,10 @@ public static bool CanBeAdmired(PlayerControl pc, PlayerControl admirer) } else AdmiredList.Add(admirer.PlayerId, []); - return pc != null; + return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || pc.GetCustomRole().IsNeutral() || pc.GetCustomRole().IsCoven()) + && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Lovers) && !pc.Is(CustomRoles.Loyal) + && !((pc.Is(CustomRoles.NiceMini) || pc.Is(CustomRoles.EvilMini)) && Mini.Age < 18) + && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void SetAbilityButtonText(HudManager hud, byte playerId) From 5cdc4b8e7bcaf77e53b4c89d84d3ded37ea630ed Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 11:57:15 +0800 Subject: [PATCH 26/43] Update Cultist.cs --- Roles/Neutral/Cultist.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Roles/Neutral/Cultist.cs b/Roles/Neutral/Cultist.cs index 3aaf5e7a31..439340f429 100644 --- a/Roles/Neutral/Cultist.cs +++ b/Roles/Neutral/Cultist.cs @@ -114,10 +114,10 @@ public static bool KnowRole(PlayerControl player, PlayerControl target) } public static bool CanBeCharmed(PlayerControl pc) { - return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || - (CanCharmNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || - (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) - && (!pc.Is(CustomRoles.Cultist) || pc.GetBetrayalAddon(true) != CustomRoles.Charmed); + (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Charmed) + && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Infectious) + && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Enchanted) + && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public static bool NameRoleColor(PlayerControl seer, PlayerControl target) { From 8448d5fb9d16ef75c82316085da55d1e54b9b4ca Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 11:58:13 +0800 Subject: [PATCH 27/43] Update CursedSoul.cs --- Roles/Neutral/CursedSoul.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Roles/Neutral/CursedSoul.cs b/Roles/Neutral/CursedSoul.cs index dd73955e73..889029857b 100644 --- a/Roles/Neutral/CursedSoul.cs +++ b/Roles/Neutral/CursedSoul.cs @@ -92,7 +92,7 @@ public static bool CanBeSoulless(PlayerControl pc) { return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || (CanCurseNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || - (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())); + (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Loyal) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From 9e27e3cf25bae2c4ef6ae3609424a79493c1f998 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:00:24 +0800 Subject: [PATCH 28/43] Update Infectious.cs --- Roles/Neutral/Infectious.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Roles/Neutral/Infectious.cs b/Roles/Neutral/Infectious.cs index 7c6c587452..8b5f9373fd 100644 --- a/Roles/Neutral/Infectious.cs +++ b/Roles/Neutral/Infectious.cs @@ -167,9 +167,12 @@ public static bool CanBeBitten(PlayerControl pc) return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostorTeamV3() || pc.GetCustomRole().IsNK() - || pc.GetCustomRole().IsCoven()) - && !pc.Is(CustomRoles.Infectious) - && !pc.IsTransformedNeutralApocalypse(); + || pc.GetCustomRole().IsCoven()) && !pc.Is(CustomRoles.Infected) + && !pc.Is(CustomRoles.Admired) + && !pc.Is(CustomRoles.Loyal) + && !pc.Is(CustomRoles.Cultist) + && !pc.Is(CustomRoles.Enchanted) + && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Virus) && !pc.IsTransformedNeutralApocalypse() && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From b23cee8a9a42d57fd0f235107043b966beb627ff Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:05:02 +0800 Subject: [PATCH 29/43] Update Jackal.cs --- Roles/Neutral/Jackal.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Roles/Neutral/Jackal.cs b/Roles/Neutral/Jackal.cs index 68575be2da..5eaad47b21 100644 --- a/Roles/Neutral/Jackal.cs +++ b/Roles/Neutral/Jackal.cs @@ -389,7 +389,10 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t // very very Long Dog shit lmao public static bool CanBeSidekick(PlayerControl pc) { - return pc != null && !pc.Is(CustomRoles.Sidekick); + return pc != null && !pc.Is(CustomRoles.Sidekick) && !pc.Is(CustomRoles.Recruit) + && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Rascal) && !pc.Is(CustomRoles.Madmate) + && !pc.Is(CustomRoles.Charmed) && !pc.Is(CustomRoles.Infected) && !pc.Is(CustomRoles.Paranoia) + && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Enchanted) && pc.GetCustomRole().IsAbleToBeSidekicked() && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void OnMurderPlayerAsTarget(PlayerControl killer, PlayerControl target, bool inMeeting, bool isSuidice) From 9b9fc623ea8b5ad71091d1613fa294a56af4f98d Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:06:01 +0800 Subject: [PATCH 30/43] Update Virus.cs --- Roles/Neutral/Virus.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Roles/Neutral/Virus.cs b/Roles/Neutral/Virus.cs index 915fc13f17..e33b84e991 100644 --- a/Roles/Neutral/Virus.cs +++ b/Roles/Neutral/Virus.cs @@ -171,7 +171,8 @@ public static class VirusPlayerControls { public static bool CanBeInfected(this PlayerControl pc) { - return pc != null && !pc.Is(CustomRoles.Virus) - && !pc.GetCustomRole().IsTNA(); + return true && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Loyal) + && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Specter) + && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } } From 44873412ec351bece8682d0c4741beeee74ae32c Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:09:52 +0800 Subject: [PATCH 31/43] Update Admirer.cs --- Roles/Crewmate/Admirer.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Roles/Crewmate/Admirer.cs b/Roles/Crewmate/Admirer.cs index 44d3a14737..65145a0a3f 100644 --- a/Roles/Crewmate/Admirer.cs +++ b/Roles/Crewmate/Admirer.cs @@ -149,10 +149,7 @@ public static bool CanBeAdmired(PlayerControl pc, PlayerControl admirer) } else AdmiredList.Add(admirer.PlayerId, []); - return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || pc.GetCustomRole().IsNeutral() || pc.GetCustomRole().IsCoven()) - && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Lovers) && !pc.Is(CustomRoles.Loyal) - && !((pc.Is(CustomRoles.NiceMini) || pc.Is(CustomRoles.EvilMini)) && Mini.Age < 18) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); + return pc != null; } public override void SetAbilityButtonText(HudManager hud, byte playerId) From 182459f6c6b130e694b04d86f38b69e3e9cf4209 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:13:40 +0800 Subject: [PATCH 32/43] Update Cultist.cs --- Roles/Neutral/Cultist.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Roles/Neutral/Cultist.cs b/Roles/Neutral/Cultist.cs index 439340f429..cdf09a22db 100644 --- a/Roles/Neutral/Cultist.cs +++ b/Roles/Neutral/Cultist.cs @@ -114,10 +114,11 @@ public static bool KnowRole(PlayerControl player, PlayerControl target) } public static bool CanBeCharmed(PlayerControl pc) { - (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Charmed) - && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Infectious) - && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Enchanted) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); + return pc != null && ( + (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven()) + || (CanCharmNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) + || pc.GetCustomRole().IsImpostorTeamV3() || pc.GetCustomRole().IsCrewmate() + ); } public static bool NameRoleColor(PlayerControl seer, PlayerControl target) { From 5d9ab7501729f5dd7ffb702937bc9ad1f47f2c91 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:16:48 +0800 Subject: [PATCH 33/43] Update CursedSoul.cs --- Roles/Neutral/CursedSoul.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Roles/Neutral/CursedSoul.cs b/Roles/Neutral/CursedSoul.cs index 889029857b..349be937b3 100644 --- a/Roles/Neutral/CursedSoul.cs +++ b/Roles/Neutral/CursedSoul.cs @@ -90,9 +90,9 @@ public override string PlayerKnowTargetColor(PlayerControl seer, PlayerControl t public static bool CanBeSoulless(PlayerControl pc) { - return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || + return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostorTeamV3() || (CanCurseNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || - (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Loyal) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); + (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Soulless); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From 871e15767d65beca2c46e50d4c43833651e2e57b Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:17:47 +0800 Subject: [PATCH 34/43] Update Infectious.cs --- Roles/Neutral/Infectious.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Roles/Neutral/Infectious.cs b/Roles/Neutral/Infectious.cs index 8b5f9373fd..f878a54af9 100644 --- a/Roles/Neutral/Infectious.cs +++ b/Roles/Neutral/Infectious.cs @@ -167,12 +167,8 @@ public static bool CanBeBitten(PlayerControl pc) return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostorTeamV3() || pc.GetCustomRole().IsNK() - || pc.GetCustomRole().IsCoven()) && !pc.Is(CustomRoles.Infected) - && !pc.Is(CustomRoles.Admired) - && !pc.Is(CustomRoles.Loyal) - && !pc.Is(CustomRoles.Cultist) - && !pc.Is(CustomRoles.Enchanted) - && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Virus) && !pc.IsTransformedNeutralApocalypse() && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); + || pc.GetCustomRole().IsCoven()) + && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Virus) && !pc.IsTransformedNeutralApocalypse(); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From 6706032c4196cf4d9eab170f61c62e35bd5d33bd Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:18:59 +0800 Subject: [PATCH 35/43] Update Jackal.cs --- Roles/Neutral/Jackal.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Roles/Neutral/Jackal.cs b/Roles/Neutral/Jackal.cs index 5eaad47b21..80b837c9ec 100644 --- a/Roles/Neutral/Jackal.cs +++ b/Roles/Neutral/Jackal.cs @@ -389,10 +389,7 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t // very very Long Dog shit lmao public static bool CanBeSidekick(PlayerControl pc) { - return pc != null && !pc.Is(CustomRoles.Sidekick) && !pc.Is(CustomRoles.Recruit) - && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Rascal) && !pc.Is(CustomRoles.Madmate) - && !pc.Is(CustomRoles.Charmed) && !pc.Is(CustomRoles.Infected) && !pc.Is(CustomRoles.Paranoia) - && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Enchanted) && pc.GetCustomRole().IsAbleToBeSidekicked() && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); + return pc != null && !pc.Is(CustomRoles.Sidekick) && !pc.Is(CustomRoles.Paranoia); } public override void OnMurderPlayerAsTarget(PlayerControl killer, PlayerControl target, bool inMeeting, bool isSuidice) From a62e22bec72380169e52ee85354806f3bfcde934 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:20:23 +0800 Subject: [PATCH 36/43] Update Virus.cs --- Roles/Neutral/Virus.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Roles/Neutral/Virus.cs b/Roles/Neutral/Virus.cs index e33b84e991..46ba3d3b36 100644 --- a/Roles/Neutral/Virus.cs +++ b/Roles/Neutral/Virus.cs @@ -171,8 +171,6 @@ public static class VirusPlayerControls { public static bool CanBeInfected(this PlayerControl pc) { - return true && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Loyal) - && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Specter) - && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); + return pc != null && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Specter); } } From f3556ca5de4d443b07368ec2414c2d1291b0a50a Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 12:27:07 +0800 Subject: [PATCH 37/43] CL gives betrayal addon on retrain --- Patches/MeetingHudPatch.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Patches/MeetingHudPatch.cs b/Patches/MeetingHudPatch.cs index 79d9499464..40644e98f2 100644 --- a/Patches/MeetingHudPatch.cs +++ b/Patches/MeetingHudPatch.cs @@ -755,6 +755,7 @@ public static bool Prefix(MeetingHud __instance, byte srcPlayerId, byte suspectP voter.RpcChangeRoleBasis(CovenLeader.retrainPlayer[voter.PlayerId]); voter.RpcSetCustomRole(CovenLeader.retrainPlayer[voter.PlayerId]); voter.GetRoleClass()?.OnAdd(voter.PlayerId); + if (CL.GetBetrayalAddon() != CustomRoles.NotAssigned) voter.RpcSetCustomRole(CL.GetBetrayalAddon()); SendMessage(string.Format(GetString("CovenLeaderAcceptRetrain"), CustomRoles.CovenLeader.ToColoredString(), CovenLeader.retrainPlayer[voter.PlayerId].ToColoredString()), CL.PlayerId); SendMessage(string.Format(GetString("RetrainAcceptOffer"), CustomRoles.CovenLeader.ToColoredString(), CovenLeader.retrainPlayer[voter.PlayerId].ToColoredString()), voter.PlayerId); From e825088e5ac23edf80a0d5c77cbaca35354f4291 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 23:27:36 +0800 Subject: [PATCH 38/43] Update Admirer.cs --- Roles/Crewmate/Admirer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Roles/Crewmate/Admirer.cs b/Roles/Crewmate/Admirer.cs index 65145a0a3f..44d3a14737 100644 --- a/Roles/Crewmate/Admirer.cs +++ b/Roles/Crewmate/Admirer.cs @@ -149,7 +149,10 @@ public static bool CanBeAdmired(PlayerControl pc, PlayerControl admirer) } else AdmiredList.Add(admirer.PlayerId, []); - return pc != null; + return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || pc.GetCustomRole().IsNeutral() || pc.GetCustomRole().IsCoven()) + && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Lovers) && !pc.Is(CustomRoles.Loyal) + && !((pc.Is(CustomRoles.NiceMini) || pc.Is(CustomRoles.EvilMini)) && Mini.Age < 18) + && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void SetAbilityButtonText(HudManager hud, byte playerId) From 04fc5a8dbd1bd28d5be2c740ff44e4cdc2518b33 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 23:29:20 +0800 Subject: [PATCH 39/43] Update Cultist.cs --- Roles/Neutral/Cultist.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Roles/Neutral/Cultist.cs b/Roles/Neutral/Cultist.cs index cdf09a22db..e55f958da2 100644 --- a/Roles/Neutral/Cultist.cs +++ b/Roles/Neutral/Cultist.cs @@ -114,11 +114,12 @@ public static bool KnowRole(PlayerControl player, PlayerControl target) } public static bool CanBeCharmed(PlayerControl pc) { - return pc != null && ( - (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven()) - || (CanCharmNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) - || pc.GetCustomRole().IsImpostorTeamV3() || pc.GetCustomRole().IsCrewmate() - ); + return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || + (CanCharmNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || + (CanCharmCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Charmed) + && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Infectious) + && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Enchanted) + && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public static bool NameRoleColor(PlayerControl seer, PlayerControl target) { From c94da5829e2ea857b101efc9fcb89d06fed4879d Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 23:30:04 +0800 Subject: [PATCH 40/43] Update CursedSoul.cs --- Roles/Neutral/CursedSoul.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Roles/Neutral/CursedSoul.cs b/Roles/Neutral/CursedSoul.cs index 349be937b3..889029857b 100644 --- a/Roles/Neutral/CursedSoul.cs +++ b/Roles/Neutral/CursedSoul.cs @@ -90,9 +90,9 @@ public override string PlayerKnowTargetColor(PlayerControl seer, PlayerControl t public static bool CanBeSoulless(PlayerControl pc) { - return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostorTeamV3() || + return pc != null && (pc.GetCustomRole().IsCrewmate() || pc.GetCustomRole().IsImpostor() || (CanCurseNeutral.GetBool() && pc.GetCustomRole().IsNeutral()) || - (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Soulless); + (CanCurseCoven.GetBool() && pc.GetCustomRole().IsCoven())) && !pc.Is(CustomRoles.Soulless) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Loyal) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From 0b18f63c096d9da49b70e81d5976e664333819f6 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 23:30:43 +0800 Subject: [PATCH 41/43] Update Infectious.cs --- Roles/Neutral/Infectious.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Roles/Neutral/Infectious.cs b/Roles/Neutral/Infectious.cs index f878a54af9..c364f10b28 100644 --- a/Roles/Neutral/Infectious.cs +++ b/Roles/Neutral/Infectious.cs @@ -165,10 +165,14 @@ public static bool InfectedKnowColorOthersInfected(PlayerControl player, PlayerC public static bool CanBeBitten(PlayerControl pc) { return pc != null && (pc.GetCustomRole().IsCrewmate() - || pc.GetCustomRole().IsImpostorTeamV3() + || pc.GetCustomRole().IsImpostor() || pc.GetCustomRole().IsNK() - || pc.GetCustomRole().IsCoven()) - && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Virus) && !pc.IsTransformedNeutralApocalypse(); + || pc.GetCustomRole().IsCoven()) && !pc.Is(CustomRoles.Infected) + && !pc.Is(CustomRoles.Admired) + && !pc.Is(CustomRoles.Loyal) + && !pc.Is(CustomRoles.Cultist) + && !pc.Is(CustomRoles.Enchanted) + && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Virus) && !pc.IsTransformedNeutralApocalypse() && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void SetAbilityButtonText(HudManager hud, byte playerId) { From 428c0ef0a1c773397ea0feb05ebe66dcd8d0b037 Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 23:31:23 +0800 Subject: [PATCH 42/43] Update Jackal.cs --- Roles/Neutral/Jackal.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Roles/Neutral/Jackal.cs b/Roles/Neutral/Jackal.cs index 80b837c9ec..5eaad47b21 100644 --- a/Roles/Neutral/Jackal.cs +++ b/Roles/Neutral/Jackal.cs @@ -389,7 +389,10 @@ public override bool OnCheckMurderAsKiller(PlayerControl killer, PlayerControl t // very very Long Dog shit lmao public static bool CanBeSidekick(PlayerControl pc) { - return pc != null && !pc.Is(CustomRoles.Sidekick) && !pc.Is(CustomRoles.Paranoia); + return pc != null && !pc.Is(CustomRoles.Sidekick) && !pc.Is(CustomRoles.Recruit) + && !pc.Is(CustomRoles.Loyal) && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Rascal) && !pc.Is(CustomRoles.Madmate) + && !pc.Is(CustomRoles.Charmed) && !pc.Is(CustomRoles.Infected) && !pc.Is(CustomRoles.Paranoia) + && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Enchanted) && pc.GetCustomRole().IsAbleToBeSidekicked() && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } public override void OnMurderPlayerAsTarget(PlayerControl killer, PlayerControl target, bool inMeeting, bool isSuidice) From 91bc592294c01e234a9c4076aceb6b4fe8d3fbdf Mon Sep 17 00:00:00 2001 From: ImpyIsLazy Date: Sat, 22 Mar 2025 23:32:31 +0800 Subject: [PATCH 43/43] Update Virus.cs --- Roles/Neutral/Virus.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Roles/Neutral/Virus.cs b/Roles/Neutral/Virus.cs index 46ba3d3b36..e33b84e991 100644 --- a/Roles/Neutral/Virus.cs +++ b/Roles/Neutral/Virus.cs @@ -171,6 +171,8 @@ public static class VirusPlayerControls { public static bool CanBeInfected(this PlayerControl pc) { - return pc != null && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Specter); + return true && !pc.Is(CustomRoles.Virus) && !pc.Is(CustomRoles.Contagious) && !pc.Is(CustomRoles.Loyal) + && !pc.Is(CustomRoles.Admired) && !pc.Is(CustomRoles.Enchanted) && !pc.Is(CustomRoles.Cultist) && !pc.Is(CustomRoles.Infectious) && !pc.Is(CustomRoles.Specter) + && !(pc.GetCustomSubRoles().Contains(CustomRoles.Hurried) && !Hurried.CanBeConverted.GetBool()) && !(CovenManager.HasNecronomicon(pc.PlayerId) && pc.Is(CustomRoles.CovenLeader)); } }