Skip to content

#1466(make all recruiting roles recruit players to their current team) #1520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 54 commits into
base: dev_2.3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
0223ee1
global methods to check if target can be recruited
impostor4291 Mar 6, 2025
94250d5
admirer
impostor4291 Mar 6, 2025
181af65
gangster
impostor4291 Mar 6, 2025
db7d8a6
godfather
impostor4291 Mar 6, 2025
e009a17
cultist
impostor4291 Mar 6, 2025
17239b0
cursed soul
impostor4291 Mar 6, 2025
0e16c9d
jackal
impostor4291 Mar 6, 2025
d748dd8
infectious
impostor4291 Mar 6, 2025
ae34616
virus
impostor4291 Mar 6, 2025
ad75c32
build error
impostor4291 Mar 6, 2025
31f3c66
build error v2
impostor4291 Mar 6, 2025
74f1d59
why does Jackal.HasEnabled check Jailer?
impostor4291 Mar 6, 2025
8e26ce9
Update Virus.cs
impostor4291 Mar 6, 2025
145e302
Update CustomRolesHelper.cs
impostor4291 Mar 6, 2025
fec017e
Update Cultist.cs
impostor4291 Mar 6, 2025
0bdc386
Update CursedSoul.cs
impostor4291 Mar 6, 2025
f28f42c
Update Godfather.cs
impostor4291 Mar 6, 2025
10380c0
Update Virus.cs
impostor4291 Mar 6, 2025
75ce456
Update Godfather.cs
impostor4291 Mar 6, 2025
516632b
build error v3
impostor4291 Mar 6, 2025
10ec734
ritualist
impostor4291 Mar 6, 2025
c474603
Update CheckGameEndPatch.cs
impostor4291 Mar 7, 2025
0db19bb
cv moment
impostor4291 Mar 7, 2025
fad06b2
Change some roles' win condition to make them only win with current team
impostor4291 Mar 7, 2025
cf1dce9
proved not working
impostor4291 Mar 13, 2025
5c1191d
changes + add some more checks to IsPlayerXTeam
impostor4291 Mar 22, 2025
bffc060
Update Admirer.cs
impostor4291 Mar 22, 2025
5cdc4b8
Update Cultist.cs
impostor4291 Mar 22, 2025
8448d5f
Update CursedSoul.cs
impostor4291 Mar 22, 2025
9e27e3c
Update Infectious.cs
impostor4291 Mar 22, 2025
b23cee8
Update Jackal.cs
impostor4291 Mar 22, 2025
9b9fc62
Update Virus.cs
impostor4291 Mar 22, 2025
2979039
resolve conflicts
impostor4291 Mar 22, 2025
4487341
Update Admirer.cs
impostor4291 Mar 22, 2025
182459f
Update Cultist.cs
impostor4291 Mar 22, 2025
5d9ab75
Update CursedSoul.cs
impostor4291 Mar 22, 2025
871e157
Update Infectious.cs
impostor4291 Mar 22, 2025
6706032
Update Jackal.cs
impostor4291 Mar 22, 2025
a62e22b
Update Virus.cs
impostor4291 Mar 22, 2025
f3556ca
CL gives betrayal addon on retrain
impostor4291 Mar 22, 2025
d7f3410
change back
impostor4291 Mar 22, 2025
e825088
Update Admirer.cs
impostor4291 Mar 22, 2025
04fc5a8
Update Cultist.cs
impostor4291 Mar 22, 2025
c94da58
Update CursedSoul.cs
impostor4291 Mar 22, 2025
0b18f63
Update Infectious.cs
impostor4291 Mar 22, 2025
428c0ef
Update Jackal.cs
impostor4291 Mar 22, 2025
91bc592
Update Virus.cs
impostor4291 Mar 22, 2025
cac4454
resolve-conflicts
impostor4291 Mar 22, 2025
9f93760
merge
impostor4291 Mar 22, 2025
345605b
merge merge merge
impostor4291 Mar 25, 2025
4219882
Merge pull request #156 from impostor4291/main
impostor4291 Mar 28, 2025
5802e75
Merge pull request #159 from impostor4291/main
impostor4291 Mar 28, 2025
6b881e4
Merge pull request #160 from EnhancedNetwork/dev_2.3.0
impostor4291 Apr 2, 2025
8683c8a
Merge pull request #161 from impostor4291/main
impostor4291 Apr 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 84 additions & 6 deletions Modules/CustomRolesHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
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;
using TOHE.Roles.Neutral;
using static TOHE.Roles.Core.CustomRoleManager;
Expand Down Expand Up @@ -317,11 +319,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)
Expand Down Expand Up @@ -413,13 +426,77 @@ 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<CustomRoles> 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;

//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
{
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)
{
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);
Expand All @@ -431,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);
Expand All @@ -440,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);
Expand All @@ -457,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)
{
Expand Down
12 changes: 8 additions & 4 deletions Patches/CheckGameEndPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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.Jackal || pc.Is(CustomRoles.Soulless)) && !Main.PlayerStates[pc.PlayerId].IsNecromancer) ||
pc.Is(CustomRoles.Recruit) && !WinnerIds.Contains(pc.PlayerId))
{
WinnerIds.Add(pc.PlayerId);
}
Expand Down
1 change: 1 addition & 0 deletions Patches/MeetingHudPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,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);

Expand Down
68 changes: 12 additions & 56 deletions Roles/Coven/Ritualist.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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());
}
}
Loading