mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 01:46:25 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9b06aff9a | ||
|
|
063b9ff964 | ||
|
|
9a944d9fd3 | ||
|
|
b2013dc25f | ||
|
|
cc8244f487 | ||
|
|
0dc6fc2164 | ||
|
|
1e57d4e171 | ||
|
|
9abed63369 | ||
|
|
2713b69f86 | ||
|
|
2260f90180 | ||
|
|
9c1464582c | ||
|
|
3c5b8f982b | ||
|
|
a7ecca76f7 | ||
|
|
6b86c5ea87 | ||
|
|
57ec47d100 | ||
|
|
970712c4c5 |
No files matched your search
@@ -293,7 +293,7 @@ internal static class FFAManager
|
||||
}
|
||||
else // Mixed
|
||||
{
|
||||
_ = new LateTask(killer.TPtoRndVent, 0.5f, "FFA-Event-TP");
|
||||
_ = new LateTask(() => { killer.TPtoRndVent(); }, 0.5f, "FFA-Event-TP");
|
||||
killer.Notify(GetString("FFA-Event-GetTP"));
|
||||
Main.AllPlayerKillCooldown[killer.PlayerId] = FFA_KCD.GetFloat();
|
||||
}
|
||||
|
||||
@@ -88,15 +88,12 @@ internal class CustomRoleSelector
|
||||
{
|
||||
object cr = list[i1];
|
||||
CustomRoles role = (CustomRoles)Enum.Parse(typeof(CustomRoles), cr.ToString());
|
||||
if (role.IsVanilla() || role.IsAdditionRole()) continue;
|
||||
if (!Main.UseVersionProtocol.Value && !role.IsAbleToHostPublic()) continue;
|
||||
if (role.IsVanilla() || role.IsAdditionRole() || (CustomRolesHelper.OnlySpawnsWithPetsRoleList.Contains(role) && !Options.UsePets.GetBool()) || (!Main.UseVersionProtocol.Value && !role.IsAbleToHostPublic())) continue;
|
||||
switch (role)
|
||||
{
|
||||
case CustomRoles.DarkHide when (MapNames)Main.NormalOptions.MapId == MapNames.Fungle:
|
||||
case CustomRoles.Pelican when roleList.Contains(CustomRoles.Duellist):
|
||||
case CustomRoles.Duellist when roleList.Contains(CustomRoles.Pelican):
|
||||
case CustomRoles.Tunneler when !Options.UsePets.GetBool():
|
||||
case CustomRoles.Tornado when !Options.UsePets.GetBool():
|
||||
case CustomRoles.GM:
|
||||
case CustomRoles.NotAssigned:
|
||||
continue;
|
||||
|
||||
+348
-420
@@ -1,4 +1,5 @@
|
||||
using AmongUs.GameOptions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
@@ -194,95 +195,92 @@ internal static class CustomRolesHelper
|
||||
};
|
||||
}
|
||||
|
||||
public static CustomRoles GetErasedRole(this CustomRoles role)
|
||||
{
|
||||
return role.IsVanilla()
|
||||
? role
|
||||
: role switch
|
||||
{
|
||||
CustomRoles.Tracker => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mayor => Options.MayorHasPortableButton.GetBool() ? CustomRoles.EngineerTOHE : CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Observer => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.DovesOfNeace => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Monitor => Monitor.CanVent.GetBool() ? CustomRoles.EngineerTOHE : CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Judge => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceSwapper => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mortician => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mediumshiper => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Bodyguard => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.ParityCop => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Enigma => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Grenadier => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.SecurityGuard => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Lighter => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Ignitor => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Speedrunner => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Transporter => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Veteran => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.GuardianAngelTOHE => CustomRoles.GuardianAngel,
|
||||
CustomRoles.Detective => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceGuesser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Cleanser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Luckey => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Lookout => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.CyberStar => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Demolitionist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Ventguard => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Express => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceEraser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.TaskManager => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Shiftguard => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mole => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Sentinel => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Electric => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Philantropist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Tornado => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Druid => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Insight => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Tunneler => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Detour => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Drainer => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.GuessManager => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Benefactor => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Altruist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Transmitter => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Autocrat => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Nightmare => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.CameraMan => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Spy => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Ricochet => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Aid => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.DonutDelivery => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Gaulois => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Analyzer => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Escort => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Doormaster => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Tether => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Psychic => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Needy => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.SuperStar => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Paranoia => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.EngineerTOHE => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.TimeMaster => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.CrewmateTOHE => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Doctor => CustomRoles.ScientistTOHE,
|
||||
CustomRoles.ScientistTOHE => CustomRoles.ScientistTOHE,
|
||||
CustomRoles.Tracefinder => CustomRoles.ScientistTOHE,
|
||||
CustomRoles.SpeedBooster => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Dictator => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Snitch => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Marshall => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.SabotageMaster => CustomRoles.EngineerTOHE,
|
||||
//CustomRoles.Retributionist => CustomRoles.Crewmate,
|
||||
CustomRoles.Witness => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Guardian => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Addict => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Alchemist => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Oracle => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Chameleon => CustomRoles.EngineerTOHE,
|
||||
_ => role.IsImpostor() ? CustomRoles.ImpostorTOHE : CustomRoles.CrewmateTOHE,
|
||||
};
|
||||
}
|
||||
public static CustomRoles GetErasedRole(this CustomRoles role) => role.IsVanilla()
|
||||
? role
|
||||
: role switch
|
||||
{
|
||||
CustomRoles.Tracker => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mayor => Options.MayorHasPortableButton.GetBool() ? CustomRoles.EngineerTOHE : CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Observer => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.DovesOfNeace => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Monitor => Monitor.CanVent.GetBool() ? CustomRoles.EngineerTOHE : CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Judge => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceSwapper => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mortician => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mediumshiper => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Bodyguard => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.ParityCop => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Enigma => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Grenadier => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.SecurityGuard => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Lighter => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Ignitor => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Speedrunner => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Transporter => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Veteran => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.GuardianAngelTOHE => CustomRoles.GuardianAngel,
|
||||
CustomRoles.Detective => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceGuesser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Cleanser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Luckey => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Lookout => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.CyberStar => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Demolitionist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Ventguard => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Express => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.NiceEraser => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.TaskManager => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Shiftguard => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Mole => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Sentinel => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Electric => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Philantropist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Tornado => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Druid => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Insight => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Tunneler => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Detour => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Drainer => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.GuessManager => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Benefactor => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Altruist => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Transmitter => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Autocrat => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Nightmare => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.CameraMan => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Spy => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Ricochet => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Aid => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.DonutDelivery => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Gaulois => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Analyzer => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Escort => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Doormaster => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Tether => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Psychic => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Needy => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.SuperStar => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Paranoia => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.EngineerTOHE => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.TimeMaster => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.CrewmateTOHE => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Doctor => CustomRoles.ScientistTOHE,
|
||||
CustomRoles.ScientistTOHE => CustomRoles.ScientistTOHE,
|
||||
CustomRoles.Tracefinder => CustomRoles.ScientistTOHE,
|
||||
CustomRoles.SpeedBooster => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Dictator => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Snitch => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Marshall => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.SabotageMaster => CustomRoles.EngineerTOHE,
|
||||
//CustomRoles.Retributionist => CustomRoles.Crewmate,
|
||||
CustomRoles.Witness => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Guardian => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Addict => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Alchemist => CustomRoles.EngineerTOHE,
|
||||
CustomRoles.Oracle => CustomRoles.CrewmateTOHE,
|
||||
CustomRoles.Chameleon => CustomRoles.EngineerTOHE,
|
||||
_ => role.IsImpostor() ? CustomRoles.ImpostorTOHE : CustomRoles.CrewmateTOHE,
|
||||
};
|
||||
|
||||
public static RoleTypes GetDYRole(this CustomRoles role)
|
||||
{
|
||||
@@ -375,9 +373,7 @@ internal static class CustomRolesHelper
|
||||
_ => RoleTypes.GuardianAngel
|
||||
};
|
||||
}
|
||||
public static bool IsAdditionRole(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsAdditionRole(this CustomRoles role) => role is
|
||||
CustomRoles.Lovers or
|
||||
CustomRoles.LastImpostor or
|
||||
CustomRoles.Ntr or
|
||||
@@ -435,10 +431,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.DoubleShot or
|
||||
CustomRoles.Ghoul or
|
||||
CustomRoles.EvilSpirit;
|
||||
}
|
||||
public static bool IsNonNK(this CustomRoles role) // ROLE ASSIGNING, NOT NEUTRAL TYPE
|
||||
{
|
||||
return role is
|
||||
=> role is
|
||||
CustomRoles.Jester or
|
||||
CustomRoles.Terrorist or
|
||||
CustomRoles.Opportunist or
|
||||
@@ -458,7 +452,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Gamer or
|
||||
CustomRoles.FFF or
|
||||
CustomRoles.Workaholic or
|
||||
// CustomRoles.Pelican or
|
||||
// CustomRoles.Pelican or
|
||||
CustomRoles.Collector or
|
||||
CustomRoles.Sunnyboy or
|
||||
CustomRoles.Maverick or
|
||||
@@ -469,11 +463,9 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.VengefulRomantic or
|
||||
CustomRoles.Doomsayer or
|
||||
CustomRoles.Succubus;
|
||||
}
|
||||
|
||||
public static bool IsAmneMaverick(this CustomRoles role) // ROLE ASSIGNING, NOT NEUTRAL TYPE
|
||||
{
|
||||
return role is
|
||||
=> role is
|
||||
CustomRoles.Jester or
|
||||
CustomRoles.Terrorist or
|
||||
CustomRoles.Opportunist or
|
||||
@@ -499,7 +491,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Gamer or
|
||||
CustomRoles.FFF or
|
||||
CustomRoles.Workaholic or
|
||||
// CustomRoles.Pelican or
|
||||
// CustomRoles.Pelican or
|
||||
CustomRoles.Collector or
|
||||
CustomRoles.Sunnyboy or
|
||||
CustomRoles.Arsonist or
|
||||
@@ -518,10 +510,7 @@ internal static class CustomRolesHelper
|
||||
// CustomRoles.Poisoner or
|
||||
// CustomRoles.HexMaster or
|
||||
CustomRoles.Totocalcio;
|
||||
}
|
||||
public static bool IsAmneNK(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsAmneNK(this CustomRoles role) => role is
|
||||
CustomRoles.Sidekick or
|
||||
CustomRoles.Infectious or
|
||||
CustomRoles.Glitch or
|
||||
@@ -551,11 +540,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Virus or
|
||||
CustomRoles.Spiritcaller or
|
||||
CustomRoles.Succubus;
|
||||
}
|
||||
|
||||
public static bool IsNK(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsNK(this CustomRoles role) => role is
|
||||
CustomRoles.Jackal or
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Sidekick or
|
||||
@@ -600,10 +586,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.RuthlessRomantic or
|
||||
CustomRoles.PlagueBearer or
|
||||
CustomRoles.Pestilence;
|
||||
}
|
||||
public static bool IsSnitchTarget(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsSnitchTarget(this CustomRoles role) => role is
|
||||
CustomRoles.Jackal or
|
||||
CustomRoles.Sidekick or
|
||||
CustomRoles.HexMaster or
|
||||
@@ -645,10 +628,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.RuthlessRomantic or
|
||||
CustomRoles.PlagueBearer or
|
||||
CustomRoles.Pestilence;
|
||||
}
|
||||
public static bool IsNE(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsNE(this CustomRoles role) => role is
|
||||
CustomRoles.Jester or
|
||||
CustomRoles.Gamer or
|
||||
//CustomRoles.Masochist or
|
||||
@@ -656,10 +636,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Executioner or
|
||||
CustomRoles.Doomsayer or
|
||||
CustomRoles.Innocent;
|
||||
}
|
||||
public static bool IsNB(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsNB(this CustomRoles role) => role is
|
||||
CustomRoles.Opportunist or
|
||||
CustomRoles.Lawyer or
|
||||
CustomRoles.Amnesiac or
|
||||
@@ -672,10 +649,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Romantic or
|
||||
CustomRoles.VengefulRomantic or
|
||||
CustomRoles.Totocalcio;
|
||||
}
|
||||
public static bool IsNC(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsNC(this CustomRoles role) => role is
|
||||
CustomRoles.Mario or
|
||||
CustomRoles.Terrorist or
|
||||
//CustomRoles.Pirate or
|
||||
@@ -688,10 +662,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Workaholic or
|
||||
CustomRoles.Collector or
|
||||
CustomRoles.Provocateur;
|
||||
}
|
||||
public static bool IsNeutralKilling(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsNeutralKilling(this CustomRoles role) => role is
|
||||
CustomRoles.Terrorist or
|
||||
CustomRoles.Arsonist or
|
||||
CustomRoles.Juggernaut or
|
||||
@@ -743,10 +714,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.RuthlessRomantic or
|
||||
CustomRoles.PlagueBearer or
|
||||
CustomRoles.Pestilence;
|
||||
}
|
||||
public static bool IsCK(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsCK(this CustomRoles role) => role is
|
||||
CustomRoles.SwordsMan or
|
||||
CustomRoles.Veteran or
|
||||
CustomRoles.CopyCat or
|
||||
@@ -758,10 +726,8 @@ internal static class CustomRolesHelper
|
||||
//CustomRoles.Retributionist or
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Jailor;
|
||||
}
|
||||
public static bool IsImpostor(this CustomRoles role) // IsImp
|
||||
{
|
||||
return role is
|
||||
=> role is
|
||||
CustomRoles.Impostor or
|
||||
CustomRoles.Godfather or
|
||||
CustomRoles.Shapeshifter or
|
||||
@@ -839,10 +805,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Camouflager or
|
||||
CustomRoles.Twister or
|
||||
CustomRoles.Lurker;
|
||||
}
|
||||
public static bool IsNeutral(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsNeutral(this CustomRoles role) => role is
|
||||
//SoloKombat
|
||||
CustomRoles.KB_Normal or
|
||||
//FFA
|
||||
@@ -929,11 +892,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Succubus or
|
||||
CustomRoles.Doomsayer or
|
||||
CustomRoles.Spiritcaller;
|
||||
}
|
||||
|
||||
public static bool IsAbleToBeSidekicked(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsAbleToBeSidekicked(this CustomRoles role) => role is
|
||||
CustomRoles.BloodKnight or
|
||||
CustomRoles.Virus or
|
||||
CustomRoles.Medusa or
|
||||
@@ -1000,11 +960,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Parasite or
|
||||
CustomRoles.PlagueBearer;
|
||||
|
||||
}
|
||||
|
||||
public static bool IsEvilAddons(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsEvilAddons(this CustomRoles role) => role is
|
||||
CustomRoles.Madmate or
|
||||
CustomRoles.Egoist or
|
||||
CustomRoles.Charmed or
|
||||
@@ -1014,19 +970,13 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Rogue or
|
||||
CustomRoles.Rascal or
|
||||
CustomRoles.Soulless;
|
||||
}
|
||||
|
||||
public static bool IsMadmate(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsMadmate(this CustomRoles role) => role is
|
||||
CustomRoles.Crewpostor or
|
||||
CustomRoles.Convict or
|
||||
CustomRoles.Refugee or
|
||||
CustomRoles.Parasite;
|
||||
}
|
||||
public static bool IsTasklessCrewmate(this CustomRoles role)
|
||||
{
|
||||
return !role.UsesPetInsteadOfKill() && role is
|
||||
public static bool IsTasklessCrewmate(this CustomRoles role) => !role.UsesPetInsteadOfKill() && role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Admirer or
|
||||
CustomRoles.Medic or
|
||||
@@ -1045,98 +995,93 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Farseer or
|
||||
CustomRoles.SwordsMan or
|
||||
CustomRoles.Deputy;
|
||||
}
|
||||
public static bool PetActivatedAbility(this CustomRoles role)
|
||||
public static bool PetActivatedAbility(this CustomRoles role) => Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
return Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
CustomRoles.Doormaster or
|
||||
CustomRoles.Tether or
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Paranoia or
|
||||
CustomRoles.Grenadier or
|
||||
CustomRoles.Veteran or
|
||||
CustomRoles.Lighter or
|
||||
CustomRoles.SecurityGuard or
|
||||
CustomRoles.DovesOfNeace or
|
||||
CustomRoles.Alchemist or
|
||||
CustomRoles.TimeMaster or
|
||||
CustomRoles.Sapper or
|
||||
CustomRoles.CameraMan or
|
||||
CustomRoles.NiceHacker or
|
||||
CustomRoles.Druid or
|
||||
CustomRoles.Tunneler or
|
||||
CustomRoles.Tornado or
|
||||
CustomRoles.Sentinel or
|
||||
CustomRoles.Lookout or
|
||||
CustomRoles.Sniper or
|
||||
CustomRoles.Warlock or
|
||||
CustomRoles.Assassin or
|
||||
CustomRoles.Undertaker or
|
||||
CustomRoles.Disperser or
|
||||
CustomRoles.Twister or
|
||||
CustomRoles.QuickShooter or
|
||||
CustomRoles.Miner or
|
||||
CustomRoles.Escapee or
|
||||
CustomRoles.RiftMaker or
|
||||
CustomRoles.Bomber or
|
||||
CustomRoles.Nuker or
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Magician or
|
||||
CustomRoles.WeaponMaster or
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Sprayer
|
||||
=> true,
|
||||
CustomRoles.Doormaster or
|
||||
CustomRoles.Tether or
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Paranoia or
|
||||
CustomRoles.Grenadier or
|
||||
CustomRoles.Veteran or
|
||||
CustomRoles.Lighter or
|
||||
CustomRoles.SecurityGuard or
|
||||
CustomRoles.DovesOfNeace or
|
||||
CustomRoles.Alchemist or
|
||||
CustomRoles.TimeMaster or
|
||||
CustomRoles.Sapper or
|
||||
CustomRoles.CameraMan or
|
||||
CustomRoles.NiceHacker or
|
||||
CustomRoles.Druid or
|
||||
CustomRoles.Tunneler or
|
||||
CustomRoles.Tornado or
|
||||
CustomRoles.Sentinel or
|
||||
CustomRoles.Lookout or
|
||||
CustomRoles.Sniper or
|
||||
CustomRoles.Warlock or
|
||||
CustomRoles.Assassin or
|
||||
CustomRoles.Undertaker or
|
||||
CustomRoles.Disperser or
|
||||
CustomRoles.Twister or
|
||||
CustomRoles.QuickShooter or
|
||||
CustomRoles.Miner or
|
||||
CustomRoles.Escapee or
|
||||
CustomRoles.RiftMaker or
|
||||
CustomRoles.Bomber or
|
||||
CustomRoles.Nuker or
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Magician or
|
||||
CustomRoles.WeaponMaster or
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Sprayer
|
||||
=> true,
|
||||
|
||||
CustomRoles.Gaulois when Gaulois.UsePet.GetBool() => true,
|
||||
CustomRoles.Aid when Aid.UsePet.GetBool() => true,
|
||||
CustomRoles.Escort when Escort.UsePet.GetBool() => true,
|
||||
CustomRoles.DonutDelivery when DonutDelivery.UsePet.GetBool() => true,
|
||||
CustomRoles.Analyzer when Analyzer.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
CustomRoles.Medic when Medic.UsePet.GetBool() => true,
|
||||
CustomRoles.Monarch when Monarch.UsePet.GetBool() => true,
|
||||
CustomRoles.CopyCat when CopyCat.UsePet.GetBool() => true,
|
||||
CustomRoles.Farseer when Farseer.UsePet.GetBool() => true,
|
||||
CustomRoles.Deputy when Deputy.UsePet.GetBool() => true,
|
||||
CustomRoles.Admirer when Admirer.UsePet.GetBool() => true,
|
||||
CustomRoles.Crusader when Crusader.UsePet.GetBool() => true,
|
||||
CustomRoles.Witness when Options.WitnessUsePet.GetBool() => true,
|
||||
CustomRoles.Gaulois when Gaulois.UsePet.GetBool() => true,
|
||||
CustomRoles.Aid when Aid.UsePet.GetBool() => true,
|
||||
CustomRoles.Escort when Escort.UsePet.GetBool() => true,
|
||||
CustomRoles.DonutDelivery when DonutDelivery.UsePet.GetBool() => true,
|
||||
CustomRoles.Analyzer when Analyzer.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
CustomRoles.Medic when Medic.UsePet.GetBool() => true,
|
||||
CustomRoles.Monarch when Monarch.UsePet.GetBool() => true,
|
||||
CustomRoles.CopyCat when CopyCat.UsePet.GetBool() => true,
|
||||
CustomRoles.Farseer when Farseer.UsePet.GetBool() => true,
|
||||
CustomRoles.Deputy when Deputy.UsePet.GetBool() => true,
|
||||
CustomRoles.Admirer when Admirer.UsePet.GetBool() => true,
|
||||
CustomRoles.Crusader when Crusader.UsePet.GetBool() => true,
|
||||
CustomRoles.Witness when Options.WitnessUsePet.GetBool() => true,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
public static bool UsesPetInsteadOfKill(this CustomRoles role)
|
||||
_ => false,
|
||||
};
|
||||
public static bool UsesPetInsteadOfKill(this CustomRoles role) => Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
return Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
CustomRoles.Gaulois when Gaulois.UsePet.GetBool() => true,
|
||||
CustomRoles.Aid when Aid.UsePet.GetBool() => true,
|
||||
CustomRoles.Escort when Escort.UsePet.GetBool() => true,
|
||||
CustomRoles.DonutDelivery when DonutDelivery.UsePet.GetBool() => true,
|
||||
CustomRoles.Analyzer when Analyzer.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
CustomRoles.Medic when Medic.UsePet.GetBool() => true,
|
||||
CustomRoles.Monarch when Monarch.UsePet.GetBool() => true,
|
||||
CustomRoles.CopyCat when CopyCat.UsePet.GetBool() => true,
|
||||
CustomRoles.Farseer when Farseer.UsePet.GetBool() => true,
|
||||
CustomRoles.Deputy when Deputy.UsePet.GetBool() => true,
|
||||
CustomRoles.Admirer when Admirer.UsePet.GetBool() => true,
|
||||
CustomRoles.Crusader when Crusader.UsePet.GetBool() => true,
|
||||
CustomRoles.Witness when Options.WitnessUsePet.GetBool() => true,
|
||||
CustomRoles.Gaulois when Gaulois.UsePet.GetBool() => true,
|
||||
CustomRoles.Aid when Aid.UsePet.GetBool() => true,
|
||||
CustomRoles.Escort when Escort.UsePet.GetBool() => true,
|
||||
CustomRoles.DonutDelivery when DonutDelivery.UsePet.GetBool() => true,
|
||||
CustomRoles.Analyzer when Analyzer.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
CustomRoles.Medic when Medic.UsePet.GetBool() => true,
|
||||
CustomRoles.Monarch when Monarch.UsePet.GetBool() => true,
|
||||
CustomRoles.CopyCat when CopyCat.UsePet.GetBool() => true,
|
||||
CustomRoles.Farseer when Farseer.UsePet.GetBool() => true,
|
||||
CustomRoles.Deputy when Deputy.UsePet.GetBool() => true,
|
||||
CustomRoles.Admirer when Admirer.UsePet.GetBool() => true,
|
||||
CustomRoles.Crusader when Crusader.UsePet.GetBool() => true,
|
||||
CustomRoles.Witness when Options.WitnessUsePet.GetBool() => true,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
public static bool NeedUpdateOnLights(this CustomRoles role)
|
||||
{
|
||||
return (!role.UsesPetInsteadOfKill()) && (role.GetDYRole() != RoleTypes.GuardianAngel || role is
|
||||
_ => false,
|
||||
};
|
||||
public static List<CustomRoles> OnlySpawnsWithPetsRoleList = [
|
||||
CustomRoles.Tunneler,
|
||||
CustomRoles.Tornado
|
||||
];
|
||||
public static bool NeedUpdateOnLights(this CustomRoles role) => (!role.UsesPetInsteadOfKill()) && (role.GetDYRole() != RoleTypes.GuardianAngel || role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Medic or
|
||||
CustomRoles.CopyCat or
|
||||
@@ -1221,35 +1166,28 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Bandit or
|
||||
CustomRoles.Agitater or
|
||||
CustomRoles.Deputy);
|
||||
}
|
||||
|
||||
public static bool IsBetrayalAddon(this CustomRoles role)
|
||||
{
|
||||
return role is CustomRoles.Charmed or
|
||||
CustomRoles.Recruit or
|
||||
CustomRoles.Infected or
|
||||
CustomRoles.Contagious or
|
||||
CustomRoles.Lovers or
|
||||
CustomRoles.Madmate or
|
||||
CustomRoles.Soulless or
|
||||
CustomRoles.Admired or
|
||||
CustomRoles.Egoist;
|
||||
}
|
||||
public static bool IsBetrayalAddon(this CustomRoles role) => role is
|
||||
CustomRoles.Charmed or
|
||||
CustomRoles.Recruit or
|
||||
CustomRoles.Infected or
|
||||
CustomRoles.Contagious or
|
||||
CustomRoles.Lovers or
|
||||
CustomRoles.Madmate or
|
||||
CustomRoles.Soulless or
|
||||
CustomRoles.Admired or
|
||||
CustomRoles.Egoist;
|
||||
|
||||
public static bool IsImpOnlyAddon(this CustomRoles role)
|
||||
{
|
||||
return role is CustomRoles.Mare or
|
||||
CustomRoles.LastImpostor or
|
||||
CustomRoles.Mare or
|
||||
CustomRoles.Mimic or
|
||||
CustomRoles.Damocles or
|
||||
CustomRoles.DeadlyQuota or
|
||||
CustomRoles.TicketsStealer or
|
||||
CustomRoles.Swift;
|
||||
}
|
||||
public static bool IsTaskBasedCrewmate(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsImpOnlyAddon(this CustomRoles role) => role is
|
||||
CustomRoles.Mare or
|
||||
CustomRoles.LastImpostor or
|
||||
CustomRoles.Mare or
|
||||
CustomRoles.Mimic or
|
||||
CustomRoles.Damocles or
|
||||
CustomRoles.DeadlyQuota or
|
||||
CustomRoles.TicketsStealer or
|
||||
CustomRoles.Swift;
|
||||
public static bool IsTaskBasedCrewmate(this CustomRoles role) => role is
|
||||
CustomRoles.Snitch or
|
||||
CustomRoles.Divinator or
|
||||
CustomRoles.Marshall or
|
||||
@@ -1259,154 +1197,147 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Merchant or
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Transporter;
|
||||
}
|
||||
|
||||
public static bool IsNotKnightable(this CustomRoles role)
|
||||
public static bool IsNotKnightable(this CustomRoles role) => role is
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Vindicator or
|
||||
CustomRoles.Dictator or
|
||||
CustomRoles.Knighted or
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Pickpocket or
|
||||
CustomRoles.TicketsStealer;
|
||||
public static bool CheckAddonConflictV2(CustomRoles addon, CustomRoles mainRole) => addon.IsAdditionRole() && mainRole is not CustomRoles.GuardianAngelTOHE and not CustomRoles.God and not CustomRoles.GM && addon is not CustomRoles.Lovers && addon switch
|
||||
{
|
||||
return role is
|
||||
CustomRoles.Mayor or
|
||||
CustomRoles.Vindicator or
|
||||
CustomRoles.Dictator or
|
||||
CustomRoles.Knighted or
|
||||
CustomRoles.Glitch or
|
||||
CustomRoles.Pickpocket or
|
||||
CustomRoles.TicketsStealer;
|
||||
}
|
||||
public static bool CheckAddonConflictV2(CustomRoles addon, CustomRoles mainRole)
|
||||
{
|
||||
return addon.IsAdditionRole() && mainRole is not CustomRoles.GuardianAngelTOHE and not CustomRoles.God and not CustomRoles.GM && addon is not CustomRoles.Lovers && addon switch
|
||||
{
|
||||
CustomRoles.Lovers when mainRole is CustomRoles.RuthlessRomantic or CustomRoles.Romantic or CustomRoles.VengefulRomantic => false,
|
||||
CustomRoles.Autopsy when mainRole is CustomRoles.Doctor or CustomRoles.Tracefinder or CustomRoles.Scientist or CustomRoles.ScientistTOHE or CustomRoles.Sunnyboy => false,
|
||||
CustomRoles.Necroview when mainRole is CustomRoles.Doctor => false,
|
||||
CustomRoles.Lazy when mainRole is CustomRoles.Speedrunner => false,
|
||||
CustomRoles.Loyal when mainRole.IsCrewmate() && !Options.CrewCanBeLoyal.GetBool() => false,
|
||||
CustomRoles.DualPersonality when mainRole.IsCrewmate() && !Options.CrewCanBeDualPersonality.GetBool() => false,
|
||||
CustomRoles.Lazy when mainRole is CustomRoles.Needy or CustomRoles.Snitch or CustomRoles.Marshall or CustomRoles.Transporter or CustomRoles.Guardian => false,
|
||||
CustomRoles.Ghoul when mainRole is CustomRoles.Needy or CustomRoles.Snitch or CustomRoles.Marshall or CustomRoles.Transporter or CustomRoles.Guardian => false,
|
||||
CustomRoles.Egoist when mainRole.IsCrewmate() && !Options.CrewCanBeEgoist.GetBool() => false,
|
||||
CustomRoles.Brakar when mainRole is CustomRoles.Dictator => false,
|
||||
CustomRoles.Stressed when !mainRole.IsCrewmate() || mainRole.IsTasklessCrewmate() => false,
|
||||
CustomRoles.Avanger when mainRole.IsImpostor() && !Options.ImpCanBeAvanger.GetBool() => false,
|
||||
CustomRoles.Ghoul when mainRole.IsNeutral() || mainRole.IsImpostor() || mainRole.IsTasklessCrewmate() || mainRole.IsTaskBasedCrewmate() => false,
|
||||
CustomRoles.Lazy when mainRole.IsNeutral() || mainRole.IsImpostor() || mainRole.IsTasklessCrewmate() && !Options.TasklessCrewCanBeLazy.GetBool() || mainRole.IsTaskBasedCrewmate() && !Options.TaskBasedCrewCanBeLazy.GetBool() => false,
|
||||
CustomRoles.TicketsStealer or CustomRoles.Swift or CustomRoles.DeadlyQuota or CustomRoles.Damocles or CustomRoles.Mare when mainRole is CustomRoles.Bomber or CustomRoles.Nuker or CustomRoles.BoobyTrap or CustomRoles.Capitalism => false,
|
||||
CustomRoles.TicketsStealer or CustomRoles.Mimic or CustomRoles.Swift or CustomRoles.DeadlyQuota or CustomRoles.Damocles or CustomRoles.Mare when !mainRole.IsImpostor() => false,
|
||||
CustomRoles.Torch when !mainRole.IsCrewmate() || mainRole is CustomRoles.Bewilder or CustomRoles.Sunglasses or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bewilder when mainRole is CustomRoles.Torch or CustomRoles.GuardianAngelTOHE or CustomRoles.Sunglasses => false,
|
||||
CustomRoles.Sunglasses when mainRole is CustomRoles.Torch or CustomRoles.GuardianAngelTOHE or CustomRoles.Bewilder => false,
|
||||
CustomRoles.Guesser when mainRole.IsCrewmate() && (!Options.CrewCanBeGuesser.GetBool() || mainRole is CustomRoles.NiceGuesser) || mainRole.IsNeutral() && !Options.NeutralCanBeGuesser.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGuesser.GetBool() || mainRole is CustomRoles.EvilGuesser or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Madmate when mainRole is CustomRoles.Egoist or CustomRoles.Rascal => false,
|
||||
CustomRoles.Oblivious when mainRole is CustomRoles.Detective or CustomRoles.Cleaner or CustomRoles.Medusa or CustomRoles.Mortician or CustomRoles.Mediumshiper or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Youtuber when !mainRole.IsCrewmate() || mainRole is CustomRoles.Madmate or CustomRoles.Sheriff or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Egoist when mainRole.IsImpostor() && !Options.ImpCanBeEgoist.GetBool() => false,
|
||||
CustomRoles.Egoist when mainRole.IsNeutral() || mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.Damocles when mainRole is CustomRoles.Bomber or CustomRoles.Nuker or CustomRoles.SerialKiller or CustomRoles.Cantankerous => false,
|
||||
CustomRoles.Necroview when mainRole is CustomRoles.Visionary => false,
|
||||
CustomRoles.Ghoul when mainRole is CustomRoles.Lazy => false,
|
||||
CustomRoles.Ghoul when mainRole is CustomRoles.Needy => false,
|
||||
CustomRoles.Lazy when mainRole is CustomRoles.Ghoul => false,
|
||||
CustomRoles.Mimic when mainRole is CustomRoles.Mafia => false,
|
||||
CustomRoles.Rascal when !mainRole.IsCrewmate() => false,
|
||||
CustomRoles.Needy when mainRole.IsAdditionRole() => false,
|
||||
CustomRoles.TicketsStealer when mainRole is CustomRoles.Vindicator => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Underdog => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Inhibitor => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Saboteur => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Swift => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Mafia => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Sniper => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.FireWorks => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Swooper => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Vampire => false,
|
||||
CustomRoles.Torch when mainRole is CustomRoles.Lighter => false,
|
||||
CustomRoles.Torch when mainRole is CustomRoles.Ignitor => false,
|
||||
CustomRoles.Bewilder when mainRole is CustomRoles.Lighter => false,
|
||||
CustomRoles.Bewilder when mainRole is CustomRoles.Ignitor => false,
|
||||
CustomRoles.Sunglasses when mainRole is CustomRoles.Lighter => false,
|
||||
CustomRoles.Sunglasses when mainRole is CustomRoles.Ignitor => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.Demolitionist => false,
|
||||
CustomRoles.Trapper when mainRole is CustomRoles.Demolitionist => false,
|
||||
CustomRoles.Lovers when mainRole is CustomRoles.Romantic => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.LastImpostor => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Mare => false,
|
||||
CustomRoles.DualPersonality when !mainRole.IsImpostor() && !mainRole.IsCrewmate() || mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.DualPersonality when mainRole.IsImpostor() && !Options.ImpCanBeDualPersonality.GetBool() => false,
|
||||
CustomRoles.Loyal when !mainRole.IsImpostor() && !mainRole.IsCrewmate() || mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.Loyal when mainRole.IsImpostor() && !Options.ImpCanBeLoyal.GetBool() => false,
|
||||
CustomRoles.Seer when mainRole.IsCrewmate() && (!Options.CrewCanBeSeer.GetBool() || mainRole is CustomRoles.Mortician) || mainRole.IsNeutral() && !Options.NeutralCanBeSeer.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeSeer.GetBool() || mainRole is CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bait when mainRole.IsCrewmate() && !Options.CrewCanBeBait.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeBait.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeBait.GetBool() => false,
|
||||
CustomRoles.Bewilder when mainRole.IsCrewmate() && !Options.CrewCanBeBewilder.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeBewilder.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeBewilder.GetBool() => false,
|
||||
CustomRoles.Sunglasses when mainRole.IsCrewmate() && !Options.CrewCanBeSunglasses.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeSunglasses.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeSunglasses.GetBool() => false,
|
||||
CustomRoles.Autopsy when mainRole.IsCrewmate() && !Options.CrewCanBeAutopsy.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeAutopsy.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeAutopsy.GetBool() => false,
|
||||
CustomRoles.Glow when mainRole.IsCrewmate() && !Options.CrewCanBeGlow.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeGlow.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGlow.GetBool() => false,
|
||||
CustomRoles.Trapper when mainRole.IsCrewmate() && !Options.CrewCanBeTrapper.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeTrapper.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeTrapper.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.Onbound when mainRole is CustomRoles.SuperStar => false,
|
||||
CustomRoles.Rascal when mainRole is CustomRoles.SuperStar or CustomRoles.Madmate => false,
|
||||
CustomRoles.Madmate when mainRole is CustomRoles.SuperStar => false,
|
||||
CustomRoles.Gravestone when mainRole is CustomRoles.SuperStar => false,
|
||||
CustomRoles.Sidekick when mainRole.IsNeutral() && !Options.NeutralCanBeSidekick.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole.IsCrewmate() && !Options.CrewmateCanBeSidekick.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole.IsImpostor() && !Options.ImpostorCanBeSidekick.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole is CustomRoles.Jackal => false,
|
||||
CustomRoles.Lucky when mainRole is CustomRoles.Guardian => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.Trapper => false,
|
||||
CustomRoles.Trapper when mainRole is CustomRoles.Bait => false,
|
||||
CustomRoles.DualPersonality when mainRole is CustomRoles.Dictator => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Swooper => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Vampire => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Scavenger => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Puppeteer => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Warlock => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.EvilDiviner => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Witch => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Mafia => false,
|
||||
CustomRoles.Reach when mainRole is CustomRoles.Mafioso => false,
|
||||
CustomRoles.Trapper when mainRole is CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Watcher when mainRole.IsCrewmate() && !Options.CrewCanBeWatcher.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeWatcher.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeWatcher.GetBool() => false,
|
||||
CustomRoles.Diseased when mainRole.IsCrewmate() && !Options.CrewCanBeDiseased.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeDiseased.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeDiseased.GetBool() => false,
|
||||
CustomRoles.Antidote when mainRole.IsCrewmate() && !Options.CrewCanBeAntidote.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeAntidote.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeAntidote.GetBool() => false,
|
||||
CustomRoles.Diseased when mainRole is CustomRoles.Antidote => false,
|
||||
CustomRoles.Antidote when mainRole is CustomRoles.Diseased => false,
|
||||
CustomRoles.Necroview when mainRole.IsCrewmate() && !Options.CrewCanBeNecroview.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeNecroview.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeNecroview.GetBool() => false,
|
||||
CustomRoles.Oblivious when mainRole.IsCrewmate() && !Options.CrewCanBeOblivious.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeOblivious.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeOblivious.GetBool() => false,
|
||||
CustomRoles.Brakar when mainRole.IsCrewmate() && !Options.CrewCanBeTiebreaker.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeTiebreaker.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeTiebreaker.GetBool() => false,
|
||||
CustomRoles.Guesser when mainRole.IsCrewmate() && !Options.CrewCanBeGuesser.GetBool() && mainRole is CustomRoles.NiceGuesser || mainRole.IsNeutral() && !Options.NeutralCanBeGuesser.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGuesser.GetBool() && mainRole is CustomRoles.EvilGuesser => false,
|
||||
CustomRoles.Onbound when mainRole.IsCrewmate() && !Options.CrewCanBeOnbound.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeOnbound.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeOnbound.GetBool() => false,
|
||||
CustomRoles.Unreportable when mainRole.IsCrewmate() && !Options.CrewCanBeUnreportable.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeUnreportable.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeUnreportable.GetBool() => false,
|
||||
CustomRoles.Lucky when mainRole.IsCrewmate() && !Options.CrewCanBeLucky.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeLucky.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeLucky.GetBool() => false,
|
||||
CustomRoles.Unlucky when mainRole.IsCrewmate() && !Options.CrewCanBeUnlucky.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeUnlucky.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeUnlucky.GetBool() => false,
|
||||
CustomRoles.Rogue when mainRole.IsCrewmate() && !Options.CrewCanBeRogue.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeRogue.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeRogue.GetBool() => false,
|
||||
CustomRoles.Gravestone when mainRole.IsCrewmate() && !Options.CrewCanBeGravestone.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeGravestone.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGravestone.GetBool() => false,
|
||||
CustomRoles.Flashman when mainRole is CustomRoles.Swooper or CustomRoles.Wraith or CustomRoles.Chameleon or CustomRoles.Alchemist => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.Unreportable => false,
|
||||
CustomRoles.Nimble when !mainRole.IsCrewmate() => false,
|
||||
CustomRoles.Physicist when !mainRole.IsCrewmate() => false,
|
||||
CustomRoles.Unreportable when mainRole is CustomRoles.Bait => false,
|
||||
CustomRoles.Oblivious when mainRole is CustomRoles.Bloodhound => false,
|
||||
CustomRoles.Oblivious when mainRole is CustomRoles.Vulture => false,
|
||||
CustomRoles.Vulture when mainRole is CustomRoles.Oblivious => false,
|
||||
CustomRoles.Guesser when mainRole is CustomRoles.CopyCat or CustomRoles.Doomsayer => false,
|
||||
CustomRoles.CopyCat when mainRole is CustomRoles.Guesser => false,
|
||||
CustomRoles.DoubleShot when mainRole is CustomRoles.CopyCat => false,
|
||||
CustomRoles.CopyCat when mainRole is CustomRoles.DoubleShot => false,
|
||||
CustomRoles.Brakar when mainRole is CustomRoles.Dictator => false,
|
||||
CustomRoles.Lucky when mainRole is CustomRoles.Luckey => false,
|
||||
CustomRoles.Unlucky when mainRole is CustomRoles.Luckey => false,
|
||||
CustomRoles.Unlucky when mainRole is CustomRoles.Lucky => false,
|
||||
CustomRoles.Lucky when mainRole is CustomRoles.Unlucky => false,
|
||||
CustomRoles.Fool when mainRole.IsCrewmate() && !Options.CrewCanBeFool.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeFool.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeFool.GetBool() || mainRole is CustomRoles.SabotageMaster or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bloodhound when mainRole is CustomRoles.Oblivious => false,
|
||||
CustomRoles.DoubleShot when mainRole.GetCustomRoleTypes() is CustomRoleTypes.Impostor && !Options.ImpCanBeDoubleShot.GetBool() || mainRole.GetCustomRoleTypes() is CustomRoleTypes.Crewmate && !Options.CrewCanBeDoubleShot.GetBool() || mainRole.GetCustomRoleTypes() is CustomRoleTypes.Neutral && !Options.NeutralCanBeDoubleShot.GetBool() => false,
|
||||
CustomRoles.DoubleShot when mainRole is not CustomRoles.EvilGuesser && mainRole is not CustomRoles.NiceGuesser && !Options.GuesserMode.GetBool() => false,
|
||||
CustomRoles.DoubleShot when Options.ImpCanBeDoubleShot.GetBool() && mainRole is not CustomRoles.Guesser && mainRole is not CustomRoles.EvilGuesser && mainRole.GetCustomRoleTypes() is CustomRoleTypes.Impostor && !Options.ImpostorsCanGuess.GetBool() => false,
|
||||
CustomRoles.DoubleShot when Options.CrewCanBeDoubleShot.GetBool() && mainRole is not CustomRoles.Guesser && mainRole is not CustomRoles.NiceGuesser && mainRole.GetCustomRoleTypes() is CustomRoleTypes.Crewmate && !Options.CrewmatesCanGuess.GetBool() => false,
|
||||
CustomRoles.DoubleShot when Options.NeutralCanBeDoubleShot.GetBool() && mainRole is not CustomRoles.Guesser && (mainRole.IsNonNK() && !Options.PassiveNeutralsCanGuess.GetBool() || mainRole.IsNK() && !Options.NeutralKillersCanGuess.GetBool()) => false,
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
CustomRoles.Lovers when mainRole is CustomRoles.RuthlessRomantic or CustomRoles.Romantic or CustomRoles.VengefulRomantic => false,
|
||||
CustomRoles.Autopsy when mainRole is CustomRoles.Doctor or CustomRoles.Tracefinder or CustomRoles.Scientist or CustomRoles.ScientistTOHE or CustomRoles.Sunnyboy => false,
|
||||
CustomRoles.Necroview when mainRole is CustomRoles.Doctor => false,
|
||||
CustomRoles.Lazy when mainRole is CustomRoles.Speedrunner => false,
|
||||
CustomRoles.Loyal when mainRole.IsCrewmate() && !Options.CrewCanBeLoyal.GetBool() => false,
|
||||
CustomRoles.DualPersonality when mainRole.IsCrewmate() && !Options.CrewCanBeDualPersonality.GetBool() => false,
|
||||
CustomRoles.Lazy when mainRole is CustomRoles.Needy or CustomRoles.Snitch or CustomRoles.Marshall or CustomRoles.Transporter or CustomRoles.Guardian => false,
|
||||
CustomRoles.Ghoul when mainRole is CustomRoles.Needy or CustomRoles.Snitch or CustomRoles.Marshall or CustomRoles.Transporter or CustomRoles.Guardian => false,
|
||||
CustomRoles.Egoist when mainRole.IsCrewmate() && !Options.CrewCanBeEgoist.GetBool() => false,
|
||||
CustomRoles.Brakar when mainRole is CustomRoles.Dictator => false,
|
||||
CustomRoles.Stressed when !mainRole.IsCrewmate() || mainRole.IsTasklessCrewmate() => false,
|
||||
CustomRoles.Avanger when mainRole.IsImpostor() && !Options.ImpCanBeAvanger.GetBool() => false,
|
||||
CustomRoles.Ghoul when mainRole.IsNeutral() || mainRole.IsImpostor() || mainRole.IsTasklessCrewmate() || mainRole.IsTaskBasedCrewmate() => false,
|
||||
CustomRoles.Lazy when mainRole.IsNeutral() || mainRole.IsImpostor() || mainRole.IsTasklessCrewmate() && !Options.TasklessCrewCanBeLazy.GetBool() || mainRole.IsTaskBasedCrewmate() && !Options.TaskBasedCrewCanBeLazy.GetBool() => false,
|
||||
CustomRoles.TicketsStealer or CustomRoles.Swift or CustomRoles.DeadlyQuota or CustomRoles.Damocles or CustomRoles.Mare when mainRole is CustomRoles.Bomber or CustomRoles.Nuker or CustomRoles.BoobyTrap or CustomRoles.Capitalism => false,
|
||||
CustomRoles.TicketsStealer or CustomRoles.Mimic or CustomRoles.Swift or CustomRoles.DeadlyQuota or CustomRoles.Damocles or CustomRoles.Mare when !mainRole.IsImpostor() => false,
|
||||
CustomRoles.Torch when !mainRole.IsCrewmate() || mainRole is CustomRoles.Bewilder or CustomRoles.Sunglasses or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bewilder when mainRole is CustomRoles.Torch or CustomRoles.GuardianAngelTOHE or CustomRoles.Sunglasses => false,
|
||||
CustomRoles.Sunglasses when mainRole is CustomRoles.Torch or CustomRoles.GuardianAngelTOHE or CustomRoles.Bewilder => false,
|
||||
CustomRoles.Guesser when mainRole.IsCrewmate() && (!Options.CrewCanBeGuesser.GetBool() || mainRole is CustomRoles.NiceGuesser) || mainRole.IsNeutral() && !Options.NeutralCanBeGuesser.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGuesser.GetBool() || mainRole is CustomRoles.EvilGuesser or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Madmate when mainRole is CustomRoles.Egoist or CustomRoles.Rascal => false,
|
||||
CustomRoles.Oblivious when mainRole is CustomRoles.Detective or CustomRoles.Cleaner or CustomRoles.Medusa or CustomRoles.Mortician or CustomRoles.Mediumshiper or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Youtuber when !mainRole.IsCrewmate() || mainRole is CustomRoles.Madmate or CustomRoles.Sheriff or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Egoist when mainRole.IsImpostor() && !Options.ImpCanBeEgoist.GetBool() => false,
|
||||
CustomRoles.Egoist when mainRole.IsNeutral() || mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.Damocles when mainRole is CustomRoles.Bomber or CustomRoles.Nuker or CustomRoles.SerialKiller or CustomRoles.Cantankerous => false,
|
||||
CustomRoles.Necroview when mainRole is CustomRoles.Visionary => false,
|
||||
CustomRoles.Ghoul when mainRole is CustomRoles.Lazy => false,
|
||||
CustomRoles.Ghoul when mainRole is CustomRoles.Needy => false,
|
||||
CustomRoles.Lazy when mainRole is CustomRoles.Ghoul => false,
|
||||
CustomRoles.Mimic when mainRole is CustomRoles.Mafia => false,
|
||||
CustomRoles.Rascal when !mainRole.IsCrewmate() => false,
|
||||
CustomRoles.Needy when mainRole.IsAdditionRole() => false,
|
||||
CustomRoles.TicketsStealer when mainRole is CustomRoles.Vindicator => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Underdog => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Inhibitor => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Saboteur => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Swift => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Mafia => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Sniper => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.FireWorks => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Swooper => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.Vampire => false,
|
||||
CustomRoles.Torch when mainRole is CustomRoles.Lighter => false,
|
||||
CustomRoles.Torch when mainRole is CustomRoles.Ignitor => false,
|
||||
CustomRoles.Bewilder when mainRole is CustomRoles.Lighter => false,
|
||||
CustomRoles.Bewilder when mainRole is CustomRoles.Ignitor => false,
|
||||
CustomRoles.Sunglasses when mainRole is CustomRoles.Lighter => false,
|
||||
CustomRoles.Sunglasses when mainRole is CustomRoles.Ignitor => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.Demolitionist => false,
|
||||
CustomRoles.Trapper when mainRole is CustomRoles.Demolitionist => false,
|
||||
CustomRoles.Lovers when mainRole is CustomRoles.Romantic => false,
|
||||
CustomRoles.Mare when mainRole is CustomRoles.LastImpostor => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Mare => false,
|
||||
CustomRoles.DualPersonality when !mainRole.IsImpostor() && !mainRole.IsCrewmate() || mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.DualPersonality when mainRole.IsImpostor() && !Options.ImpCanBeDualPersonality.GetBool() => false,
|
||||
CustomRoles.Loyal when !mainRole.IsImpostor() && !mainRole.IsCrewmate() || mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.Loyal when mainRole.IsImpostor() && !Options.ImpCanBeLoyal.GetBool() => false,
|
||||
CustomRoles.Seer when mainRole.IsCrewmate() && (!Options.CrewCanBeSeer.GetBool() || mainRole is CustomRoles.Mortician) || mainRole.IsNeutral() && !Options.NeutralCanBeSeer.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeSeer.GetBool() || mainRole is CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bait when mainRole.IsCrewmate() && !Options.CrewCanBeBait.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeBait.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeBait.GetBool() => false,
|
||||
CustomRoles.Bewilder when mainRole.IsCrewmate() && !Options.CrewCanBeBewilder.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeBewilder.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeBewilder.GetBool() => false,
|
||||
CustomRoles.Sunglasses when mainRole.IsCrewmate() && !Options.CrewCanBeSunglasses.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeSunglasses.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeSunglasses.GetBool() => false,
|
||||
CustomRoles.Autopsy when mainRole.IsCrewmate() && !Options.CrewCanBeAutopsy.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeAutopsy.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeAutopsy.GetBool() => false,
|
||||
CustomRoles.Glow when mainRole.IsCrewmate() && !Options.CrewCanBeGlow.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeGlow.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGlow.GetBool() => false,
|
||||
CustomRoles.Trapper when mainRole.IsCrewmate() && !Options.CrewCanBeTrapper.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeTrapper.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeTrapper.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole is CustomRoles.Madmate => false,
|
||||
CustomRoles.Onbound when mainRole is CustomRoles.SuperStar => false,
|
||||
CustomRoles.Rascal when mainRole is CustomRoles.SuperStar or CustomRoles.Madmate => false,
|
||||
CustomRoles.Madmate when mainRole is CustomRoles.SuperStar => false,
|
||||
CustomRoles.Gravestone when mainRole is CustomRoles.SuperStar => false,
|
||||
CustomRoles.Sidekick when mainRole.IsNeutral() && !Options.NeutralCanBeSidekick.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole.IsCrewmate() && !Options.CrewmateCanBeSidekick.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole.IsImpostor() && !Options.ImpostorCanBeSidekick.GetBool() => false,
|
||||
CustomRoles.Sidekick when mainRole is CustomRoles.Jackal => false,
|
||||
CustomRoles.Lucky when mainRole is CustomRoles.Guardian => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.Trapper => false,
|
||||
CustomRoles.Trapper when mainRole is CustomRoles.Bait => false,
|
||||
CustomRoles.DualPersonality when mainRole is CustomRoles.Dictator => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Swooper => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Vampire => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Scavenger => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Puppeteer => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Warlock => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.EvilDiviner => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Witch => false,
|
||||
CustomRoles.Swift when mainRole is CustomRoles.Mafia => false,
|
||||
CustomRoles.Reach when mainRole is CustomRoles.Mafioso => false,
|
||||
CustomRoles.Trapper when mainRole is CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Watcher when mainRole.IsCrewmate() && !Options.CrewCanBeWatcher.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeWatcher.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeWatcher.GetBool() => false,
|
||||
CustomRoles.Diseased when mainRole.IsCrewmate() && !Options.CrewCanBeDiseased.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeDiseased.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeDiseased.GetBool() => false,
|
||||
CustomRoles.Antidote when mainRole.IsCrewmate() && !Options.CrewCanBeAntidote.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeAntidote.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeAntidote.GetBool() => false,
|
||||
CustomRoles.Diseased when mainRole is CustomRoles.Antidote => false,
|
||||
CustomRoles.Antidote when mainRole is CustomRoles.Diseased => false,
|
||||
CustomRoles.Necroview when mainRole.IsCrewmate() && !Options.CrewCanBeNecroview.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeNecroview.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeNecroview.GetBool() => false,
|
||||
CustomRoles.Oblivious when mainRole.IsCrewmate() && !Options.CrewCanBeOblivious.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeOblivious.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeOblivious.GetBool() => false,
|
||||
CustomRoles.Brakar when mainRole.IsCrewmate() && !Options.CrewCanBeTiebreaker.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeTiebreaker.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeTiebreaker.GetBool() => false,
|
||||
CustomRoles.Guesser when mainRole.IsCrewmate() && !Options.CrewCanBeGuesser.GetBool() && mainRole is CustomRoles.NiceGuesser || mainRole.IsNeutral() && !Options.NeutralCanBeGuesser.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGuesser.GetBool() && mainRole is CustomRoles.EvilGuesser => false,
|
||||
CustomRoles.Onbound when mainRole.IsCrewmate() && !Options.CrewCanBeOnbound.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeOnbound.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeOnbound.GetBool() => false,
|
||||
CustomRoles.Unreportable when mainRole.IsCrewmate() && !Options.CrewCanBeUnreportable.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeUnreportable.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeUnreportable.GetBool() => false,
|
||||
CustomRoles.Lucky when mainRole.IsCrewmate() && !Options.CrewCanBeLucky.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeLucky.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeLucky.GetBool() => false,
|
||||
CustomRoles.Unlucky when mainRole.IsCrewmate() && !Options.CrewCanBeUnlucky.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeUnlucky.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeUnlucky.GetBool() => false,
|
||||
CustomRoles.Rogue when mainRole.IsCrewmate() && !Options.CrewCanBeRogue.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeRogue.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeRogue.GetBool() => false,
|
||||
CustomRoles.Gravestone when mainRole.IsCrewmate() && !Options.CrewCanBeGravestone.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeGravestone.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeGravestone.GetBool() => false,
|
||||
CustomRoles.Flashman when mainRole is CustomRoles.Swooper or CustomRoles.Wraith or CustomRoles.Chameleon or CustomRoles.Alchemist => false,
|
||||
CustomRoles.Bait when mainRole is CustomRoles.Unreportable => false,
|
||||
CustomRoles.Nimble when !mainRole.IsCrewmate() => false,
|
||||
CustomRoles.Physicist when !mainRole.IsCrewmate() => false,
|
||||
CustomRoles.Unreportable when mainRole is CustomRoles.Bait => false,
|
||||
CustomRoles.Oblivious when mainRole is CustomRoles.Bloodhound => false,
|
||||
CustomRoles.Oblivious when mainRole is CustomRoles.Vulture => false,
|
||||
CustomRoles.Vulture when mainRole is CustomRoles.Oblivious => false,
|
||||
CustomRoles.Guesser when mainRole is CustomRoles.CopyCat or CustomRoles.Doomsayer => false,
|
||||
CustomRoles.CopyCat when mainRole is CustomRoles.Guesser => false,
|
||||
CustomRoles.DoubleShot when mainRole is CustomRoles.CopyCat => false,
|
||||
CustomRoles.CopyCat when mainRole is CustomRoles.DoubleShot => false,
|
||||
CustomRoles.Brakar when mainRole is CustomRoles.Dictator => false,
|
||||
CustomRoles.Lucky when mainRole is CustomRoles.Luckey => false,
|
||||
CustomRoles.Unlucky when mainRole is CustomRoles.Luckey => false,
|
||||
CustomRoles.Unlucky when mainRole is CustomRoles.Lucky => false,
|
||||
CustomRoles.Lucky when mainRole is CustomRoles.Unlucky => false,
|
||||
CustomRoles.Fool when mainRole.IsCrewmate() && !Options.CrewCanBeFool.GetBool() || mainRole.IsNeutral() && !Options.NeutralCanBeFool.GetBool() || mainRole.IsImpostor() && !Options.ImpCanBeFool.GetBool() || mainRole is CustomRoles.SabotageMaster or CustomRoles.GuardianAngelTOHE => false,
|
||||
CustomRoles.Bloodhound when mainRole is CustomRoles.Oblivious => false,
|
||||
CustomRoles.DoubleShot when mainRole.GetCustomRoleTypes() is CustomRoleTypes.Impostor && !Options.ImpCanBeDoubleShot.GetBool() || mainRole.GetCustomRoleTypes() is CustomRoleTypes.Crewmate && !Options.CrewCanBeDoubleShot.GetBool() || mainRole.GetCustomRoleTypes() is CustomRoleTypes.Neutral && !Options.NeutralCanBeDoubleShot.GetBool() => false,
|
||||
CustomRoles.DoubleShot when mainRole is not CustomRoles.EvilGuesser && mainRole is not CustomRoles.NiceGuesser && !Options.GuesserMode.GetBool() => false,
|
||||
CustomRoles.DoubleShot when Options.ImpCanBeDoubleShot.GetBool() && mainRole is not CustomRoles.Guesser && mainRole is not CustomRoles.EvilGuesser && mainRole.GetCustomRoleTypes() is CustomRoleTypes.Impostor && !Options.ImpostorsCanGuess.GetBool() => false,
|
||||
CustomRoles.DoubleShot when Options.CrewCanBeDoubleShot.GetBool() && mainRole is not CustomRoles.Guesser && mainRole is not CustomRoles.NiceGuesser && mainRole.GetCustomRoleTypes() is CustomRoleTypes.Crewmate && !Options.CrewmatesCanGuess.GetBool() => false,
|
||||
CustomRoles.DoubleShot when Options.NeutralCanBeDoubleShot.GetBool() && mainRole is not CustomRoles.Guesser && (mainRole.IsNonNK() && !Options.PassiveNeutralsCanGuess.GetBool() || mainRole.IsNK() && !Options.NeutralKillersCanGuess.GetBool()) => false,
|
||||
_ => true
|
||||
};
|
||||
public static bool CheckAddonConflict(CustomRoles role, PlayerControl pc)
|
||||
{
|
||||
if (!role.IsAdditionRole()) return false;
|
||||
@@ -1632,16 +1563,13 @@ internal static class CustomRolesHelper
|
||||
public static bool IsNeutralKillerTeam(this CustomRoles role) => role.IsNK() && !role.IsMadmate();
|
||||
public static bool IsPassiveNeutralTeam(this CustomRoles role) => role.IsNonNK() && !role.IsMadmate();
|
||||
public static bool IsNNK(this CustomRoles role) => role.IsNeutral() && !role.IsNK();
|
||||
public static bool IsVanilla(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
public static bool IsVanilla(this CustomRoles role) => role is
|
||||
CustomRoles.Crewmate or
|
||||
CustomRoles.Engineer or
|
||||
CustomRoles.Scientist or
|
||||
CustomRoles.GuardianAngel or
|
||||
CustomRoles.Impostor or
|
||||
CustomRoles.Shapeshifter;
|
||||
}
|
||||
public static CustomRoleTypes GetCustomRoleTypes(this CustomRoles role)
|
||||
{
|
||||
CustomRoleTypes type = CustomRoleTypes.Crewmate;
|
||||
|
||||
@@ -15,7 +15,7 @@ public class DevUser(string code = "", string color = "null", string tag = "null
|
||||
public string UpName { get; set; } = upName;
|
||||
|
||||
public bool HasTag() => Tag != "null";
|
||||
public string GetTag() => Color == "null" ? $"<size=1>{Tag}</size>\r\n" : $"<color={Color}><size=1>{(Tag == "#Dev" ? Translator.GetString("Developer") : Tag)}</size></color>\r\n";
|
||||
public string GetTag() => Color == "null" ? $"<size=1.4>{Tag}</size>\r\n" : $"<color={Color}><size=1.4>{(Tag == "#Dev" ? Translator.GetString("Developer") : Tag)}</size></color>\r\n";
|
||||
}
|
||||
|
||||
public static class DevManager
|
||||
@@ -72,6 +72,8 @@ public static class DevManager
|
||||
DevUserList.Add(new(code: "swiftlord#0872", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "But What About"));
|
||||
DevUserList.Add(new(code: "ovalinstep#2984", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Seleneous"));
|
||||
DevUserList.Add(new(code: "innerruler#4140", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "thewhiskas27"));
|
||||
DevUserList.Add(new(code: "urbanecalf#4975", color: "#420773", tag: "Streamer", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "Gugutsik"));
|
||||
DevUserList.Add(new(code: "crustzonal#9589", color: "null", tag: "null", isUp: true, isDev: false, deBug: false, colorCmd: false, upName: "aviiiv0102"));
|
||||
|
||||
// Sponsor
|
||||
DevUserList.Add(new(code: "recentduct#6068", color: "#FF00FF", tag: "高冷男模法师", isUp: false, isDev: false, colorCmd: false, deBug: true, upName: null));
|
||||
|
||||
+48
-44
@@ -69,7 +69,6 @@ internal class EAC
|
||||
break;
|
||||
case RpcCalls.SendChat:
|
||||
var text = sr.ReadString();
|
||||
if (text.StartsWith("/")) return false;
|
||||
if (
|
||||
text.Contains('░') ||
|
||||
text.Contains('▄') ||
|
||||
@@ -85,7 +84,7 @@ internal class EAC
|
||||
}
|
||||
break;
|
||||
case RpcCalls.StartMeeting:
|
||||
//Client will never send StartMeeting rpc
|
||||
// Non-Host Clients will never send StartMeeting RPC
|
||||
WarnHost();
|
||||
Report(pc, "Bad StartMeeting");
|
||||
HandleCheat(pc, "Bad StartMeeting");
|
||||
@@ -133,6 +132,13 @@ internal class EAC
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the color and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (pc.AmOwner)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Illegal setting of host color");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the host's color, which has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case RpcCalls.CheckMurder:
|
||||
if (GameStates.IsLobby)
|
||||
@@ -145,28 +151,29 @@ internal class EAC
|
||||
}
|
||||
break;
|
||||
case RpcCalls.MurderPlayer:
|
||||
//If using version protocol, client should never directly send Murder player rpc
|
||||
// Calls will only be sent by server / host
|
||||
Report(pc, "Directly Murder Player");
|
||||
HandleCheat(pc, "Directly Murder Player");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] killed directly, rejected", "EAC");
|
||||
return true;
|
||||
case RpcCalls.Shapeshift:
|
||||
case RpcCalls.CheckShapeshift:
|
||||
if (GameStates.IsLobby)
|
||||
{
|
||||
Report(pc, "ShapeShift in lobby");
|
||||
HandleCheat(pc, "ShapeShift in lobby");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] lobby is deformed and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
var target = sr.ReadNetObject<PlayerControl>();
|
||||
if (target == null)
|
||||
{
|
||||
Report(pc, "ShapeShift to null player!");
|
||||
//HandleCheat(pc, "ShapeShift to null player!");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally transformed into an empty player and has been rejected", "EAC");
|
||||
Report(pc, "Lobby CheckShapeshift");
|
||||
HandleCheat(pc, "Lobby CheckShapeshift");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] directly shapeshifted and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case RpcCalls.Shapeshift:
|
||||
Report(pc, "Directly Shapeshift");
|
||||
var swriter = AmongUsClient.Instance.StartRpcImmediately(pc.NetId, (byte)RpcCalls.Shapeshift, SendOption.Reliable, -1);
|
||||
swriter.WriteNetObject(pc);
|
||||
swriter.Write(false);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(swriter);
|
||||
HandleCheat(pc, "Directly Shapeshift");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] directly shapeshifted and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
switch (callId)
|
||||
{
|
||||
@@ -177,6 +184,7 @@ internal class EAC
|
||||
HandleCheat(pc, GetString("EAC.CheatDetected.EAC"));
|
||||
return true;
|
||||
case 7:
|
||||
case 8:
|
||||
if (!GameStates.IsLobby)
|
||||
{
|
||||
WarnHost();
|
||||
@@ -204,49 +212,45 @@ internal class EAC
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 41:
|
||||
case 38:
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Illegal pet setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set a pet and has been rejected", "EAC");
|
||||
Report(pc, "Set level in game");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] changed the level in the game and it has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
if (GameStates.IsInGame)
|
||||
if (sr.ReadPackedUInt32() > 0)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Illegal skin setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the skin and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 42:
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Illegal facial decoration");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set facial decoration and has been rejected", "EAC");
|
||||
return true;
|
||||
uint ClientDataLevel = pc.GetClient() == null ? pc.GetClient().PlayerLevel : 0;
|
||||
uint PlayerControlLevel = sr.ReadPackedUInt32();
|
||||
if (ClientDataLevel != 0 && Math.Abs(PlayerControlLevel - ClientDataLevel) > 4)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Sus Level Change");
|
||||
AmongUsClient.Instance.KickPlayer(pc.GetClientId(), false);
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] changed the level in the game and it has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Illegal hat setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set a hat and has been rejected", "EAC");
|
||||
Report(pc, "Change skin in game");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] changed the skin in the game and it has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 43:
|
||||
if (sr.BytesRemaining > 0 && sr.ReadBoolean()) return false;
|
||||
if (GameStates.IsInGame)
|
||||
if (pc.AmOwner)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "Illegal setting of game name");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the name and has been rejected", "EAC");
|
||||
Report(pc, "Change Host skin");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] changed the owner's skin and it has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -280,7 +284,7 @@ internal class EAC
|
||||
//Update system rpc can not get received by playercontrol.handlerpc
|
||||
var Mapid = Main.NormalOptions.MapId;
|
||||
Logger.Info("Check sabotage RPC" + ", PlayerName: " + player.GetNameWithRole() + ", SabotageType: " + systemType.ToString() + ", amount: " + amount.ToString(), "EAC");
|
||||
if (player.AmOwner || !AmongUsClient.Instance.AmHost) return false;
|
||||
if (!AmongUsClient.Instance.AmHost) return false;
|
||||
switch (systemType) //Normal sabotage using buttons
|
||||
{
|
||||
case SystemTypes.Sabotage:
|
||||
@@ -402,7 +406,7 @@ internal class EAC
|
||||
string msg = $"{pc.GetClientId()}|{pc.FriendCode}|{pc.Data.PlayerName}|{pc.GetClient().GetHashedPuid()}|{reason}";
|
||||
//Cloud.SendData(msg);
|
||||
Logger.Fatal($"EAC report: {msg}", "EAC Cloud");
|
||||
Logger.SendInGame(string.Format(GetString("Message.NoticeByEAC"), $"{pc?.Data?.PlayerName} | {pc.GetClient().GetHashedPuid()}", reason));
|
||||
if (Options.CheatResponses.GetInt() != 5) Logger.SendInGame(string.Format(GetString("Message.NoticeByEAC"), $"{pc?.Data?.PlayerName} | {pc.GetClient().GetHashedPuid()}", reason));
|
||||
}
|
||||
public static bool ReceiveInvalidRpc(PlayerControl pc, byte callId)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TOHE.Modules;
|
||||
using TOHE.Roles.AddOns.Crewmate;
|
||||
using TOHE.Roles.AddOns.Impostor;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
@@ -212,7 +213,10 @@ static class ExtendedPlayerControl
|
||||
Main.PlayerStates[pc.PlayerId].deathReason = deathReason;
|
||||
Main.PlayerStates[pc.PlayerId].SetDead();
|
||||
if (realKiller != null) pc.SetRealKiller(realKiller);
|
||||
|
||||
Medic.IsDead(pc);
|
||||
if (realKiller != null && realKiller.Is(CustomRoles.Damocles)) Damocles.OnMurder(realKiller.PlayerId);
|
||||
|
||||
pc.Kill(pc);
|
||||
}
|
||||
|
||||
@@ -623,8 +627,8 @@ static class ExtendedPlayerControl
|
||||
CustomRoles.YinYanger => pc.IsAlive(),
|
||||
CustomRoles.Librarian => pc.IsAlive() && Librarian.CanUseKillButton(pc),
|
||||
CustomRoles.Cantankerous => pc.IsAlive() && Cantankerous.CanUseKillButton(pc.PlayerId),
|
||||
CustomRoles.Inhibitor => !Utils.IsActive(SystemTypes.Electrical) && !Utils.IsActive(SystemTypes.Comms) && !Utils.IsActive(SystemTypes.MushroomMixupSabotage) && !Utils.IsActive(SystemTypes.Laboratory) && !Utils.IsActive(SystemTypes.LifeSupp) && !Utils.IsActive(SystemTypes.Reactor) && !Utils.IsActive(SystemTypes.HeliSabotage),
|
||||
CustomRoles.Saboteur => Utils.IsActive(SystemTypes.Electrical) || Utils.IsActive(SystemTypes.Comms) || Utils.IsActive(SystemTypes.MushroomMixupSabotage) || Utils.IsActive(SystemTypes.Laboratory) || Utils.IsActive(SystemTypes.LifeSupp) || Utils.IsActive(SystemTypes.Reactor) || Utils.IsActive(SystemTypes.HeliSabotage),
|
||||
CustomRoles.Inhibitor => !IsActive(SystemTypes.Electrical) && !IsActive(SystemTypes.Comms) && !IsActive(SystemTypes.MushroomMixupSabotage) && !IsActive(SystemTypes.Laboratory) && !IsActive(SystemTypes.LifeSupp) && !IsActive(SystemTypes.Reactor) && !IsActive(SystemTypes.HeliSabotage),
|
||||
CustomRoles.Saboteur => IsActive(SystemTypes.Electrical) || IsActive(SystemTypes.Comms) || IsActive(SystemTypes.MushroomMixupSabotage) || IsActive(SystemTypes.Laboratory) || IsActive(SystemTypes.LifeSupp) || IsActive(SystemTypes.Reactor) || IsActive(SystemTypes.HeliSabotage),
|
||||
CustomRoles.Sniper => Sniper.CanUseKillButton(pc),
|
||||
CustomRoles.Sheriff => Sheriff.CanUseKillButton(pc.PlayerId),
|
||||
CustomRoles.Crusader => Crusader.CanUseKillButton(pc.PlayerId),
|
||||
@@ -1208,7 +1212,6 @@ static class ExtendedPlayerControl
|
||||
case CustomRoles.Medusa:
|
||||
Medusa.SetKillCooldown(player.PlayerId);
|
||||
break;
|
||||
|
||||
case CustomRoles.Cleaner:
|
||||
Main.AllPlayerKillCooldown[player.PlayerId] = Options.CleanerKillCooldown.GetFloat();
|
||||
break;
|
||||
@@ -1381,17 +1384,17 @@ static class ExtendedPlayerControl
|
||||
|
||||
return (pos, roomName);
|
||||
}
|
||||
public static void TP(this PlayerControl pc, PlayerControl target)
|
||||
public static bool TP(this PlayerControl pc, PlayerControl target)
|
||||
{
|
||||
Utils.TP(pc.NetTransform, target.Pos());
|
||||
return Utils.TP(pc.NetTransform, target.Pos());
|
||||
}
|
||||
public static void TP(this PlayerControl pc, Vector2 location)
|
||||
public static bool TP(this PlayerControl pc, Vector2 location)
|
||||
{
|
||||
Utils.TP(pc.NetTransform, location);
|
||||
return Utils.TP(pc.NetTransform, location);
|
||||
}
|
||||
public static void TPtoRndVent(this PlayerControl pc)
|
||||
public static bool TPtoRndVent(this PlayerControl pc)
|
||||
{
|
||||
Utils.TPtoRndVent(pc.NetTransform);
|
||||
return Utils.TPtoRndVent(pc.NetTransform);
|
||||
}
|
||||
public static void Kill(this PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
@@ -1399,6 +1402,12 @@ static class ExtendedPlayerControl
|
||||
|
||||
if (Options.CurrentGameMode == CustomGameMode.SoloKombat) return;
|
||||
|
||||
if (target.GetTeam() is Team.Impostor or Team.Neutral) Stressed.OnNonCrewmateDead();
|
||||
|
||||
if (killer.Is(CustomRoles.Damocles)) Damocles.OnMurder(killer.PlayerId);
|
||||
else if (killer.Is(Team.Impostor)) Damocles.OnOtherImpostorMurder();
|
||||
if (target.Is(Team.Impostor)) Damocles.OnImpostorDeath();
|
||||
|
||||
if (killer.PlayerId == target.PlayerId && killer.shapeshifting)
|
||||
{
|
||||
_ = new LateTask(() => { killer.RpcMurderPlayerV2(target); }, 1.5f, "Shapeshifting Suicide Delay");
|
||||
@@ -1437,7 +1446,7 @@ static class ExtendedPlayerControl
|
||||
}
|
||||
target.Data.IsDead = true;
|
||||
|
||||
NotifyRoles(SpecifySeer: killer);
|
||||
NotifyRoles(SpecifySeer: killer, SpecifyTarget: target);
|
||||
NotifyRoles(SpecifySeer: target);
|
||||
}
|
||||
public static bool RpcCheckAndMurder(this PlayerControl killer, PlayerControl target, bool check = false) => CheckMurderPatch.RpcCheckAndMurder(killer, target, check);
|
||||
|
||||
@@ -118,7 +118,8 @@ public static class Options
|
||||
"Ban",
|
||||
"Kick",
|
||||
"NoticeMe",
|
||||
"NoticeEveryone"
|
||||
"NoticeEveryone",
|
||||
"OnlyCancel"
|
||||
];
|
||||
public static readonly string[] ConfirmEjectionsMode =
|
||||
[
|
||||
@@ -1123,7 +1124,7 @@ public static class Options
|
||||
NameDisplayAddons = BooleanOptionItem.Create(210, "NameDisplayAddons", true, TabGroup.Addons, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true);
|
||||
NoLimitAddonsNumMax = IntegerOptionItem.Create(211, "NoLimitAddonsNumMax", new(1, 15, 1), 1, TabGroup.Addons, false)
|
||||
NoLimitAddonsNumMax = IntegerOptionItem.Create(211, "NoLimitAddonsNumMax", new(1, 90, 1), 1, TabGroup.Addons, false)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
|
||||
//==================================================================================================================================//
|
||||
@@ -3704,7 +3705,7 @@ public static class Options
|
||||
.SetHeader(true)
|
||||
.SetGameMode(customGameMode) as StringOptionItem;
|
||||
|
||||
var countOption = IntegerOptionItem.Create(id + 1, "Maximum", new(1, canSetNum ? 10 : 1, 1), 1, tab, false)
|
||||
var countOption = IntegerOptionItem.Create(id + 1, "Maximum", new(1, canSetNum ? 15 : 1, 1), 1, tab, false)
|
||||
.SetParent(spawnOption)
|
||||
.SetValueFormat(OptionFormat.Players)
|
||||
.SetHidden(!canSetNum)
|
||||
|
||||
@@ -6,14 +6,8 @@ public class StringOptionItem(int id, string name, int defaultValue, TabGroup ta
|
||||
public IntegerValueRule Rule = (0, selections.Length - 1, 1);
|
||||
public string[] Selections = selections;
|
||||
|
||||
public static StringOptionItem Create(
|
||||
int id, string name, string[] selections, int defaultIndex, TabGroup tab, bool isSingleValue
|
||||
)
|
||||
{
|
||||
return new StringOptionItem(
|
||||
id, name, defaultIndex, tab, isSingleValue, selections
|
||||
);
|
||||
}
|
||||
public static StringOptionItem Create(int id, string name, string[] selections, int defaultIndex, TabGroup tab, bool isSingleValue)
|
||||
=> new(id, name, defaultIndex, tab, isSingleValue, selections);
|
||||
|
||||
// Getter
|
||||
public override int GetInt() => Rule.GetValueByIndex(CurrentValue);
|
||||
|
||||
@@ -58,6 +58,8 @@ enum CustomRPC
|
||||
|
||||
//Roles
|
||||
SetDrawPlayer,
|
||||
SyncMycologist,
|
||||
SyncBubble,
|
||||
AddTornado,
|
||||
RemoveTornado,
|
||||
SyncSprayer,
|
||||
@@ -585,6 +587,12 @@ internal class RPCHandlerPatch
|
||||
case CustomRPC.SendFireWorksState:
|
||||
FireWorks.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.SyncMycologist:
|
||||
Mycologist.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.SyncBubble:
|
||||
Bubble.ReceiveRPC(reader);
|
||||
break;
|
||||
case CustomRPC.SetCurrentDousingTarget:
|
||||
byte arsonistId = reader.ReadByte();
|
||||
byte dousingTargetId = reader.ReadByte();
|
||||
|
||||
+147
-47
@@ -1,4 +1,3 @@
|
||||
using Csv;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
using System;
|
||||
@@ -7,6 +6,7 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace TOHE;
|
||||
@@ -17,55 +17,105 @@ public static class Translator
|
||||
public const string LANGUAGE_FOLDER_NAME = "Language";
|
||||
public static void Init()
|
||||
{
|
||||
Logger.Info("Loading language file...", "Translator");
|
||||
Logger.Info("Loading Custom Translations...", "Translator");
|
||||
LoadLangs();
|
||||
Logger.Info("Language file loaded successfully", "Translator");
|
||||
Logger.Info("Loaded Custom Translations", "Translator");
|
||||
}
|
||||
public static void LoadLangs()
|
||||
{
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
var stream = assembly.GetManifestResourceStream("TOHE.Resources.String.csv");
|
||||
translateMaps = [];
|
||||
try
|
||||
{
|
||||
// Get the directory containing the JSON files (e.g., TOHE.Resources.Lang)
|
||||
string jsonDirectory = "TOHE.Resources.Lang";
|
||||
// Get the assembly containing the resources
|
||||
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
|
||||
string[] jsonFileNames = GetJsonFileNames(assembly, jsonDirectory);
|
||||
|
||||
var options = new CsvOptions()
|
||||
{
|
||||
HeaderMode = HeaderMode.HeaderPresent,
|
||||
AllowNewLineInEnclosedFieldValues = false,
|
||||
};
|
||||
foreach (var line in CsvReader.ReadFromStream(stream, options))
|
||||
{
|
||||
if (line.Values[0][0] == '#') continue;
|
||||
try
|
||||
translateMaps = [];
|
||||
|
||||
if (jsonFileNames.Length == 0)
|
||||
{
|
||||
Dictionary<int, string> dic = [];
|
||||
for (int i = 1; i < line.ColumnCount; i++)
|
||||
Logger.Warn("Json Translation files does not exist.", "Translator");
|
||||
return;
|
||||
}
|
||||
foreach (string jsonFileName in jsonFileNames)
|
||||
{
|
||||
// Read the JSON file content
|
||||
using Stream resourceStream = assembly.GetManifestResourceStream(jsonFileName);
|
||||
if (resourceStream != null)
|
||||
{
|
||||
int id = int.Parse(line.Headers[i]);
|
||||
dic[id] = line.Values[i].Replace("\\n", "\n").Replace("\\r", "\r");
|
||||
using StreamReader reader = new(resourceStream);
|
||||
string jsonContent = reader.ReadToEnd();
|
||||
|
||||
// Deserialize the JSON into a dictionary
|
||||
Dictionary<string, string> jsonDictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(jsonContent);
|
||||
if (jsonDictionary.TryGetValue("LanguageID", out string languageIdObj) && int.TryParse(languageIdObj, out int languageId))
|
||||
{
|
||||
// Remove the "LanguageID" entry
|
||||
jsonDictionary.Remove("LanguageID");
|
||||
|
||||
// Handle the rest of the data and merge it into the resulting translation map
|
||||
MergeJsonIntoTranslationMap(translateMaps, languageId, jsonDictionary);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Logger.Warn(jsonDictionary["HostText"], "Translator");
|
||||
Logger.Warn($"Invalid JSON format in {jsonFileName}: Missing or invalid 'LanguageID' field.", "Translator");
|
||||
}
|
||||
}
|
||||
if (!translateMaps.TryAdd(line.Values[0], dic))
|
||||
Logger.Warn($"Duplicate in CSV file to be translated: line {line.Index} => \"{line.Values[0]}\"", "Translator");
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
// Convert the resulting translation map to JSON
|
||||
string mergedJson = JsonSerializer.Serialize(translateMaps, new JsonSerializerOptions
|
||||
{
|
||||
Logger.Warn($"Translation file error: line {line.Index} => \"{line.Values[0]}\"", "Translator");
|
||||
Logger.Warn(ex.ToString(), "Translator");
|
||||
}
|
||||
WriteIndented = true
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Error: {ex}", "Translator");
|
||||
}
|
||||
|
||||
// カスタム翻訳ファイルの読み込み
|
||||
// Loading custom translation files
|
||||
if (!Directory.Exists(LANGUAGE_FOLDER_NAME)) Directory.CreateDirectory(LANGUAGE_FOLDER_NAME);
|
||||
|
||||
// 翻訳テンプレートの作成
|
||||
// Creating a translation template
|
||||
CreateTemplateFile();
|
||||
System.Collections.IList list = Enum.GetValues(typeof(SupportedLangs));
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
foreach (var lang in EnumHelper.GetAllValues<SupportedLangs>())
|
||||
{
|
||||
object lang = list[i];
|
||||
if (File.Exists(@$"./{LANGUAGE_FOLDER_NAME}/{lang}.dat"))
|
||||
LoadCustomTranslation($"{lang}.dat", (SupportedLangs)lang);
|
||||
{
|
||||
UpdateCustomTranslation($"{lang}.dat", lang);
|
||||
LoadCustomTranslation($"{lang}.dat", lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void MergeJsonIntoTranslationMap(Dictionary<string, Dictionary<int, string>> translationMaps, int languageId, Dictionary<string, string> jsonDictionary)
|
||||
{
|
||||
foreach (var kvp in jsonDictionary)
|
||||
{
|
||||
string textString = kvp.Key;
|
||||
if (kvp.Value is string translation)
|
||||
{
|
||||
|
||||
// If the textString is not already in the translation map, add it
|
||||
if (!translationMaps.ContainsKey(textString))
|
||||
{
|
||||
translationMaps[textString] = [];
|
||||
}
|
||||
|
||||
// Add or update the translation for the current id and textString
|
||||
translationMaps[textString][languageId] = translation.Replace("\\n", "\n").Replace("\\r", "\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to get a list of JSON file names in a directory
|
||||
static string[] GetJsonFileNames(System.Reflection.Assembly assembly, string directoryName)
|
||||
{
|
||||
string[] resourceNames = assembly.GetManifestResourceNames();
|
||||
return resourceNames.Where(resourceName => resourceName.StartsWith(directoryName) && resourceName.EndsWith(".json")).ToArray();
|
||||
}
|
||||
|
||||
public static string GetString(string s, Dictionary<string, string> replacementDic = null, bool console = false)
|
||||
{
|
||||
@@ -93,8 +143,8 @@ public static class Translator
|
||||
}
|
||||
if (!translateMaps.ContainsKey(str)) //translateMapsにない場合、StringNamesにあれば取得する
|
||||
{
|
||||
var stringNames = Enum.GetValues(typeof(StringNames)).Cast<StringNames>().Where(x => x.ToString() == str);
|
||||
if (stringNames != null && stringNames.Any())
|
||||
var stringNames = EnumHelper.GetAllValues<StringNames>().Where(x => x.ToString() == str).ToArray();
|
||||
if (stringNames != null && stringNames.Length > 0)
|
||||
res = GetString(stringNames.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
@@ -132,34 +182,84 @@ public static class Translator
|
||||
return SupportedLangs.English;
|
||||
}
|
||||
}
|
||||
static void UpdateCustomTranslation(string filename, SupportedLangs lang)
|
||||
{
|
||||
string path = @$"./{LANGUAGE_FOLDER_NAME}/{filename}";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
Logger.Info("Updating Custom Translations", "UpdateCustomTranslation");
|
||||
try
|
||||
{
|
||||
List<string> textStrings = [];
|
||||
using (StreamReader reader = new(path, Encoding.GetEncoding("UTF-8")))
|
||||
{
|
||||
string line;
|
||||
while ((line = reader.ReadLine()) != null)
|
||||
{
|
||||
// Split the line by ':' to get the first part
|
||||
string[] parts = line.Split(':');
|
||||
|
||||
// Check if there is at least one part before ':'
|
||||
if (parts.Length >= 1)
|
||||
{
|
||||
// Trim any leading or trailing spaces and add it to the list
|
||||
string textString = parts[0].Trim();
|
||||
textStrings.Add(textString);
|
||||
}
|
||||
}
|
||||
}
|
||||
var sb = new StringBuilder();
|
||||
foreach (var templateString in translateMaps.Keys)
|
||||
{
|
||||
if (!textStrings.Contains(templateString)) sb.Append($"{templateString}:\n");
|
||||
}
|
||||
using FileStream fileStream = new(path, FileMode.Append, FileAccess.Write);
|
||||
using StreamWriter writer = new(fileStream);
|
||||
writer.WriteLine(sb.ToString());
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("An error occurred: " + e.Message, "Translator");
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void LoadCustomTranslation(string filename, SupportedLangs lang)
|
||||
{
|
||||
string path = @$"./{LANGUAGE_FOLDER_NAME}/{filename}";
|
||||
if (File.Exists(path))
|
||||
{
|
||||
Logger.Info($"Loading custom translation file:{filename}", "LoadCustomTranslation");
|
||||
using StreamReader sr = new(path, Encoding.GetEncoding("UTF-8"));
|
||||
string text;
|
||||
string[] tmp = [];
|
||||
while ((text = sr.ReadLine()) != null)
|
||||
Logger.Info($"Loading Custom Translation File:{filename}", "LoadCustomTranslation");
|
||||
try
|
||||
{
|
||||
tmp = text.Split(":");
|
||||
if (tmp.Length > 1 && tmp[1] != "")
|
||||
using StreamReader sr = new(path, Encoding.GetEncoding("UTF-8"));
|
||||
string text;
|
||||
string[] tmp = [];
|
||||
while ((text = sr.ReadLine()) != null)
|
||||
{
|
||||
try
|
||||
tmp = text.Split(":");
|
||||
if (tmp.Length > 1 && tmp[1] != "")
|
||||
{
|
||||
translateMaps[tmp[0]][(int)lang] = tmp.Skip(1).Join(delimiter: ":").Replace("\\n", "\n").Replace("\\r", "\r");
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
Logger.Warn($"Invalid key:{tmp[0]}", "LoadCustomTranslation");
|
||||
try
|
||||
{
|
||||
translateMaps[tmp[0]][(int)lang] = tmp.Skip(1).Join(delimiter: ":").Replace("\\n", "\n").Replace("\\r", "\r");
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
Logger.Warn($"Invalid Key:{tmp[0]}", "LoadCustomTranslation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException) { }
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e.ToString(), "Translator.LoadCustomTranslation");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Error($"Custom translation file not found:{filename}", "LoadCustomTranslation");
|
||||
Logger.Error($"Custom Translation File Not Found:{filename}", "LoadCustomTranslation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-37
@@ -79,13 +79,13 @@ public static class Utils
|
||||
}
|
||||
}
|
||||
|
||||
public static void TP(CustomNetworkTransform nt, Vector2 location)
|
||||
public static bool TP(CustomNetworkTransform nt, Vector2 location)
|
||||
{
|
||||
var pc = nt.myPlayer;
|
||||
if (pc.inVent || pc.inMovingPlat || !pc.IsAlive())
|
||||
if (pc.inVent || pc.inMovingPlat || !pc.IsAlive() || pc.MyPhysics.Animations.IsPlayingAnyLadderAnimation() || pc.MyPhysics.Animations.IsPlayingEnterVentAnimation())
|
||||
{
|
||||
Logger.Warn($"Target ({pc.GetNameWithRole().RemoveHtmlTags()}) is in an un-teleportable state - Teleporting canceled", "TP");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Modded
|
||||
@@ -98,15 +98,16 @@ public static class Utils
|
||||
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
|
||||
|
||||
Logger.Info($"{pc.GetNameWithRole().RemoveHtmlTags()} => {location}", "TP");
|
||||
return true;
|
||||
}
|
||||
public static void TPtoRndVent(CustomNetworkTransform nt)
|
||||
public static bool TPtoRndVent(CustomNetworkTransform nt)
|
||||
{
|
||||
var vents = UnityEngine.Object.FindObjectsOfType<Vent>();
|
||||
var vent = vents[IRandom.Instance.Next(0, vents.Count)];
|
||||
|
||||
Logger.Info($"{nt.myPlayer.GetNameWithRole().RemoveHtmlTags()} => {vent.transform.position} (vent)", "TP");
|
||||
|
||||
TP(nt, new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f));
|
||||
return TP(nt, new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f));
|
||||
}
|
||||
public static ClientData GetClientById(int id)
|
||||
{
|
||||
@@ -382,32 +383,8 @@ public static class Utils
|
||||
|
||||
if (Options.NameDisplayAddons.GetBool() && !pure && self)
|
||||
{
|
||||
if (Options.AddBracketsToAddons.GetBool())
|
||||
{
|
||||
if (Options.ImpEgoistVisibalToAllies.GetBool())
|
||||
{
|
||||
foreach (var subRole in targetSubRoles.Where(x => x is not CustomRoles.LastImpostor and not CustomRoles.Madmate and not CustomRoles.Charmed and not CustomRoles.Recruit and not CustomRoles.Admired and not CustomRoles.Soulless and not CustomRoles.Lovers and not CustomRoles.Infected and not CustomRoles.Contagious))
|
||||
RoleText = ColorString(GetRoleColor(subRole), GetString("PrefixB." + subRole.ToString())) + RoleText;
|
||||
}
|
||||
if (!Options.ImpEgoistVisibalToAllies.GetBool())
|
||||
{
|
||||
foreach (var subRole in targetSubRoles.Where(x => x is not CustomRoles.LastImpostor and not CustomRoles.Madmate and not CustomRoles.Charmed and not CustomRoles.Recruit and not CustomRoles.Admired and not CustomRoles.Soulless and not CustomRoles.Lovers and not CustomRoles.Infected and not CustomRoles.Contagious))
|
||||
RoleText = ColorString(GetRoleColor(subRole), GetString("PrefixB." + subRole.ToString())) + RoleText;
|
||||
}
|
||||
}
|
||||
else if (!Options.AddBracketsToAddons.GetBool())
|
||||
{
|
||||
if (Options.ImpEgoistVisibalToAllies.GetBool())
|
||||
{
|
||||
foreach (var subRole in targetSubRoles.Where(x => x is not CustomRoles.LastImpostor and not CustomRoles.Madmate and not CustomRoles.Charmed and not CustomRoles.Recruit and not CustomRoles.Admired and not CustomRoles.Soulless and not CustomRoles.Lovers and not CustomRoles.Infected and not CustomRoles.Contagious))
|
||||
RoleText = ColorString(GetRoleColor(subRole), GetString("Prefix." + subRole.ToString())) + RoleText;
|
||||
}
|
||||
if (!Options.ImpEgoistVisibalToAllies.GetBool())
|
||||
{
|
||||
foreach (var subRole in targetSubRoles.Where(x => x is not CustomRoles.LastImpostor and not CustomRoles.Madmate and not CustomRoles.Charmed and not CustomRoles.Recruit and not CustomRoles.Admired and not CustomRoles.Soulless and not CustomRoles.Lovers and not CustomRoles.Infected and not CustomRoles.Contagious))
|
||||
RoleText = ColorString(GetRoleColor(subRole), GetString("Prefix." + subRole.ToString())) + RoleText;
|
||||
}
|
||||
}
|
||||
foreach (var subRole in targetSubRoles.Where(x => x is not CustomRoles.LastImpostor and not CustomRoles.Madmate and not CustomRoles.Charmed and not CustomRoles.Recruit and not CustomRoles.Admired and not CustomRoles.Soulless and not CustomRoles.Lovers and not CustomRoles.Infected and not CustomRoles.Contagious))
|
||||
RoleText = ColorString(GetRoleColor(subRole), (Options.AddBracketsToAddons.GetBool() ? "<#ffffff>(</color>" : string.Empty) + GetString("Prefix." + subRole.ToString()) + (Options.AddBracketsToAddons.GetBool() ? "<#ffffff>)</color>" : string.Empty) + " ") + RoleText;
|
||||
}
|
||||
|
||||
if (targetSubRoles.Contains(CustomRoles.Madmate))
|
||||
@@ -1153,7 +1130,7 @@ public static class Utils
|
||||
Logger.Error($"For {pc.GetNameWithRole().RemoveHtmlTags()}, failed to get progress text: " + ex.ToString(), "Utils.GetProgressText");
|
||||
}
|
||||
|
||||
if (pc.Is(CustomRoles.Damocles)) ProgressText.Append(' ' + Damocles.GetProgressText());
|
||||
if (pc.Is(CustomRoles.Damocles)) ProgressText.Append(' ' + Damocles.GetProgressText(playerId));
|
||||
if (pc.Is(CustomRoles.Stressed)) ProgressText.Append(' ' + Stressed.GetProgressText(playerId));
|
||||
|
||||
if (ProgressText.Length != 0 && !ProgressText.ToString().StartsWith(' '))
|
||||
@@ -1881,12 +1858,13 @@ public static class Utils
|
||||
}
|
||||
|
||||
DevUser devUser = player.FriendCode.GetDevUser();
|
||||
if (!name.Contains('\r') && devUser.HasTag())
|
||||
bool isMod = ChatCommands.IsPlayerModerator(player.FriendCode);
|
||||
if (!name.Contains('\r') && (devUser.HasTag() || isMod))
|
||||
{
|
||||
string tag = devUser.GetTag();
|
||||
if (player.AmOwner || player.IsModClient())
|
||||
name = tag + name;
|
||||
else name = tag.Replace("\r\n", " - ") + name;
|
||||
name = tag + (isMod ? ("<size=1.4>" + GetString("ModeratorTag") + "\r\n</size>") : string.Empty) + name;
|
||||
else name = tag.Replace("\r\n", " - ") + (isMod ? ("<size=1.4>" + GetString("ModeratorTag") + " - </size>") : string.Empty) + name;
|
||||
}
|
||||
|
||||
if (player.AmOwner)
|
||||
@@ -1962,6 +1940,8 @@ public static class Utils
|
||||
PlayerControl[] seerList = SpecifySeer != null ? ([SpecifySeer]) : Main.AllPlayerControls;
|
||||
PlayerControl[] targetList = SpecifyTarget != null ? ([SpecifyTarget]) : Main.AllPlayerControls;
|
||||
|
||||
Logger.Info($" Seers: {string.Join(", ", seerList.Select(x => x.GetNameWithRole()))} Targets: {string.Join(", ", targetList.Select(x => x.GetNameWithRole()))}", "NR");
|
||||
|
||||
//seer: Players who can see changes made here
|
||||
//target: Players subject to changes that seer can see
|
||||
foreach (PlayerControl seer in seerList)
|
||||
@@ -2214,7 +2194,6 @@ public static class Utils
|
||||
if (target.PlayerId == seer.PlayerId) continue;
|
||||
Logger.Info("NotifyRoles-Loop2-" + target.GetNameWithRole().RemoveHtmlTags() + ":START", "NotifyRoles");
|
||||
|
||||
|
||||
if ((IsActive(SystemTypes.MushroomMixupSabotage) || MushroomMixup) && target.IsAlive() && !seer.Is(CustomRoleTypes.Impostor) && Main.ResetCamPlayerList.Contains(seer.PlayerId))
|
||||
{
|
||||
seer.RpcSetNamePrivate("<size=0%>", true, force: NoCache);
|
||||
@@ -2490,6 +2469,7 @@ public static class Utils
|
||||
|
||||
TargetSuffix.Append(PlagueDoctor.GetLowerTextOthers(seer, target));
|
||||
TargetSuffix.Append(Stealth.GetSuffix(seer, target));
|
||||
TargetSuffix.Append(Bubble.GetEncasedPlayerSuffix(seer, target));
|
||||
|
||||
if (target.Is(CustomRoles.Librarian)) TargetSuffix.Append(Librarian.GetNameTextForSuffix(target.PlayerId));
|
||||
|
||||
@@ -2898,7 +2878,7 @@ public static class Utils
|
||||
neutralnum++;
|
||||
}
|
||||
}
|
||||
return (notify ? "<#777777>" : string.Empty) +
|
||||
return (notify ? "<#777777>" : string.Empty) +
|
||||
(impnum == 1 ? GetString("RemainingText.Prefix.SingleImp") : GetString("RemainingText.Prefix.PluralImp")) +
|
||||
(notify ? " " : "\n") +
|
||||
(notify ? "<#ffffff>" : "<b>") +
|
||||
@@ -3057,4 +3037,5 @@ public static class Utils
|
||||
public static int PlayersCount(CountTypes countTypes) => Main.PlayerStates.Values.Count(state => state.countTypes == countTypes);
|
||||
public static int AlivePlayersCount(CountTypes countTypes) => Main.AllAlivePlayerControls.Count(pc => pc.Is(countTypes));
|
||||
public static int IsOneAlive(CountTypes countTypes) => Main.AllAlivePlayerControls.Any(pc => pc.Is(countTypes)) ? 1 : 0;
|
||||
public static bool IsNonHostModClient(this byte id) => id != 0 && Main.playerVersion.ContainsKey(id);
|
||||
}
|
||||
+46
-36
@@ -20,15 +20,16 @@ namespace TOHE;
|
||||
internal class ChatCommands
|
||||
{
|
||||
// Function to check if a player is a moderator
|
||||
private static bool IsPlayerModerator(string friendCode)
|
||||
public static bool IsPlayerModerator(string friendCode)
|
||||
{
|
||||
if (friendCode == "" || friendCode == string.Empty) return false;
|
||||
if (friendCode == "" || friendCode == string.Empty || !Options.ApplyModeratorList.GetBool()) return false;
|
||||
var friendCodesFilePath = @"./TOHE_DATA/Moderators.txt";
|
||||
var friendCodes = File.ReadAllLines(friendCodesFilePath);
|
||||
return friendCodes.Any(code => code.Contains(friendCode));
|
||||
return friendCodes.Any(code => code.Contains(friendCode, StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public static List<string> ChatHistory = [];
|
||||
public static Dictionary<byte, long> LastSentCommand = [];
|
||||
|
||||
public static bool Prefix(ChatController __instance)
|
||||
{
|
||||
@@ -75,7 +76,7 @@ internal class ChatCommands
|
||||
switch (args[0])
|
||||
{
|
||||
case "/dump":
|
||||
canceled = true;
|
||||
//canceled = true;
|
||||
Utils.DumpLog();
|
||||
break;
|
||||
case "/v":
|
||||
@@ -321,6 +322,7 @@ internal class ChatCommands
|
||||
Utils.SendMessage(args.Skip(1).Join(delimiter: " "), title: $"<color=#ff0000>{GetString("MessageFromTheHost")}</color>");
|
||||
break;
|
||||
|
||||
case "/ban":
|
||||
case "/kick":
|
||||
canceled = true;
|
||||
// Check if the kick command is enabled in the settings
|
||||
@@ -365,7 +367,7 @@ internal class ChatCommands
|
||||
}
|
||||
|
||||
// Kick the specified player
|
||||
AmongUsClient.Instance.KickPlayer(kickedPlayer.GetClientId(), true);
|
||||
AmongUsClient.Instance.KickPlayer(kickedPlayer.GetClientId(), args[0] == "/ban");
|
||||
string kickedPlayerName = kickedPlayer.GetRealName();
|
||||
string textToSend = $"{kickedPlayerName} {GetString("KickCommandKicked")}";
|
||||
if (GameStates.IsInGame)
|
||||
@@ -430,11 +432,11 @@ internal class ChatCommands
|
||||
Utils.SendMessage(string.Format(GetString("Message.SetColor"), subArgs), localPlayerId);
|
||||
break;
|
||||
|
||||
case "/quit":
|
||||
case "/qt":
|
||||
canceled = true;
|
||||
Utils.SendMessage(GetString("Message.CanNotUseByHost"), localPlayerId);
|
||||
break;
|
||||
//case "/quit":
|
||||
//case "/qt":
|
||||
// canceled = true;
|
||||
// Utils.SendMessage(GetString("Message.CanNotUseByHost"), localPlayerId);
|
||||
// break;
|
||||
|
||||
case "/xf":
|
||||
canceled = true;
|
||||
@@ -817,7 +819,8 @@ internal class ChatCommands
|
||||
if (isUp) return;
|
||||
}
|
||||
var sb = new StringBuilder();
|
||||
_ = sb.Append($"{devMark}<b>{roleName}</b>{Utils.GetRoleMode(rl)}{GetString($"{rl}InfoLong")}");
|
||||
var title = $"{devMark}<{Main.roleColors[rl]}>{roleName}</color> {Utils.GetRoleMode(rl)}";
|
||||
_ = sb.Append($"{GetString($"{rl}InfoLong")}");
|
||||
var settings = new StringBuilder();
|
||||
if (Options.CustomRoleSpawnChances.ContainsKey(rl))
|
||||
{
|
||||
@@ -828,7 +831,7 @@ internal class ChatCommands
|
||||
_ = sb.Clear().Append(txt);
|
||||
}
|
||||
Utils.SendMessage(text: "\n", sendTo: playerId, title: settings.ToString());
|
||||
Utils.SendMessage(text: sb.ToString(), sendTo: playerId);
|
||||
Utils.SendMessage(text: sb.ToString(), sendTo: playerId, title: title);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -840,6 +843,8 @@ internal class ChatCommands
|
||||
{
|
||||
canceled = false;
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
long now = Utils.GetTimeStamp();
|
||||
if (LastSentCommand.TryGetValue(player.PlayerId, out var ts) && ts + 2 >= now) { Logger.Warn("Command Ignored, it was sent too soon after their last command", "ReceiveChat"); return; }
|
||||
if (player.PlayerId != 0) ChatManager.SendMessage(player, text);
|
||||
if (text.StartsWith("\n")) text = text[1..];
|
||||
//if (!text.StartsWith("/")) return;
|
||||
@@ -847,22 +852,24 @@ internal class ChatCommands
|
||||
string subArgs = string.Empty;
|
||||
//if (text.Length >= 3) if (text[..2] == "/r" && text[..3] != "/rn") args[0] = "/r";
|
||||
// if (SpamManager.CheckSpam(player, text)) return;
|
||||
if (GuessManager.GuesserMsg(player, text)) { canceled = true; return; }
|
||||
if (Judge.TrialMsg(player, text)) { canceled = true; return; }
|
||||
if (NiceSwapper.SwapMsg(player, text)) { canceled = true; return; }
|
||||
if (ParityCop.ParityCheckMsg(player, text)) { canceled = true; return; }
|
||||
if (GuessManager.GuesserMsg(player, text)) { canceled = true; LastSentCommand[player.PlayerId] = now; return; }
|
||||
if (Judge.TrialMsg(player, text)) { canceled = true; LastSentCommand[player.PlayerId] = now; return; }
|
||||
if (NiceSwapper.SwapMsg(player, text)) { canceled = true; LastSentCommand[player.PlayerId] = now; return; }
|
||||
if (ParityCop.ParityCheckMsg(player, text)) { canceled = true; LastSentCommand[player.PlayerId] = now; return; }
|
||||
//if (Pirate.DuelCheckMsg(player, text)) { canceled = true; return; }
|
||||
if (Councillor.MurderMsg(player, text)) { canceled = true; return; }
|
||||
if (Mediumshiper.MsMsg(player, text)) return;
|
||||
if (MafiaRevengeManager.MafiaMsgCheck(player, text)) return;
|
||||
if (Councillor.MurderMsg(player, text)) { canceled = true; LastSentCommand[player.PlayerId] = now; return; }
|
||||
if (Mediumshiper.MsMsg(player, text)) { LastSentCommand[player.PlayerId] = now; return; }
|
||||
if (MafiaRevengeManager.MafiaMsgCheck(player, text)) { LastSentCommand[player.PlayerId] = now; return; }
|
||||
//if (RetributionistRevengeManager.RetributionistMsgCheck(player, text)) return;
|
||||
if (Blackmailer.ForBlackmailer.Contains(player.PlayerId) && player.IsAlive() && player.PlayerId != 0)
|
||||
{
|
||||
ChatManager.SendPreviousMessagesToAll();
|
||||
ChatManager.cancel = false;
|
||||
canceled = true;
|
||||
LastSentCommand[player.PlayerId] = now;
|
||||
return;
|
||||
}
|
||||
bool isCommand = true;
|
||||
switch (args[0])
|
||||
{
|
||||
case "/l":
|
||||
@@ -967,22 +974,22 @@ internal class ChatCommands
|
||||
}
|
||||
break;
|
||||
|
||||
case "/quit":
|
||||
case "/qt":
|
||||
subArgs = args.Length < 2 ? string.Empty : args[1];
|
||||
var cid = player.PlayerId.ToString();
|
||||
cid = cid.Length != 1 ? cid.Substring(1, 1) : cid;
|
||||
if (subArgs.Equals(cid))
|
||||
{
|
||||
string name = player.GetRealName();
|
||||
Utils.SendMessage(string.Format(GetString("Message.PlayerQuitForever"), name));
|
||||
AmongUsClient.Instance.KickPlayer(player.GetClientId(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Utils.SendMessage(string.Format(GetString("SureUse.quit"), cid), player.PlayerId);
|
||||
}
|
||||
break;
|
||||
//case "/quit":
|
||||
//case "/qt":
|
||||
// subArgs = args.Length < 2 ? string.Empty : args[1];
|
||||
// var cid = player.PlayerId.ToString();
|
||||
// cid = cid.Length != 1 ? cid.Substring(1, 1) : cid;
|
||||
// if (subArgs.Equals(cid))
|
||||
// {
|
||||
// string name = player.GetRealName();
|
||||
// Utils.SendMessage(string.Format(GetString("Message.PlayerQuitForever"), name));
|
||||
// AmongUsClient.Instance.KickPlayer(player.GetClientId(), true);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// Utils.SendMessage(string.Format(GetString("SureUse.quit"), cid), player.PlayerId);
|
||||
// }
|
||||
// break;
|
||||
case "/id":
|
||||
if (Options.ApplyModeratorList.GetValue() == 0 || !IsPlayerModerator(player.FriendCode)) break;
|
||||
|
||||
@@ -994,6 +1001,7 @@ internal class ChatCommands
|
||||
|
||||
Utils.SendMessage(msgText, player.PlayerId);
|
||||
break;
|
||||
case "/ban":
|
||||
case "/kick":
|
||||
// Check if the kick command is enabled in the settings
|
||||
if (Options.ApplyModeratorList.GetValue() == 0)
|
||||
@@ -1037,7 +1045,7 @@ internal class ChatCommands
|
||||
}
|
||||
|
||||
// Kick the specified player
|
||||
AmongUsClient.Instance.KickPlayer(kickedPlayer.GetClientId(), true);
|
||||
AmongUsClient.Instance.KickPlayer(kickedPlayer.GetClientId(), args[0] == "/ban");
|
||||
string kickedPlayerName = kickedPlayer.GetRealName();
|
||||
string textToSend = $"{kickedPlayerName} {GetString("KickCommandKicked")}";
|
||||
if (GameStates.IsInGame)
|
||||
@@ -1133,8 +1141,10 @@ internal class ChatCommands
|
||||
}
|
||||
|
||||
default:
|
||||
isCommand = false;
|
||||
break;
|
||||
}
|
||||
if (isCommand) LastSentCommand[player.PlayerId] = now;
|
||||
if (SpamManager.CheckSpam(player, text)) return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,17 +447,18 @@ class GameEndChecker
|
||||
|
||||
foreach (PlayerControl x in Main.AllAlivePlayerControls)
|
||||
{
|
||||
if (x.GetCustomRole().IsImpostor() && x.Is(CustomRoles.DualPersonality)) Imp++;
|
||||
if (x.GetCustomRole().IsCrewmate() && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (x.GetCustomRole().IsImpostor() && x.Is(CustomRoles.Admired) && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (x.GetCustomRole().IsNeutral() && x.Is(CustomRoles.Admired) && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (x.GetCustomRole().IsCrewmate() && x.Is(CustomRoles.Admired) && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
CustomRoles role = x.GetCustomRole();
|
||||
if ((x.Is(CustomRoles.Madmate) && x.Is(CustomRoles.DualPersonality)) ||
|
||||
(role.IsImpostor() && x.Is(CustomRoles.DualPersonality))) Imp++;
|
||||
if (role.IsCrewmate() && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (role.IsImpostor() && x.Is(CustomRoles.Admired) && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (role.IsNeutral() && x.Is(CustomRoles.Admired) && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (role.IsCrewmate() && x.Is(CustomRoles.Admired) && x.Is(CustomRoles.DualPersonality)) Crew++;
|
||||
if (x.Is(CustomRoles.Charmed) && x.Is(CustomRoles.DualPersonality)) roleCounts[(null, CustomWinner.Succubus)]++;
|
||||
if (x.Is(CustomRoles.Sidekick) && x.Is(CustomRoles.DualPersonality)) roleCounts[(null, CustomWinner.Jackal)]++;
|
||||
if (x.Is(CustomRoles.Recruit) && x.Is(CustomRoles.DualPersonality)) roleCounts[(null, CustomWinner.Jackal)]++;
|
||||
if (x.Is(CustomRoles.Infected) && x.Is(CustomRoles.DualPersonality)) roleCounts[(null, CustomWinner.Infectious)]++;
|
||||
if (x.Is(CustomRoles.Contagious) && x.Is(CustomRoles.DualPersonality)) roleCounts[(null, CustomWinner.Virus)]++;
|
||||
if (x.Is(CustomRoles.Madmate) && x.Is(CustomRoles.DualPersonality)) Imp++;
|
||||
}
|
||||
|
||||
int totalNKAlive = roleCounts.Values.Sum();
|
||||
|
||||
@@ -263,6 +263,9 @@ public class StringOptionEnablePatch
|
||||
|
||||
__instance.OnValueChanged = new Action<OptionBehaviour>((o) => { });
|
||||
__instance.TitleText.text = option.GetName();
|
||||
if (option.Id == Options.UsePets.Id) LoadLangs();
|
||||
else if (!Options.UsePets.GetBool() && CustomRolesHelper.OnlySpawnsWithPetsRoleList.Any(role => role.ToString().Equals(option.GetName().RemoveHtmlTags())))
|
||||
__instance.TitleText.text += GetString("RequiresPetIndicator");
|
||||
__instance.Value = __instance.oldValue = option.CurrentValue;
|
||||
__instance.ValueText.text = option.GetString();
|
||||
|
||||
|
||||
+33
-2
@@ -591,9 +591,26 @@ class HudManagerPatch
|
||||
__instance.KillButton?.ToggleVisible(false);
|
||||
}
|
||||
|
||||
bool CanUseVent = player.CanUseImpostorVentButton() && GameStates.IsInTask;
|
||||
bool CanUseVent = (player.CanUseImpostorVentButton() || player.inVent || player.MyPhysics.Animations.IsPlayingEnterVentAnimation()) && GameStates.IsInTask;
|
||||
__instance.ImpostorVentButton?.ToggleVisible(CanUseVent);
|
||||
player.Data.Role.CanVent = CanUseVent;
|
||||
|
||||
var vents = Object.FindObjectsOfType<Vent>().ToArray();
|
||||
if (player.PlayerId == 0 && player.inVent && GameStates.IsInTask) SetVentButtonEnabled(TryMoveToVentPatch.HostVentTarget);
|
||||
else if (CanUseVent && vents.Any(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), player.Pos()) < 0.4f))
|
||||
{
|
||||
Vent vent = vents.FirstOrDefault(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), player.Pos()) < 0.4f);
|
||||
SetVentButtonEnabled(vent);
|
||||
}
|
||||
void SetVentButtonEnabled(Vent target)
|
||||
{
|
||||
__instance.ImpostorVentButton.canInteract = true;
|
||||
__instance.ImpostorVentButton.enabled = true;
|
||||
__instance.ImpostorVentButton.isCoolingDown = false;
|
||||
__instance.ImpostorVentButton.SetEnabled();
|
||||
__instance.ImpostorVentButton.currentTarget = target;
|
||||
__instance.ImpostorVentButton.SetTarget(target);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -773,7 +790,21 @@ class VentButtonDoClickPatch
|
||||
{
|
||||
var pc = PlayerControl.LocalPlayer;
|
||||
{
|
||||
if (!pc.Is(CustomRoles.Swooper) || !pc.Is(CustomRoles.Wraith) || !pc.Is(CustomRoles.Chameleon) || pc.inVent || __instance.currentTarget == null || !pc.CanMove || !__instance.isActiveAndEnabled) return true;
|
||||
if (pc.inVent)
|
||||
{
|
||||
pc.MyPhysics.RpcExitVent(TryMoveToVentPatch.HostVentTarget.Id);
|
||||
TryMoveToVentPatch.HostVentTarget.SetButtons(false);
|
||||
return true;
|
||||
}
|
||||
if (pc.inVent || !pc.CanMove) return true;
|
||||
var vents = Object.FindObjectsOfType<Vent>().ToArray();
|
||||
if (vents.Any(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), pc.Pos()) < 0.4f))
|
||||
{
|
||||
Vent vent = vents.FirstOrDefault(vent => Vector2.Distance(new Vector2(vent.transform.position.x, vent.transform.position.y + 0.3636f), pc.Pos()) < 0.4f);
|
||||
pc.MyPhysics.RpcEnterVent(vent.Id);
|
||||
vent.SetButtons(true);
|
||||
return false;
|
||||
}
|
||||
pc?.MyPhysics?.RpcEnterVent(__instance.currentTarget.Id);
|
||||
return false;
|
||||
}
|
||||
|
||||
+13
-12
@@ -113,6 +113,7 @@ class SetEverythingUpPatch
|
||||
|
||||
try
|
||||
{
|
||||
// ---------- Code from TOR (The Other Roles)! ----------
|
||||
if (Options.CurrentGameMode is not CustomGameMode.Standard) goto End;
|
||||
int num = Mathf.CeilToInt(7.5f);
|
||||
List<WinningPlayerData> winningPlayerDataList = TempData.winners.ToArray().ToList();
|
||||
@@ -144,19 +145,20 @@ class SetEverythingUpPatch
|
||||
|
||||
poolablePlayer.cosmetics.nameText.color = Color.white;
|
||||
poolablePlayer.cosmetics.nameText.transform.localScale = new Vector3(1f / vector.x, 1f / vector.y, 1f / vector.z);
|
||||
poolablePlayer.cosmetics.nameText.transform.localPosition = new Vector3(poolablePlayer.cosmetics.nameText.transform.localPosition.x, !lowered ? poolablePlayer.cosmetics.nameText.transform.localPosition.y - 0.6f : poolablePlayer.cosmetics.nameText.transform.localPosition.y - 1.4f, -15f);
|
||||
poolablePlayer.cosmetics.nameText.text = winningPlayerData2.PlayerName;
|
||||
|
||||
Vector3 defaultPos = poolablePlayer.cosmetics.nameText.transform.localPosition;
|
||||
|
||||
for (int i1 = 0; i1 < Main.winnerList.Count; i1++)
|
||||
{
|
||||
byte id = Main.winnerList[i1];
|
||||
if (Main.winnerNameList[i1].RemoveHtmlTags() != winningPlayerData2?.PlayerName.RemoveHtmlTags()) continue;
|
||||
var color = Main.roleColors[Main.winnerRolesList[i1]];
|
||||
var rolename = Utils.GetRoleName(Main.PlayerStates[id].MainRole);
|
||||
var role = Main.PlayerStates[id].MainRole;
|
||||
var color = Main.roleColors[role];
|
||||
var rolename = Utils.GetRoleName(role);
|
||||
poolablePlayer.cosmetics.nameText.text += $"\n<color={color}>{rolename}</color>";
|
||||
poolablePlayer.cosmetics.nameText.transform.localPosition = new Vector3(defaultPos.x, !lowered || role.IsImpostorTeamV3() || role.IsNK() ? defaultPos.y - 0.6f : defaultPos.y - 1.4f, -15f);
|
||||
}
|
||||
|
||||
poolablePlayer.cosmetics.nameText.text += $"<size=0>";
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -316,21 +318,21 @@ class SetEverythingUpPatch
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//#######################################
|
||||
// ==最終結果表示==
|
||||
//#######################################
|
||||
//########################################
|
||||
// ==The final result indicates==
|
||||
//########################################
|
||||
|
||||
var Pos = Camera.main.ViewportToWorldPoint(new Vector3(0f, 1f, Camera.main.nearClipPlane));
|
||||
var RoleSummaryObject = UnityEngine.Object.Instantiate(__instance.WinText.gameObject);
|
||||
RoleSummaryObject.transform.position = new Vector3(__instance.Navigation.ExitButton.transform.position.x + 0.1f, Pos.y - 0.1f, -15f);
|
||||
RoleSummaryObject.transform.localScale = new Vector3(1f, 1f, 1f);
|
||||
|
||||
StringBuilder sb = new($"{GetString("RoleSummaryText")}\n");
|
||||
StringBuilder sb = new($"{GetString("RoleSummaryText")}\n<b>");
|
||||
List<byte> cloneRoles = new(Main.PlayerStates.Keys);
|
||||
foreach (byte id in Main.winnerList.ToArray())
|
||||
{
|
||||
if (EndGamePatch.SummaryText[id].Contains("<INVALID:NotAssigned>")) continue;
|
||||
sb.Append($"\n<b>").Append(EndGamePatch.SummaryText[id]);
|
||||
sb.Append('\n').Append(EndGamePatch.SummaryText[id]);
|
||||
cloneRoles.Remove(id);
|
||||
}
|
||||
switch (Options.CurrentGameMode)
|
||||
@@ -379,8 +381,7 @@ class SetEverythingUpPatch
|
||||
sb.Append($"</b>\n");
|
||||
foreach (byte id in cloneRoles.ToArray())
|
||||
{
|
||||
if (EndGamePatch.SummaryText[id].Contains("<INVALID:NotAssigned>"))
|
||||
continue;
|
||||
if (EndGamePatch.SummaryText[id].Contains("<INVALID:NotAssigned>")) continue;
|
||||
sb.Append('\n').Append(EndGamePatch.SummaryText[id]);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,12 @@ class ExternalRpcPetPatch
|
||||
Pelican.IsEaten(pc.PlayerId))
|
||||
return;
|
||||
|
||||
if (Mastermind.ManipulatedPlayers.ContainsKey(pc.PlayerId))
|
||||
{
|
||||
var killTarget = SelectKillButtonTarget(pc);
|
||||
if (killTarget != null) Mastermind.ForceKillForManipulatedPlayer(pc, killTarget);
|
||||
}
|
||||
|
||||
if (pc.HasAbilityCD()) return;
|
||||
|
||||
PlayerControl[] AllAlivePlayers = Main.AllAlivePlayerControls;
|
||||
|
||||
@@ -214,15 +214,14 @@ class CheckMurderPatch
|
||||
//非自杀场景下才会触发
|
||||
switch (killer.GetCustomRole())
|
||||
{
|
||||
//==========内鬼阵营==========//
|
||||
case CustomRoles.BountyHunter: //必须在击杀发生前处理
|
||||
case CustomRoles.BountyHunter:
|
||||
BountyHunter.OnCheckMurder(killer, target);
|
||||
break;
|
||||
case CustomRoles.Reckless:
|
||||
Reckless.OnCheckMurder(killer);
|
||||
break;
|
||||
case CustomRoles.YinYanger:
|
||||
if (YinYanger.OnCheckMurder(killer, target)) return false;
|
||||
if (!YinYanger.OnCheckMurder(killer, target)) return false;
|
||||
break;
|
||||
case CustomRoles.Magician:
|
||||
Magician.OnCheckMurder(killer);
|
||||
@@ -1238,12 +1237,6 @@ class MurderPlayerPatch
|
||||
break;
|
||||
}
|
||||
|
||||
if (target.GetTeam() is Team.Impostor or Team.Neutral) Stressed.OnNonCrewmateDead();
|
||||
|
||||
if (killer.Is(CustomRoles.Damocles)) Damocles.OnMurder();
|
||||
else if (killer.Is(Team.Impostor)) Damocles.OnOtherImpostorMurder();
|
||||
if (target.Is(Team.Impostor)) Damocles.OnImpostorDeath();
|
||||
|
||||
if (killer.Is(CustomRoles.TicketsStealer) && killer.PlayerId != target.PlayerId)
|
||||
killer.Notify(string.Format(GetString("TicketsStealerGetTicket"), ((Main.AllPlayerControls.Count(x => x.GetRealKiller()?.PlayerId == killer.PlayerId) + 1) * Options.TicketsPerKill.GetFloat()).ToString("0.0#####")));
|
||||
|
||||
@@ -1401,7 +1394,7 @@ class ShapeshiftPatch
|
||||
isSSneeded = false;
|
||||
break;
|
||||
case CustomRoles.Librarian:
|
||||
if (shapeshifting) isSSneeded = Librarian.OnShapeshift(shapeshifter);
|
||||
isSSneeded = Librarian.OnShapeshift(shapeshifter, shapeshifting);
|
||||
break;
|
||||
case CustomRoles.Warlock:
|
||||
if (Main.CursedPlayers[shapeshifter.PlayerId] != null)//呪われた人がいるか確認
|
||||
@@ -1945,7 +1938,7 @@ class ReportDeadBodyPatch
|
||||
|
||||
if (player.Is(CustomRoles.Damocles))
|
||||
{
|
||||
Damocles.OnReport();
|
||||
Damocles.OnReport(player.PlayerId);
|
||||
}
|
||||
Damocles.OnMeetingStart();
|
||||
|
||||
@@ -1953,6 +1946,7 @@ class ReportDeadBodyPatch
|
||||
{
|
||||
Stressed.OnReport(player);
|
||||
}
|
||||
Stressed.OnMeetingStart();
|
||||
|
||||
if (Options.InhibitorCDAfterMeetings.GetFloat() != Options.InhibitorCD.GetFloat() || Options.SaboteurCD.GetFloat() != Options.SaboteurCDAfterMeetings.GetFloat())
|
||||
{
|
||||
@@ -2143,9 +2137,6 @@ class FixedUpdatePatch
|
||||
case CustomRoles.BountyHunter:
|
||||
BountyHunter.FixedUpdate(player);
|
||||
break;
|
||||
case CustomRoles.Tornado when !lowLoad:
|
||||
Tornado.OnFixedUpdate(player);
|
||||
break;
|
||||
case CustomRoles.Glitch when !lowLoad:
|
||||
Glitch.UpdateHackCooldown(player);
|
||||
break;
|
||||
@@ -2179,9 +2170,6 @@ class FixedUpdatePatch
|
||||
case CustomRoles.Bubble when !lowLoad:
|
||||
Bubble.OnFixedUpdate();
|
||||
break;
|
||||
case CustomRoles.Sprayer when !lowLoad:
|
||||
Sprayer.OnFixedUpdate();
|
||||
break;
|
||||
case CustomRoles.Sentinel when !lowLoad:
|
||||
Sentinel.OnFixedUpdate();
|
||||
break;
|
||||
@@ -2224,6 +2212,15 @@ class FixedUpdatePatch
|
||||
PlagueBearer.playerIdList.Remove(playerId);
|
||||
}
|
||||
|
||||
if (GameStates.IsInTask && player != null && player.IsAlive())
|
||||
{
|
||||
Druid.OnCheckPlayerPosition(player);
|
||||
Sentinel.OnCheckPlayerPosition(player);
|
||||
Tornado.OnCheckPlayerPosition(player);
|
||||
BallLightning.OnCheckPlayerPosition(player);
|
||||
Sprayer.OnCheckPlayerPosition(player);
|
||||
}
|
||||
|
||||
if (!lowLoad && Main.PlayerStates.TryGetValue(playerId, out var playerState) && GameStates.IsInTask)
|
||||
{
|
||||
if (playerState.SubRoles.Contains(CustomRoles.Damocles))
|
||||
@@ -2538,10 +2535,6 @@ class FixedUpdatePatch
|
||||
Pelican.OnFixedUpdate();
|
||||
break;
|
||||
|
||||
case CustomRoles.BallLightning:
|
||||
BallLightning.OnFixedUpdate();
|
||||
break;
|
||||
|
||||
case CustomRoles.Sapper:
|
||||
Sapper.OnFixedUpdate(player);
|
||||
break;
|
||||
@@ -2942,6 +2935,7 @@ class FixedUpdatePatch
|
||||
if (PlagueDoctor.IsEnable) Suffix.Append(PlagueDoctor.GetLowerTextOthers(seer, target));
|
||||
if (Stealth.IsEnable) Suffix.Append(Stealth.GetSuffix(seer, target));
|
||||
if (Tracker.IsEnable) Suffix.Append(Tracker.GetTrackerArrow(seer, target));
|
||||
if (Bubble.IsEnable) Suffix.Append(Bubble.GetEncasedPlayerSuffix(seer, target));
|
||||
|
||||
if (Deathpact.IsEnable)
|
||||
{
|
||||
@@ -3040,6 +3034,10 @@ class FixedUpdatePatch
|
||||
target.cosmetics.nameText.text = changeTo;
|
||||
|
||||
float offset = 0.2f;
|
||||
if (NameNotifyManager.Notice.TryGetValue(seer.PlayerId, out var notify) && notify.TEXT.Contains('\n'))
|
||||
{
|
||||
offset += 0.1f;
|
||||
}
|
||||
if (Suffix.ToString() != string.Empty)
|
||||
{
|
||||
// If the name is on two lines, the job title text needs to be moved up.
|
||||
@@ -3047,6 +3045,10 @@ class FixedUpdatePatch
|
||||
offset += 0.15f;
|
||||
target.cosmetics.nameText.text += "\r\n" + Suffix.ToString();
|
||||
}
|
||||
if (!seer.IsAlive())
|
||||
{
|
||||
offset += 0.1f;
|
||||
}
|
||||
if (isProgressTextLong)
|
||||
{
|
||||
offset += 0.3f;
|
||||
@@ -3073,14 +3075,12 @@ class FixedUpdatePatch
|
||||
{
|
||||
foreach (PlayerControl loversPlayer in Main.LoversPlayers.ToArray())
|
||||
{
|
||||
if (!loversPlayer.Data.IsDead && loversPlayer.PlayerId != deathId)
|
||||
continue;
|
||||
if (!loversPlayer.Data.IsDead && loversPlayer.PlayerId != deathId) continue;
|
||||
Main.isLoversDead = true;
|
||||
for (int i1 = 0; i1 < Main.LoversPlayers.Count; i1++)
|
||||
{
|
||||
PlayerControl partnerPlayer = Main.LoversPlayers[i1];
|
||||
if (loversPlayer.PlayerId == partnerPlayer.PlayerId)
|
||||
continue;
|
||||
if (loversPlayer.PlayerId == partnerPlayer.PlayerId) continue;
|
||||
if (partnerPlayer.PlayerId != deathId && !partnerPlayer.Data.IsDead)
|
||||
{
|
||||
if (partnerPlayer.Is(CustomRoles.Lovers))
|
||||
@@ -3123,6 +3123,19 @@ class SetColorPatch
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.TryMoveToVent))]
|
||||
class TryMoveToVentPatch
|
||||
{
|
||||
public static Vent HostVentTarget;
|
||||
public static void Postfix(Vent __instance, [HarmonyArgument(0)] Vent otherVent, bool __result)
|
||||
{
|
||||
if (__result && AmongUsClient.Instance.AmHost && PlayerControl.LocalPlayer.PlayerId == 0 && PlayerControl.LocalPlayer.inVent && (HostVentTarget.Equals(__instance) || HostVentTarget == __instance))
|
||||
{
|
||||
Logger.Info($"(Move) {__instance.name} => {otherVent.name}", "HostVentTarget");
|
||||
HostVentTarget = otherVent;
|
||||
}
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.ExitVent))]
|
||||
class ExitVentPatch
|
||||
{
|
||||
@@ -3130,6 +3143,12 @@ class ExitVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "ExitVent");
|
||||
|
||||
if (pc.PlayerId == 0)
|
||||
{
|
||||
Logger.Info("(Exit) " + __instance.name, "HostVentTarget");
|
||||
TryMoveToVentPatch.HostVentTarget = __instance;
|
||||
}
|
||||
|
||||
Drainer.OnAnyoneExitVent(pc, __instance.Id);
|
||||
}
|
||||
}
|
||||
@@ -3140,6 +3159,12 @@ class EnterVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "EnterVent");
|
||||
|
||||
if (pc.PlayerId == 0)
|
||||
{
|
||||
Logger.Info("(Enter) " + __instance.name, "HostVentTarget");
|
||||
TryMoveToVentPatch.HostVentTarget = __instance;
|
||||
}
|
||||
|
||||
Drainer.OnAnyoneEnterVent(pc, __instance);
|
||||
Analyzer.OnAnyoneEnterVent(pc);
|
||||
|
||||
@@ -3207,7 +3232,7 @@ class EnterVentPatch
|
||||
|
||||
if (pc.Is(CustomRoles.Damocles))
|
||||
{
|
||||
Damocles.OnEnterVent(__instance.Id);
|
||||
Damocles.OnEnterVent(pc.PlayerId, __instance.Id);
|
||||
}
|
||||
|
||||
switch (pc.GetCustomRole())
|
||||
|
||||
+38
-27
@@ -74,9 +74,11 @@ class RepairSystemPatch
|
||||
{
|
||||
case CustomRoles.SabotageMaster:
|
||||
SabotageMaster.RepairSystem(__instance, systemType, amount);
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
case CustomRoles.Alchemist when Alchemist.FixNextSabo:
|
||||
Alchemist.RepairSystem(systemType, amount);
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -118,6 +120,9 @@ class RepairSystemPatch
|
||||
case CustomRoles.Enderman:
|
||||
Enderman.MarkPosition();
|
||||
return false;
|
||||
case CustomRoles.Hookshot:
|
||||
Hookshot.ExecuteAction();
|
||||
return false;
|
||||
case CustomRoles.Mycologist when Mycologist.SpreadAction.GetValue() == 1 || (Mycologist.SpreadAction.GetValue() == 2 && !Options.UsePets.GetBool()):
|
||||
Mycologist.SpreadSpores();
|
||||
return false;
|
||||
@@ -160,37 +165,43 @@ class RepairSystemPatch
|
||||
{
|
||||
Camouflage.CheckCamouflage();
|
||||
|
||||
if (systemType == SystemTypes.Electrical && 0 <= amount && amount <= 4)
|
||||
switch (systemType)
|
||||
{
|
||||
var SwitchSystem = ShipStatus.Instance?.Systems?[SystemTypes.Electrical]?.Cast<SwitchSystem>();
|
||||
if (SwitchSystem != null && SwitchSystem.IsActive)
|
||||
{
|
||||
switch (player.GetCustomRole())
|
||||
case SystemTypes.Electrical when 0 <= amount && amount <= 4:
|
||||
{
|
||||
case CustomRoles.SabotageMaster:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SabotageMaster.SwitchSystemRepair(SwitchSystem, amount);
|
||||
break;
|
||||
case CustomRoles.Alchemist when Alchemist.FixNextSabo:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SwitchSystem.ActualSwitches = 0;
|
||||
SwitchSystem.ExpectedSwitches = 0;
|
||||
Alchemist.FixNextSabo = false;
|
||||
break;
|
||||
var SwitchSystem = ShipStatus.Instance?.Systems?[SystemTypes.Electrical]?.Cast<SwitchSystem>();
|
||||
if (SwitchSystem != null && SwitchSystem.IsActive)
|
||||
{
|
||||
switch (player.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.SabotageMaster:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SabotageMaster.SwitchSystemRepair(SwitchSystem, amount);
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
case CustomRoles.Alchemist when Alchemist.FixNextSabo:
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} instant-fix-lights", "SwitchSystem");
|
||||
SwitchSystem.ActualSwitches = 0;
|
||||
SwitchSystem.ExpectedSwitches = 0;
|
||||
Alchemist.FixNextSabo = false;
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
break;
|
||||
}
|
||||
if (player.Is(CustomRoles.Damocles) && Damocles.countRepairSabotage) Damocles.OnRepairSabotage(player.PlayerId);
|
||||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (systemType is
|
||||
SystemTypes.Reactor or
|
||||
SystemTypes.LifeSupp or
|
||||
SystemTypes.Comms or
|
||||
SystemTypes.Laboratory or
|
||||
SystemTypes.HeliSabotage or
|
||||
SystemTypes.Electrical)
|
||||
{
|
||||
if (player.Is(CustomRoles.Damocles) && Damocles.countRepairSabotage) Damocles.OnRepairSabotage();
|
||||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||||
case SystemTypes.Reactor:
|
||||
case SystemTypes.LifeSupp:
|
||||
case SystemTypes.Comms:
|
||||
case SystemTypes.Laboratory:
|
||||
case SystemTypes.HeliSabotage:
|
||||
case SystemTypes.Electrical:
|
||||
if (player.Is(CustomRoles.Damocles) && Damocles.countRepairSabotage) Damocles.OnRepairSabotage(player.PlayerId);
|
||||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static void CheckAndOpenDoorsRange(ShipStatus __instance, int amount, int min, int max)
|
||||
|
||||
+533
-522
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -103,10 +103,10 @@ namespace TOHE.Roles.AddOns.Crewmate
|
||||
|
||||
public static void Update(PlayerControl pc)
|
||||
{
|
||||
if (!LastUpdates.TryGetValue(pc.PlayerId, out var x) || x >= GetTimeStamp() || !Timers.ContainsKey(pc.PlayerId) || !IsEnable || !GameStates.IsInTask || !pc.IsAlive() || !pc.Is(CustomRoles.Stressed)) return;
|
||||
if (!LastUpdates.TryGetValue(pc.PlayerId, out var x) || x >= GetTimeStamp() || !Timers.ContainsKey(pc.PlayerId) || !IsEnable || !GameStates.IsInTask || !pc.Is(CustomRoles.Stressed)) return;
|
||||
LastUpdates[pc.PlayerId] = GetTimeStamp();
|
||||
|
||||
if (pc.GetPlayerTaskState().IsTaskFinished)
|
||||
if (pc.GetPlayerTaskState().IsTaskFinished || !pc.IsAlive())
|
||||
{
|
||||
Main.PlayerStates[pc.PlayerId].RemoveSubRole(CustomRoles.Stressed);
|
||||
Timers.Remove(pc.PlayerId);
|
||||
@@ -121,7 +121,7 @@ namespace TOHE.Roles.AddOns.Crewmate
|
||||
pc.Suicide();
|
||||
}
|
||||
|
||||
if (pc.IsModClient() && pc.PlayerId != 0) SendRPC(pc.PlayerId, Timers[pc.PlayerId], LastUpdates[pc.PlayerId]);
|
||||
if (pc.IsNonHostModClient()) SendRPC(pc.PlayerId, Timers[pc.PlayerId], LastUpdates[pc.PlayerId]);
|
||||
if (!pc.IsModClient()) NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,6 @@ namespace TOHE.Roles.AddOns.Crewmate
|
||||
public static void AfterMeetingTasks()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
AdjustTime(TimeAfterMeeting + 9);
|
||||
countRepairSabotage = true;
|
||||
}
|
||||
|
||||
@@ -188,6 +187,12 @@ namespace TOHE.Roles.AddOns.Crewmate
|
||||
Timers[pc.PlayerId] += TimeAfterReport;
|
||||
}
|
||||
|
||||
public static void OnMeetingStart()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
AdjustTime(TimeAfterMeeting + 9);
|
||||
}
|
||||
|
||||
public static string GetProgressText(byte playerId) => Timers.TryGetValue(playerId, out var x) ? string.Format(GetString("DamoclesTimeLeft"), x) : string.Empty;
|
||||
|
||||
private static void AdjustTime(int change)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Hazel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
using static TOHE.Utils;
|
||||
@@ -19,16 +20,16 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
private static int TimeAfterMeeting;
|
||||
private static int StartingTime;
|
||||
|
||||
public static int Timer;
|
||||
public static Dictionary<byte, int> Timer;
|
||||
|
||||
public static long lastUpdate;
|
||||
public static List<int> PreviouslyEnteredVents;
|
||||
public static Dictionary<byte, long> lastUpdate;
|
||||
public static Dictionary<byte, List<int>> PreviouslyEnteredVents;
|
||||
|
||||
public static bool countRepairSabotage;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupAdtRoleOptions(Id, CustomRoles.Damocles, canSetNum: false);
|
||||
SetupAdtRoleOptions(Id, CustomRoles.Damocles, canSetNum: true);
|
||||
DamoclesExtraTimeAfterKill = IntegerOptionItem.Create(Id + 10, "DamoclesExtraTimeAfterKill", new(0, 60, 1), 30, TabGroup.Addons, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Damocles])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
@@ -46,109 +47,130 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
TimeAfterMeeting = DamoclesExtraTimeAfterMeeting.GetInt();
|
||||
StartingTime = DamoclesStartingTime.GetInt();
|
||||
|
||||
Timer = StartingTime;
|
||||
lastUpdate = GetTimeStamp() + 10;
|
||||
Timer = [];
|
||||
lastUpdate = [];
|
||||
PreviouslyEnteredVents = [];
|
||||
countRepairSabotage = true;
|
||||
}
|
||||
|
||||
public static void Update(PlayerControl pc)
|
||||
{
|
||||
if (lastUpdate >= GetTimeStamp() || !GameStates.IsInTask || pc == null) return;
|
||||
byte id = pc.PlayerId;
|
||||
if (lastUpdate.TryGetValue(id, out var ts) && ts >= GetTimeStamp() || !GameStates.IsInTask || pc == null) return;
|
||||
if (!pc.IsAlive())
|
||||
{
|
||||
Main.PlayerStates[pc.PlayerId].RemoveSubRole(CustomRoles.Damocles);
|
||||
Main.PlayerStates[id].RemoveSubRole(CustomRoles.Damocles);
|
||||
return;
|
||||
}
|
||||
lastUpdate = GetTimeStamp();
|
||||
lastUpdate[id] = GetTimeStamp();
|
||||
if (!Timer.ContainsKey(id)) Timer[id] = StartingTime + 8;
|
||||
|
||||
Timer--;
|
||||
Timer[id]--;
|
||||
|
||||
if (Timer < 0)
|
||||
if (Timer[id] < 0)
|
||||
{
|
||||
Timer = 0;
|
||||
Timer[id] = 0;
|
||||
pc.Suicide();
|
||||
}
|
||||
|
||||
if (pc.IsNonHostModClient()) SendRPC();
|
||||
NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
if (pc.IsNonHostModClient()) SendRPC(id);
|
||||
if (!pc.IsModClient()) NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
public static void SendRPC()
|
||||
public static void SendRPC(byte playerId)
|
||||
{
|
||||
if (!DoRPC) return;
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncDamoclesTimer, SendOption.Reliable, -1);
|
||||
writer.Write(Timer);
|
||||
writer.Write(lastUpdate.ToString());
|
||||
writer.Write(PreviouslyEnteredVents.Count);
|
||||
if (PreviouslyEnteredVents.Count > 0) foreach (var vent in PreviouslyEnteredVents.ToArray()) writer.Write(vent);
|
||||
writer.Write(playerId);
|
||||
writer.Write(Timer[playerId]);
|
||||
writer.Write(lastUpdate[playerId].ToString());
|
||||
writer.Write(PreviouslyEnteredVents[playerId].Count);
|
||||
if (PreviouslyEnteredVents[playerId].Count > 0) foreach (var vent in PreviouslyEnteredVents[playerId].ToArray()) writer.Write(vent);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
|
||||
public static void ReceiveRPC(MessageReader reader)
|
||||
{
|
||||
Timer = reader.ReadInt32();
|
||||
lastUpdate = long.Parse(reader.ReadString());
|
||||
byte playerId = reader.ReadByte();
|
||||
Timer[playerId] = reader.ReadInt32();
|
||||
lastUpdate[playerId] = long.Parse(reader.ReadString());
|
||||
var elements = reader.ReadInt32();
|
||||
if (elements > 0) for (int i = 0; i < elements; i++) PreviouslyEnteredVents.Add(reader.ReadInt32());
|
||||
if (elements > 0) for (int i = 0; i < elements; i++) PreviouslyEnteredVents[playerId].Add(reader.ReadInt32());
|
||||
}
|
||||
|
||||
public static void OnMurder()
|
||||
public static void OnMurder(byte id)
|
||||
{
|
||||
Timer += TimeAfterKill;
|
||||
Timer[id] += TimeAfterKill;
|
||||
}
|
||||
|
||||
public static void OnOtherImpostorMurder()
|
||||
{
|
||||
Timer += 10;
|
||||
AdjustTime(10);
|
||||
}
|
||||
|
||||
public static void OnEnterVent(int ventId)
|
||||
public static void OnEnterVent(byte id, int ventId)
|
||||
{
|
||||
if (PreviouslyEnteredVents.Contains(ventId)) return;
|
||||
if (!PreviouslyEnteredVents.ContainsKey(id)) PreviouslyEnteredVents[id] = [];
|
||||
if (PreviouslyEnteredVents[id].Contains(ventId)) return;
|
||||
|
||||
PreviouslyEnteredVents.Add(ventId);
|
||||
Timer += 10;
|
||||
PreviouslyEnteredVents[id].Add(ventId);
|
||||
Timer[id] += 10;
|
||||
}
|
||||
|
||||
public static void AfterMeetingTasks()
|
||||
{
|
||||
PreviouslyEnteredVents.Clear();
|
||||
|
||||
Timer += TimeAfterMeeting;
|
||||
AdjustTime(TimeAfterMeeting);
|
||||
countRepairSabotage = true;
|
||||
}
|
||||
|
||||
public static void OnMeetingStart()
|
||||
{
|
||||
Timer += 9;
|
||||
AdjustTime(9);
|
||||
}
|
||||
|
||||
public static void OnCrewmateEjected()
|
||||
{
|
||||
Timer = (int)Math.Round(Timer * 1.3);
|
||||
AdjustTimeByPercent(1.3);
|
||||
}
|
||||
|
||||
public static void OnRepairSabotage()
|
||||
public static void OnRepairSabotage(byte id)
|
||||
{
|
||||
Timer -= 15;
|
||||
Timer[id] -= 15;
|
||||
}
|
||||
|
||||
public static void OnImpostorDeath()
|
||||
{
|
||||
Timer -= 20;
|
||||
AdjustTime(-20);
|
||||
}
|
||||
|
||||
public static void OnReport()
|
||||
public static void OnReport(byte id)
|
||||
{
|
||||
Timer = (int)Math.Round(Timer * 0.9);
|
||||
Timer[id] = (int)Math.Round(Timer[id] * 0.9);
|
||||
}
|
||||
|
||||
public static void OnImpostorEjected()
|
||||
{
|
||||
Timer = (int)Math.Round(Timer * 0.8);
|
||||
AdjustTimeByPercent(0.8);
|
||||
}
|
||||
|
||||
public static string GetProgressText() => string.Format(GetString("DamoclesTimeLeft"), Timer);
|
||||
private static void AdjustTime(int change)
|
||||
{
|
||||
foreach (var item in Timer.Keys.ToArray())
|
||||
{
|
||||
Timer[item] += change;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AdjustTimeByPercent(double percent)
|
||||
{
|
||||
foreach (var item in Timer.Keys.ToArray())
|
||||
{
|
||||
Timer[item] = (int)Math.Round(Timer[item] * percent);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetProgressText(byte id) => string.Format(GetString("DamoclesTimeLeft"), Timer.TryGetValue(id, out var time) ? time : StartingTime);
|
||||
}
|
||||
}
|
||||
+30
-37
@@ -169,52 +169,45 @@ namespace TOHE.Roles.Crewmate
|
||||
SendRPCSyncAbilityUse(pc.PlayerId);
|
||||
}
|
||||
|
||||
public static void OnCheckPlayerPosition(PlayerControl pc)
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || Triggers.Count <= 0 || playerIdList.Contains(pc.PlayerId)) return;
|
||||
|
||||
foreach (var triggers in Triggers.ToArray()) // Check for all Druids' traps - Most likely just 1 loop
|
||||
{
|
||||
foreach (var trigger in triggers.Value.Where(trigger => Vector2.Distance(trigger.Key, pc.Pos()) <= 1.5f)) // Check for all traps of the current Druid - Most likely 0-3 loops
|
||||
{
|
||||
GetPlayerById(triggers.Key).Notify(string.Format(GetString("DruidTriggerTriggered"), GetFormattedRoomName(trigger.Value), GetFormattedVectorText(trigger.Key)));
|
||||
Triggers[triggers.Key].Remove(trigger.Key);
|
||||
SendRPCRemoveTrigger(triggers.Key, trigger.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnFixedUpdate()
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || Triggers.Count == 0 && TriggerDelays.Count == 0) return;
|
||||
if (!IsEnable || !GameStates.IsInTask || TriggerDelays.Count <= 0) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
|
||||
if (TriggerDelays.Count > 0)
|
||||
foreach (var x in TriggerDelays.ToArray())
|
||||
{
|
||||
foreach (var x in TriggerDelays.ToArray())
|
||||
var id = x.Key;
|
||||
var pc = GetPlayerById(id);
|
||||
if (pc == null) continue;
|
||||
|
||||
if (x.Value + TriggerPlaceDelay.GetInt() < now)
|
||||
{
|
||||
var id = x.Key;
|
||||
var pc = GetPlayerById(id);
|
||||
if (pc == null) continue;
|
||||
|
||||
if (x.Value + TriggerPlaceDelay.GetInt() < now)
|
||||
{
|
||||
TriggerDelays.Remove(id);
|
||||
var (LOCATION, ROOM_NAME) = pc.GetPositionInfo();
|
||||
if (!Triggers.ContainsKey(id)) Triggers.Add(id, []);
|
||||
Triggers[id].TryAdd(LOCATION, ROOM_NAME);
|
||||
SendRPCAddTrigger(id, LOCATION, ROOM_NAME);
|
||||
continue;
|
||||
}
|
||||
|
||||
var timeLeft = TriggerPlaceDelay.GetInt() - (now - x.Value);
|
||||
if (lastUpdate < now) pc.Notify(string.Format(GetString("DruidTimeLeft"), timeLeft, 2f));
|
||||
TriggerDelays.Remove(id);
|
||||
var (LOCATION, ROOM_NAME) = pc.GetPositionInfo();
|
||||
if (!Triggers.ContainsKey(id)) Triggers.Add(id, []);
|
||||
Triggers[id].TryAdd(LOCATION, ROOM_NAME);
|
||||
SendRPCAddTrigger(id, LOCATION, ROOM_NAME);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (Triggers.Count > 0)
|
||||
{
|
||||
foreach (var pc in Main.AllAlivePlayerControls.Where(pc => !playerIdList.Contains(pc.PlayerId)).ToArray()) // Check for all alive players except Druids - Worst case scenario it's 14 loops
|
||||
{
|
||||
foreach (var triggers in Triggers.ToArray()) // Check for all Druids' traps - Most likely just 1 loop
|
||||
{
|
||||
foreach (var trigger in triggers.Value.ToArray()) // Check for all traps of the current Druid - Most likely 0-3 loops
|
||||
{
|
||||
if (Vector2.Distance(trigger.Key, pc.Pos()) <= 1.5f)
|
||||
{
|
||||
GetPlayerById(triggers.Key).Notify(string.Format(GetString("DruidTriggerTriggered"), GetFormattedRoomName(trigger.Value), GetFormattedVectorText(trigger.Key)));
|
||||
Triggers[triggers.Key].Remove(trigger.Key);
|
||||
SendRPCRemoveTrigger(triggers.Key, trigger.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var timeLeft = TriggerPlaceDelay.GetInt() - (now - x.Value);
|
||||
if (lastUpdate < now) pc.Notify(string.Format(GetString("DruidTimeLeft"), timeLeft, 2f));
|
||||
}
|
||||
|
||||
lastUpdate = now;
|
||||
|
||||
@@ -29,7 +29,7 @@ public static class Judge
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
Options.SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Judge);
|
||||
TrialLimitPerMeeting = IntegerOptionItem.Create(Id + 10, "TrialLimitPerMeeting", new(1, 10, 1), 1, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge])
|
||||
TrialLimitPerMeeting = IntegerOptionItem.Create(Id + 10, "TrialLimitPerMeeting", new(1, 15, 1), 1, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CanTrialMadmate = BooleanOptionItem.Create(Id + 12, "JudgeCanTrialMadmate", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]);
|
||||
CanTrialCharmed = BooleanOptionItem.Create(Id + 16, "JudgeCanTrialCharmed", true, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Judge]);
|
||||
|
||||
@@ -24,6 +24,7 @@ public static class Medic
|
||||
public static OptionItem GuesserIgnoreShield;
|
||||
private static OptionItem AmountOfShields;
|
||||
public static OptionItem UsePet;
|
||||
public static OptionItem CD;
|
||||
|
||||
public static readonly string[] MedicWhoCanSeeProtectName =
|
||||
[
|
||||
@@ -67,6 +68,9 @@ public static class Medic
|
||||
AmountOfShields = IntegerOptionItem.Create(Id + 34, "MedicAmountOfShields", new(1, 14, 1), 1, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic]);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 36, CustomRoles.Medic);
|
||||
CD = FloatOptionItem.Create(Id + 38, "AbilityCooldown", new(0f, 180f, 2.5f), 7.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Medic])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -124,7 +128,7 @@ public static class Medic
|
||||
public static bool CanUseKillButton(byte playerId)
|
||||
=> !Main.PlayerStates[playerId].IsDead
|
||||
&& (ProtectLimit.TryGetValue(playerId, out var x) ? x : 1) >= 1;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = CanUseKillButton(id) ? 5f : 300f;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = CanUseKillButton(id) ? CD.GetFloat() : 300f;
|
||||
public static string GetSkillLimit(byte playerId) => Utils.ColorString(CanUseKillButton(playerId) ? Utils.GetRoleColor(CustomRoles.Medic).ShadeColor(0.25f) : Color.gray, ProtectLimit.TryGetValue(playerId, out var protectLimit) ? $"({protectLimit})" : "Invalid");
|
||||
public static bool InProtect(byte id) => ProtectList.Contains(id) && Main.PlayerStates.TryGetValue(id, out var ps) && !ps.IsDead;
|
||||
public static void OnCheckMurderFormedicaler(PlayerControl killer, PlayerControl target)
|
||||
|
||||
+28
-12
@@ -49,22 +49,30 @@ namespace TOHE.Roles.Crewmate
|
||||
FinishPatrolling();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnCheckPlayerPosition(PlayerControl pc)
|
||||
{
|
||||
if (!IsPatrolling) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
if (LastUpdate >= now) return;
|
||||
LastUpdate = now;
|
||||
|
||||
var killers = NearbyKillers;
|
||||
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
bool nowInRange = killers.Any(x => x.PlayerId == pc.PlayerId);
|
||||
bool wasInRange = LastNearbyKillers.Contains(pc.PlayerId);
|
||||
bool nowInRange = killers.Any(x => x.PlayerId == pc.PlayerId);
|
||||
bool wasInRange = LastNearbyKillers.Contains(pc.PlayerId);
|
||||
|
||||
if (wasInRange && !nowInRange)
|
||||
{
|
||||
pc.Notify(GetString("KillerEscapedFromSentinel"));
|
||||
}
|
||||
if (nowInRange)
|
||||
{
|
||||
pc.Notify(string.Format(GetString("KillerNotifyPatrol"), PatrolDuration - (now - PatrolStartTimeStamp)));
|
||||
}
|
||||
if (wasInRange && !nowInRange)
|
||||
{
|
||||
pc.Notify(GetString("KillerEscapedFromSentinel"));
|
||||
LastNearbyKillers.Remove(pc.PlayerId);
|
||||
}
|
||||
if (nowInRange)
|
||||
{
|
||||
pc.Notify(string.Format(GetString("KillerNotifyPatrol"), PatrolDuration - (GetTimeStamp() - PatrolStartTimeStamp)));
|
||||
LastNearbyKillers.Add(pc.PlayerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,5 +179,13 @@ namespace TOHE.Roles.Crewmate
|
||||
state.Update();
|
||||
}
|
||||
}
|
||||
public static void OnCheckPlayerPosition(PlayerControl pc)
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
foreach (PatrollingState state in PatrolStates)
|
||||
{
|
||||
state.OnCheckPlayerPosition(pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,7 @@ namespace TOHE.Roles.Crewmate
|
||||
Tornados.Add(info, now);
|
||||
SendRPCAddTornado(info.LOCATION, info.ROOM_NAME, now);
|
||||
}
|
||||
public static void OnFixedUpdate(PlayerControl tornadoPc)
|
||||
public static void OnCheckPlayerPosition(PlayerControl pc)
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || Tornados.Count == 0) return;
|
||||
|
||||
@@ -114,10 +114,8 @@ namespace TOHE.Roles.Crewmate
|
||||
var tornadoRange = TornadoRange.GetFloat();
|
||||
var tornadoDuration = TornadoDuration.GetInt();
|
||||
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
foreach (var tornadoPc in playerIdList.Select(x => GetPlayerById(x)).Where(x => x.PlayerId != pc.PlayerId).ToArray())
|
||||
{
|
||||
if (playerIdList.Contains(pc.PlayerId)) continue;
|
||||
|
||||
foreach (var tornado in Tornados)
|
||||
{
|
||||
if (Vector2.Distance(tornado.Key.LOCATION, pc.Pos()) <= tornadoRange)
|
||||
@@ -139,11 +137,11 @@ namespace TOHE.Roles.Crewmate
|
||||
SendRPCRemoveTornado(tornado.Key.LOCATION, tornado.Key.ROOM_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tornadoPc == null || LastNotify >= now || !tornadoPc.Is(CustomRoles.Tornado) || tornadoPc.HasAbilityCD()) return;
|
||||
NotifyRoles(SpecifySeer: tornadoPc, SpecifyTarget: tornadoPc);
|
||||
LastNotify = now;
|
||||
if (tornadoPc == null || LastNotify >= now || !tornadoPc.Is(CustomRoles.Tornado) || tornadoPc.HasAbilityCD()) return;
|
||||
NotifyRoles(SpecifySeer: tornadoPc, SpecifyTarget: tornadoPc);
|
||||
LastNotify = now;
|
||||
}
|
||||
}
|
||||
public static string GetSuffixText(byte playerId, bool isHUD = false) => string.Join(isHUD ? "\n" : ", ", Tornados.Select(x => $"Tornado {GetFormattedRoomName(x.Key.ROOM_NAME)} {GetFormattedVectorText(x.Key.LOCATION)} ({(int)(TornadoDuration.GetInt() - (GetTimeStamp() - x.Value) + 1)}s)"));
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public static class BallLightning
|
||||
RealKiller.TryAdd(killer.PlayerId, target);
|
||||
StartConvertCountDown(target, killer);
|
||||
}
|
||||
public static void OnFixedUpdate()
|
||||
public static void OnCheckPlayerPosition(PlayerControl pc)
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask) return;
|
||||
List<byte> deList = [];
|
||||
@@ -115,7 +115,7 @@ public static class BallLightning
|
||||
deList.Add(gs.PlayerId);
|
||||
continue;
|
||||
}
|
||||
foreach (var pc in Main.AllAlivePlayerControls.Where(x => x.PlayerId != gs.PlayerId && x.IsAlive() && !x.Is(CustomRoles.BallLightning) && !IsGhost(x) && !Pelican.IsEaten(x.PlayerId)).ToArray())
|
||||
if (pc.PlayerId != gs.PlayerId && pc.IsAlive() && !pc.Is(CustomRoles.BallLightning) && !IsGhost(pc) && !Pelican.IsEaten(pc.PlayerId))
|
||||
{
|
||||
var pos = gs.transform.position;
|
||||
var dis = Vector2.Distance(pos, pc.Pos());
|
||||
|
||||
@@ -29,7 +29,7 @@ public static class Councillor
|
||||
Options.SetupRoleOptions(Id, TabGroup.ImpostorRoles, CustomRoles.Councillor);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 15, "KillCooldown", new(0f, 180f, 2.5f), 25f, TabGroup.ImpostorRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Councillor])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
MurderLimitPerMeeting = IntegerOptionItem.Create(Id + 10, "MurderLimitPerMeeting", new(0, 5, 1), 0, TabGroup.ImpostorRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Councillor])
|
||||
MurderLimitPerMeeting = IntegerOptionItem.Create(Id + 10, "MurderLimitPerMeeting", new(0, 15, 1), 0, TabGroup.ImpostorRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Councillor])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
// MurderLimitPerGame = IntegerOptionItem.Create(Id + 13, "MurderLimitPerGame", new(1, 99, 1), 2, TabGroup.ImpostorRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Councillor])
|
||||
// .SetValueFormat(OptionFormat.Times);
|
||||
|
||||
@@ -97,13 +97,13 @@ namespace TOHE.Roles.Impostor
|
||||
{
|
||||
DuelPair.Remove(pair.Key);
|
||||
SendRPC(pair.Key, pair.Value, true);
|
||||
_ = new LateTask(duellist.TPtoRndVent, 0.5f, log: false);
|
||||
_ = new LateTask(() => { duellist.TPtoRndVent(); }, 0.5f, log: false);
|
||||
}
|
||||
else if (TAlive && !DAlive)
|
||||
{
|
||||
DuelPair.Remove(pair.Key);
|
||||
SendRPC(pair.Key, pair.Value, true);
|
||||
_ = new LateTask(target.TPtoRndVent, 0.5f, log: false);
|
||||
_ = new LateTask(() => { target.TPtoRndVent(); }, 0.5f, log: false);
|
||||
}
|
||||
else continue;
|
||||
}
|
||||
|
||||
+23
-20
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using MS.Internal.Xml.XPath;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Crewmate;
|
||||
@@ -33,8 +34,8 @@ namespace TOHE.Roles.Impostor
|
||||
public static OptionItem IgnorePestilence;
|
||||
public static OptionItem PositiveEffectChance;
|
||||
|
||||
public static byte EffectID = byte.MaxValue;
|
||||
public static bool isPositiveEffect;
|
||||
public static Dictionary<byte, byte> EffectID = [];
|
||||
public static Dictionary<byte, bool> isPositiveEffect = [];
|
||||
|
||||
public static Dictionary<byte, long> waitingDelayedKills = [];
|
||||
public static Dictionary<byte, long> isShielded = [];
|
||||
@@ -43,7 +44,7 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.ImpostorRoles, CustomRoles.Gambler, 1);
|
||||
SetupRoleOptions(Id, TabGroup.ImpostorRoles, CustomRoles.Gambler);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 60f, 2.5f), 25f, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
KillDelay = IntegerOptionItem.Create(Id + 11, "GamblerKillDelay", new(0, 10, 1), 3, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
@@ -60,13 +61,13 @@ namespace TOHE.Roles.Impostor
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
SpeedDur = IntegerOptionItem.Create(Id + 17, "GamblerSpeedupDur", new(1, 20, 1), 5, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
BSRDelay = IntegerOptionItem.Create(Id + 18, "GamblerKillDelay", new(0, 10, 1), 2, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
BSRDelay = IntegerOptionItem.Create(Id + 18, "GamblerBSRDelay", new(0, 10, 1), 2, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
HighKCD = FloatOptionItem.Create(Id + 19, "GamblerHighKCD", new(10f, 60f, 2.5f), 30f, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
LowKCD = FloatOptionItem.Create(Id + 20, "GamblerLowKCD", new(10f, 60f, 2.5f), 17.5f, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
TPDelay = IntegerOptionItem.Create(Id + 21, "GamblerKillDelay", new(0, 10, 1), 2, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
TPDelay = IntegerOptionItem.Create(Id + 21, "GamblerTPDelay", new(0, 10, 1), 2, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
WhatToIgnore = BooleanOptionItem.Create(Id + 22, "GamblerWhatToIgnore", true, TabGroup.ImpostorRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Gambler]);
|
||||
IgnoreMedicShield = BooleanOptionItem.Create(Id + 23, "GamblerIgnoreMedicShield", true, TabGroup.ImpostorRoles, false).SetParent(WhatToIgnore);
|
||||
@@ -74,17 +75,18 @@ namespace TOHE.Roles.Impostor
|
||||
IgnoreVeteranAlert = BooleanOptionItem.Create(Id + 25, "GamblerIgnoreVeteranAlert", false, TabGroup.ImpostorRoles, false).SetParent(WhatToIgnore);
|
||||
IgnorePestilence = BooleanOptionItem.Create(Id + 26, "GamblerIgnorePestilence", false, TabGroup.ImpostorRoles, false).SetParent(WhatToIgnore);
|
||||
PositiveEffectChance = IntegerOptionItem.Create(Id + 27, "GamblerPositiveEffectChance", new(0, 100, 5), 70, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Percent);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Gambler])
|
||||
.SetValueFormat(OptionFormat.Percent);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
playerIdList = [];
|
||||
EffectID = byte.MaxValue;
|
||||
EffectID = [];
|
||||
waitingDelayedKills = [];
|
||||
isSpeedChange = [];
|
||||
isVisionChange = [];
|
||||
isPositiveEffect = [];
|
||||
}
|
||||
|
||||
public static void Add(byte playerId)
|
||||
@@ -99,17 +101,17 @@ namespace TOHE.Roles.Impostor
|
||||
if (killer == null) return false;
|
||||
if (target == null) return false;
|
||||
|
||||
if (EffectID != byte.MaxValue)
|
||||
if (EffectID.TryGetValue(killer.PlayerId, out var id) && id != byte.MaxValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var rd = IRandom.Instance;
|
||||
isPositiveEffect = rd.Next(1, 101) <= PositiveEffectChance.GetInt();
|
||||
if (isPositiveEffect)
|
||||
isPositiveEffect[killer.PlayerId] = rd.Next(1, 101) <= PositiveEffectChance.GetInt();
|
||||
if (isPositiveEffect[killer.PlayerId])
|
||||
{
|
||||
EffectID = (byte)rd.Next(1, 8);
|
||||
switch (EffectID)
|
||||
EffectID[killer.PlayerId] = (byte)rd.Next(1, 8);
|
||||
switch (EffectID[killer.PlayerId])
|
||||
{
|
||||
case 1: // Delayed kill
|
||||
killer.Notify(string.Format(GetString("GamblerGet.DelayedKill"), KillDelay.GetInt()));
|
||||
@@ -153,7 +155,7 @@ namespace TOHE.Roles.Impostor
|
||||
}
|
||||
else
|
||||
{
|
||||
killer.Kill(target);
|
||||
killer.RpcCheckAndMurder(target);
|
||||
return false;
|
||||
}
|
||||
case 6: // Low KCD
|
||||
@@ -176,8 +178,8 @@ namespace TOHE.Roles.Impostor
|
||||
}
|
||||
else
|
||||
{
|
||||
EffectID = (byte)rd.Next(1, 5);
|
||||
switch (EffectID)
|
||||
EffectID[killer.PlayerId] = (byte)rd.Next(1, 5);
|
||||
switch (EffectID[killer.PlayerId])
|
||||
{
|
||||
case 1: // BSR
|
||||
var delay = Math.Max(0.15f, BSRDelay.GetFloat());
|
||||
@@ -211,7 +213,7 @@ namespace TOHE.Roles.Impostor
|
||||
}
|
||||
}
|
||||
|
||||
EffectID = byte.MaxValue;
|
||||
EffectID[killer.PlayerId] = byte.MaxValue;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -260,8 +262,9 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
EffectID = byte.MaxValue;
|
||||
foreach (var playerId in waitingDelayedKills.Keys)
|
||||
EffectID.Clear();
|
||||
isPositiveEffect.Clear();
|
||||
foreach (var playerId in waitingDelayedKills.Keys.ToArray())
|
||||
{
|
||||
var pc = GetPlayerById(playerId);
|
||||
if (pc.IsAlive()) pc.Kill(pc);
|
||||
|
||||
@@ -129,6 +129,7 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
if (librarian == null) return true;
|
||||
|
||||
reporter.SetRealKiller(librarian);
|
||||
if (librarian.RpcCheckAndMurder(reporter))
|
||||
{
|
||||
sssh.Add(librarian.PlayerId);
|
||||
@@ -143,7 +144,7 @@ namespace TOHE.Roles.Impostor
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool OnShapeshift(PlayerControl pc)
|
||||
public static bool OnShapeshift(PlayerControl pc, bool shapeshifting)
|
||||
{
|
||||
if (!IsEnable) return false;
|
||||
if (pc == null) return false;
|
||||
@@ -153,7 +154,7 @@ namespace TOHE.Roles.Impostor
|
||||
isInSilencingMode[id] = (!isInSilencingMode[id].SILENCING, GetTimeStamp());
|
||||
SendRPC(id, isInSilencingMode[id].SILENCING);
|
||||
|
||||
return ShowSSAnimation.GetBool();
|
||||
return !shapeshifting || ShowSSAnimation.GetBool();
|
||||
}
|
||||
|
||||
public static void OnFixedUpdate()
|
||||
@@ -179,13 +180,9 @@ namespace TOHE.Roles.Impostor
|
||||
sssh.Clear();
|
||||
}
|
||||
|
||||
public static string GetNameTextForSuffix(byte playerId)
|
||||
{
|
||||
if (!IsEnable) return string.Empty;
|
||||
return isInSilencingMode.TryGetValue(playerId, out var x) && x.SILENCING && sssh.Contains(playerId) && GameStates.IsInTask
|
||||
public static string GetNameTextForSuffix(byte playerId) => IsEnable && isInSilencingMode.TryGetValue(playerId, out var x) && x.SILENCING && sssh.Contains(playerId) && GameStates.IsInTask
|
||||
? GetString("LibrarianNameText")
|
||||
: string.Empty;
|
||||
}
|
||||
|
||||
public static string GetSelfSuffixAndHUDText(byte playerId)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
using static TOHE.Utils;
|
||||
@@ -59,7 +60,7 @@ namespace TOHE.Roles.Impostor
|
||||
return killer.CheckDoubleTrigger(target, () =>
|
||||
{
|
||||
killer.SetKillCooldown(time: ManipulateCD);
|
||||
if (target.HasKillButton() || target.GetPlayerTaskState().hasTasks)
|
||||
if (target.HasKillButton() || target.GetPlayerTaskState().hasTasks || UsePets.GetBool())
|
||||
{
|
||||
ManipulateDelays.TryAdd(target.PlayerId, GetTimeStamp());
|
||||
NotifyRoles(SpecifySeer: killer, SpecifyTarget: target);
|
||||
@@ -85,13 +86,13 @@ namespace TOHE.Roles.Impostor
|
||||
ManipulateDelays.Remove(x.Key);
|
||||
ManipulatedPlayers.TryAdd(x.Key, GetTimeStamp());
|
||||
|
||||
if (!pc.GetPlayerTaskState().hasTasks)
|
||||
if (!pc.GetPlayerTaskState().hasTasks || UsePets.GetBool())
|
||||
{
|
||||
TempKCDs.TryAdd(pc.PlayerId, Main.KillTimers[pc.PlayerId]);
|
||||
pc.SetKillCooldown(time: 1f);
|
||||
}
|
||||
|
||||
NotifyRoles(SpecifySeer: Mastermind_, SpecifyTarget: Mastermind_);
|
||||
NotifyRoles(SpecifySeer: Mastermind_, SpecifyTarget: pc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
var time = TimeLimit.GetInt() - (GetTimeStamp() - x.Value);
|
||||
|
||||
player.Notify(string.Format(GetString(player.GetPlayerTaskState().hasTasks ? "ManipulateTaskNotify" : "ManipulateNotify"), time), 1.1f);
|
||||
player.Notify(string.Format(GetString(UsePets.GetBool() ? "ManipulatePetNotify" : player.GetPlayerTaskState().hasTasks ? "ManipulateTaskNotify" : "ManipulateNotify"), time), 1.1f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +158,9 @@ namespace TOHE.Roles.Impostor
|
||||
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
killer.SetKillCooldown(time: TempKCDs.TryGetValue(killer.PlayerId, out var cd) ? cd : 0f + Main.AllPlayerKillCooldown[killer.PlayerId]);
|
||||
var kcd = TempKCDs.TryGetValue(killer.PlayerId, out var cd) ? cd : Main.AllPlayerKillCooldown.TryGetValue(killer.PlayerId, out var baseKCD) ? baseKCD : DefaultKillCooldown;
|
||||
killer.SetKillCooldown(time: kcd);
|
||||
if (killer.GetCustomRole().PetActivatedAbility()) killer.AddAbilityCD((int)Math.Round(kcd));
|
||||
TempKCDs.Remove(killer.PlayerId);
|
||||
}, 0.1f, "Set KCD for Manipulated Kill");
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace TOHE.Roles.Impostor
|
||||
public static bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
if (!IsEnable) return false;
|
||||
if (killer == null || target == null) return false;
|
||||
if (killer == null || target == null || !killer.Is(CustomRoles.YinYanger)) return false;
|
||||
|
||||
if (YinYangedPlayers.Count == 2)
|
||||
{
|
||||
|
||||
+59
-10
@@ -1,6 +1,9 @@
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Utils;
|
||||
|
||||
@@ -61,10 +64,29 @@ namespace TOHE.Roles.Neutral
|
||||
public static bool IsEnable => BubbleId != byte.MaxValue;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
private static void SendRPC(byte id = byte.MaxValue, bool remove = false, bool clear = false)
|
||||
{
|
||||
if (!IsEnable || !DoRPC) return;
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncBubble, SendOption.Reliable, -1);
|
||||
writer.Write(remove);
|
||||
writer.Write(clear);
|
||||
writer.Write(id);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
public static void ReceiveRPC(MessageReader reader)
|
||||
{
|
||||
bool remove = reader.ReadBoolean();
|
||||
bool clear = reader.ReadBoolean();
|
||||
byte id = reader.ReadByte();
|
||||
if (clear) EncasedPlayers.Clear();
|
||||
else if (remove) EncasedPlayers.Remove(id);
|
||||
else EncasedPlayers.Add(id, GetTimeStamp());
|
||||
}
|
||||
public static void OnCheckMurder(PlayerControl target)
|
||||
{
|
||||
if (!IsEnable || target == null) return;
|
||||
EncasedPlayers.Add(target.PlayerId, GetTimeStamp());
|
||||
SendRPC(target.PlayerId);
|
||||
Bubble_.SetKillCooldown();
|
||||
}
|
||||
public static void OnFixedUpdate()
|
||||
@@ -72,25 +94,52 @@ namespace TOHE.Roles.Neutral
|
||||
if (!IsEnable || !GameStates.IsInTask || EncasedPlayers.Count == 0) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
foreach (var id in EncasedPlayers.Where(item => item.Value + ExplodeDelay.GetInt() < now).Select(item => item.Key).ToArray())
|
||||
foreach (var kvp in EncasedPlayers)
|
||||
{
|
||||
var players = GetPlayersInRadius(ExplosionRadius.GetFloat(), GetPlayerById(id).Pos());
|
||||
foreach (var pc in players)
|
||||
var id = kvp.Key;
|
||||
var encasedPc = GetPlayerById(id);
|
||||
|
||||
if (kvp.Value + ExplodeDelay.GetInt() < now)
|
||||
{
|
||||
if (pc == null) continue;
|
||||
if (pc.PlayerId == BubbleId)
|
||||
if (!encasedPc.IsAlive())
|
||||
{
|
||||
if (BubbleDiesIfInRange.GetBool()) _ = new LateTask(() => { if (GameStates.IsInTask) pc.Suicide(); }, 0.2f, log: false);
|
||||
else continue;
|
||||
EncasedPlayers.Remove(id);
|
||||
SendRPC(id, remove: true);
|
||||
continue;
|
||||
}
|
||||
pc.Suicide(realKiller: Bubble_);
|
||||
var players = GetPlayersInRadius(ExplosionRadius.GetFloat(), encasedPc.Pos());
|
||||
foreach (var pc in players)
|
||||
{
|
||||
if (pc == null) continue;
|
||||
if (pc.PlayerId == BubbleId)
|
||||
{
|
||||
if (BubbleDiesIfInRange.GetBool()) _ = new LateTask(() => { if (GameStates.IsInTask) pc.Suicide(PlayerState.DeathReason.Bombed); }, 0.5f, log: false);
|
||||
continue;
|
||||
}
|
||||
pc.Suicide(PlayerState.DeathReason.Bombed, Bubble_);
|
||||
}
|
||||
EncasedPlayers.Remove(id);
|
||||
SendRPC(id, remove: true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kvp.Value + NotifyDelay.GetInt() < now)
|
||||
{
|
||||
Main.AllAlivePlayerControls.Where(x => Vector2.Distance(x.Pos(), encasedPc.Pos()) < 5f).Do(x => NotifyRoles(SpecifySeer: x, SpecifyTarget: encasedPc));
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
if (IsEnable) return;
|
||||
foreach (var pc in EncasedPlayers.Keys.Select(x => GetPlayerById(x)).Where(x => x != null && x.IsAlive())) pc.Suicide(realKiller: Bubble_);
|
||||
if (!IsEnable) return;
|
||||
foreach (var pc in EncasedPlayers.Keys.Select(x => GetPlayerById(x)).Where(x => x != null && x.IsAlive())) pc.Suicide(PlayerState.DeathReason.Bombed, Bubble_);
|
||||
EncasedPlayers.Clear();
|
||||
SendRPC(clear: true);
|
||||
}
|
||||
public static string GetEncasedPlayerSuffix(PlayerControl seer, PlayerControl target)
|
||||
{
|
||||
if (!IsEnable || target == null || !EncasedPlayers.TryGetValue(target.PlayerId, out var ts) || (ts + NotifyDelay.GetInt() >= GetTimeStamp())) return string.Empty;
|
||||
return ColorString(GetRoleColor(CustomRoles.Bubble), $"{ExplodeDelay.GetInt() - (GetTimeStamp() - ts) + 1}s");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,27 +72,39 @@ public static class Executioner
|
||||
playerIdList.Add(playerId);
|
||||
|
||||
//ターゲット割り当て
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
try
|
||||
{
|
||||
List<PlayerControl> targetList = [];
|
||||
var rand = IRandom.Instance;
|
||||
foreach (PlayerControl target in Main.AllPlayerControls)
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
if (playerId == target.PlayerId) continue;
|
||||
else if (!CanTargetImpostor.GetBool() && target.Is(CustomRoleTypes.Impostor)) continue;
|
||||
else if (!CanTargetNeutralKiller.GetBool() && target.IsNeutralKiller()) continue;
|
||||
else if (!CanTargetNeutralBenign.GetBool() && target.IsNeutralBenign()) continue;
|
||||
else if (!CanTargetNeutralEvil.GetBool() && target.IsNeutralEvil()) continue;
|
||||
else if (!CanTargetNeutralChaos.GetBool() && target.IsNeutralChaos()) continue;
|
||||
if (target.GetCustomRole() is CustomRoles.GM or CustomRoles.SuperStar) continue;
|
||||
if (Utils.GetPlayerById(playerId).Is(CustomRoles.Lovers) && target.Is(CustomRoles.Lovers)) continue;
|
||||
List<PlayerControl> targetList = [];
|
||||
var rand = IRandom.Instance;
|
||||
foreach (PlayerControl target in Main.AllPlayerControls)
|
||||
{
|
||||
if (playerId == target.PlayerId) continue;
|
||||
else if (!CanTargetImpostor.GetBool() && target.Is(CustomRoleTypes.Impostor)) continue;
|
||||
else if (!CanTargetNeutralKiller.GetBool() && target.IsNeutralKiller()) continue;
|
||||
else if (!CanTargetNeutralBenign.GetBool() && target.IsNeutralBenign()) continue;
|
||||
else if (!CanTargetNeutralEvil.GetBool() && target.IsNeutralEvil()) continue;
|
||||
else if (!CanTargetNeutralChaos.GetBool() && target.IsNeutralChaos()) continue;
|
||||
if (target.GetCustomRole() is CustomRoles.GM or CustomRoles.SuperStar) continue;
|
||||
if (Utils.GetPlayerById(playerId).Is(CustomRoles.Lovers) && target.Is(CustomRoles.Lovers)) continue;
|
||||
|
||||
targetList.Add(target);
|
||||
targetList.Add(target);
|
||||
}
|
||||
if (targetList.Count == 0)
|
||||
{
|
||||
ChangeRole(Utils.GetPlayerById(playerId));
|
||||
return;
|
||||
}
|
||||
var SelectedTarget = targetList[rand.Next(targetList.Count)];
|
||||
Target.Add(playerId, SelectedTarget.PlayerId);
|
||||
SendRPC(playerId, SelectedTarget.PlayerId, "SetTarget");
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}:{SelectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Executioner");
|
||||
}
|
||||
var SelectedTarget = targetList[rand.Next(targetList.Count)];
|
||||
Target.Add(playerId, SelectedTarget.PlayerId);
|
||||
SendRPC(playerId, SelectedTarget.PlayerId, "SetTarget");
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}:{SelectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Executioner");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Error(ex.ToString(), "Executioner.Add");
|
||||
}
|
||||
}
|
||||
public static bool IsEnable() => playerIdList.Count > 0;
|
||||
|
||||
+22
-11
@@ -51,9 +51,14 @@ namespace TOHE.Roles.Neutral
|
||||
if (!IsEnable || !DoRPC) return;
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncHookshot, SendOption.Reliable, -1);
|
||||
writer.Write(ToTargetTP);
|
||||
writer.Write(MarkedPlayerId);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
public static void ReceiveRPC(MessageReader reader) => ToTargetTP = reader.ReadBoolean();
|
||||
public static void ReceiveRPC(MessageReader reader)
|
||||
{
|
||||
ToTargetTP = reader.ReadBoolean();
|
||||
MarkedPlayerId = reader.ReadByte();
|
||||
}
|
||||
public static void ExecuteAction()
|
||||
{
|
||||
if (MarkedPlayerId == byte.MaxValue) return;
|
||||
@@ -62,19 +67,20 @@ namespace TOHE.Roles.Neutral
|
||||
if (markedPlayer == null)
|
||||
{
|
||||
MarkedPlayerId = byte.MaxValue;
|
||||
SendRPC();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ToTargetTP)
|
||||
{
|
||||
Hookshot_.TP(markedPlayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
markedPlayer.TP(Hookshot_);
|
||||
}
|
||||
bool isTPsuccess;
|
||||
|
||||
MarkedPlayerId = byte.MaxValue;
|
||||
if (ToTargetTP) isTPsuccess = Hookshot_.TP(markedPlayer);
|
||||
else isTPsuccess = markedPlayer.TP(Hookshot_);
|
||||
|
||||
if (isTPsuccess)
|
||||
{
|
||||
MarkedPlayerId = byte.MaxValue;
|
||||
SendRPC();
|
||||
}
|
||||
}
|
||||
public static void SwitchActionMode()
|
||||
{
|
||||
@@ -89,10 +95,15 @@ namespace TOHE.Roles.Neutral
|
||||
return Hookshot_.CheckDoubleTrigger(target, () =>
|
||||
{
|
||||
MarkedPlayerId = target.PlayerId;
|
||||
SendRPC();
|
||||
Hookshot_.SetKillCooldown(5f);
|
||||
});
|
||||
}
|
||||
public static void OnReportDeadBody() => MarkedPlayerId = byte.MaxValue;
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
MarkedPlayerId = byte.MaxValue;
|
||||
SendRPC();
|
||||
}
|
||||
public static string SuffixText => $"<#00ffa5>Mode:</color> <#ffffff>{(ToTargetTP ? "TP to Target" : "Pull Target")}</color>";
|
||||
}
|
||||
}
|
||||
+33
-28
@@ -75,27 +75,39 @@ public static class Lawyer
|
||||
playerIdList.Add(playerId);
|
||||
|
||||
//ターゲット割り当て
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
try
|
||||
{
|
||||
List<PlayerControl> targetList = [];
|
||||
var rand = IRandom.Instance;
|
||||
foreach (PlayerControl target in Main.AllPlayerControls)
|
||||
if (AmongUsClient.Instance.AmHost)
|
||||
{
|
||||
if (playerId == target.PlayerId) continue;
|
||||
else if (!CanTargetImpostor.GetBool() && target.Is(CustomRoleTypes.Impostor)) continue;
|
||||
else if (!CanTargetNeutralKiller.GetBool() && target.IsNeutralKiller()) continue;
|
||||
else if (!CanTargetCrewmate.GetBool() && target.Is(CustomRoleTypes.Crewmate)) continue;
|
||||
else if (!CanTargetJester.GetBool() && target.Is(CustomRoles.Jester)) continue;
|
||||
else if (target.Is(CustomRoleTypes.Neutral) && !target.IsNeutralKiller() && !target.Is(CustomRoles.Jester)) continue;
|
||||
if (target.GetCustomRole() is CustomRoles.GM or CustomRoles.SuperStar) continue;
|
||||
if (Utils.GetPlayerById(playerId).Is(CustomRoles.Lovers) && target.Is(CustomRoles.Lovers)) continue;
|
||||
List<PlayerControl> targetList = [];
|
||||
var rand = IRandom.Instance;
|
||||
foreach (PlayerControl target in Main.AllPlayerControls)
|
||||
{
|
||||
if (playerId == target.PlayerId) continue;
|
||||
else if (!CanTargetImpostor.GetBool() && target.Is(CustomRoleTypes.Impostor)) continue;
|
||||
else if (!CanTargetNeutralKiller.GetBool() && target.IsNeutralKiller()) continue;
|
||||
else if (!CanTargetCrewmate.GetBool() && target.Is(CustomRoleTypes.Crewmate)) continue;
|
||||
else if (!CanTargetJester.GetBool() && target.Is(CustomRoles.Jester)) continue;
|
||||
else if (target.Is(CustomRoleTypes.Neutral) && !target.IsNeutralKiller() && !target.Is(CustomRoles.Jester)) continue;
|
||||
if (target.GetCustomRole() is CustomRoles.GM or CustomRoles.SuperStar) continue;
|
||||
if (Utils.GetPlayerById(playerId).Is(CustomRoles.Lovers) && target.Is(CustomRoles.Lovers)) continue;
|
||||
|
||||
targetList.Add(target);
|
||||
targetList.Add(target);
|
||||
}
|
||||
if (targetList.Count == 0)
|
||||
{
|
||||
ChangeRole(Utils.GetPlayerById(playerId));
|
||||
return;
|
||||
}
|
||||
var SelectedTarget = targetList[rand.Next(targetList.Count)];
|
||||
Target.Add(playerId, SelectedTarget.PlayerId);
|
||||
SendRPC(playerId, SelectedTarget.PlayerId, "SetTarget");
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}:{SelectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Lawyer");
|
||||
}
|
||||
var SelectedTarget = targetList[rand.Next(targetList.Count)];
|
||||
Target.Add(playerId, SelectedTarget.PlayerId);
|
||||
SendRPC(playerId, SelectedTarget.PlayerId, "SetTarget");
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()}:{SelectedTarget.GetNameWithRole().RemoveHtmlTags()}", "Lawyer");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Logger.Error(ex.ToString(), "Lawyer.Add");
|
||||
}
|
||||
}
|
||||
public static bool IsEnable() => playerIdList.Count > 0;
|
||||
@@ -139,11 +151,12 @@ public static class Lawyer
|
||||
if (x.Value == target.PlayerId)
|
||||
Lawyer = x.Key;
|
||||
});
|
||||
Utils.GetPlayerById(Lawyer).RpcSetCustomRole(CRoleChangeRoles[ChangeRolesAfterTargetKilled.GetValue()]);
|
||||
PlayerControl lawyer = Utils.GetPlayerById(Lawyer);
|
||||
lawyer.RpcSetCustomRole(CRoleChangeRoles[ChangeRolesAfterTargetKilled.GetValue()]);
|
||||
Target.Remove(Lawyer);
|
||||
SendRPC(Lawyer);
|
||||
Utils.NotifyRoles(SpecifySeer: Utils.GetPlayerById(Lawyer), SpecifyTarget: target);
|
||||
Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: Utils.GetPlayerById(Lawyer));
|
||||
Utils.NotifyRoles(SpecifySeer: lawyer, SpecifyTarget: target);
|
||||
Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: lawyer);
|
||||
}
|
||||
public static bool KnowRole(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
@@ -161,7 +174,6 @@ public static class Lawyer
|
||||
var GetValue = Target.TryGetValue(seer.PlayerId, out var targetId);
|
||||
return GetValue && targetId == target.PlayerId ? Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lawyer), "§") : string.Empty;
|
||||
}
|
||||
|
||||
public static void ChangeRole(PlayerControl lawyer)
|
||||
{
|
||||
lawyer.RpcSetCustomRole(CRoleChangeRoles[ChangeRolesAfterTargetKilled.GetValue()]);
|
||||
@@ -171,13 +183,6 @@ public static class Lawyer
|
||||
text = string.Format(text, Utils.ColorString(Utils.GetRoleColor(CRoleChangeRoles[ChangeRolesAfterTargetKilled.GetValue()]), Translator.GetString(CRoleChangeRoles[ChangeRolesAfterTargetKilled.GetValue()].ToString())));
|
||||
lawyer.Notify(text);
|
||||
}
|
||||
public static string TargetMark(PlayerControl seer, PlayerControl target)
|
||||
{
|
||||
if (!seer.Is(CustomRoles.Lawyer)) return string.Empty; //エクスキューショナー以外処理しない
|
||||
|
||||
var GetValue = Target.TryGetValue(seer.PlayerId, out var targetId);
|
||||
return GetValue && targetId == target.PlayerId ? Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lawyer), "§") : string.Empty;
|
||||
}
|
||||
public static bool CheckExileTarget(GameData.PlayerInfo exiled/*, bool DecidedWinner, bool Check = false*/)
|
||||
{
|
||||
foreach (var kvp in Target.Where(x => x.Value == exiled.PlayerId))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static TOHE.Options;
|
||||
@@ -45,7 +46,7 @@ namespace TOHE.Roles.Neutral
|
||||
InfectRadius = FloatOptionItem.Create(Id + 5, "InfectRadius", new(0.1f, 5f, 0.1f), 3f, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Mycologist])
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
InfectTime = IntegerOptionItem.Create(Id + 6, "PlagueDoctorInfectTime", new(0, 60, 1), 5, TabGroup.NeutralRoles, false)
|
||||
InfectTime = IntegerOptionItem.Create(Id + 6, "InfectDelay", new(0, 60, 1), 5, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Mycologist])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
}
|
||||
@@ -65,6 +66,23 @@ namespace TOHE.Roles.Neutral
|
||||
public static bool IsEnable => MycologistId != byte.MaxValue;
|
||||
public static void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public static void ApplyGameOptions(IGameOptions opt) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
private static void SendRPC()
|
||||
{
|
||||
if (!IsEnable || !DoRPC) return;
|
||||
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(PlayerControl.LocalPlayer.NetId, (byte)CustomRPC.SyncMycologist, SendOption.Reliable, -1);
|
||||
writer.Write(InfectedPlayers.Count);
|
||||
if (InfectedPlayers.Count > 0) foreach (var x in InfectedPlayers) writer.Write(x);
|
||||
AmongUsClient.Instance.FinishRpcImmediately(writer);
|
||||
}
|
||||
public static void ReceiveRPC(MessageReader reader)
|
||||
{
|
||||
InfectedPlayers.Clear();
|
||||
var length = reader.ReadInt32();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
InfectedPlayers.Add(reader.ReadByte());
|
||||
}
|
||||
}
|
||||
public static void SpreadSpores()
|
||||
{
|
||||
if (!IsEnable || Mycologist_.HasAbilityCD()) return;
|
||||
@@ -72,6 +90,8 @@ namespace TOHE.Roles.Neutral
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
InfectedPlayers.AddRange(GetPlayersInRadius(InfectRadius.GetFloat(), Mycologist_.Pos()).Select(x => x.PlayerId));
|
||||
SendRPC();
|
||||
NotifyRoles(SpecifySeer: Mycologist_);
|
||||
}, InfectTime.GetFloat(), "Mycologist Infect Time");
|
||||
Mycologist_.Notify(GetString("MycologistNotify"));
|
||||
}
|
||||
|
||||
+31
-30
@@ -4,6 +4,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
using static TOHE.Utils;
|
||||
|
||||
namespace TOHE.Roles.Neutral
|
||||
@@ -93,56 +94,56 @@ namespace TOHE.Roles.Neutral
|
||||
public static void ReceiveRPC(MessageReader reader) => UseLimit = reader.ReadInt32();
|
||||
public static void PlaceTrap()
|
||||
{
|
||||
if (!IsEnable || Sprayer_.HasAbilityCD() || UseLimit <= 0) return;
|
||||
if (!IsEnable || UseLimit <= 0 || Sprayer_.HasAbilityCD()) return;
|
||||
|
||||
Traps.Add(Sprayer_.Pos());
|
||||
UseLimit--;
|
||||
SendRPC();
|
||||
|
||||
if (UseLimit > 0) Sprayer_.AddAbilityCD(CD.GetInt());
|
||||
|
||||
Sprayer_.Notify(GetString("SprayerNotify"));
|
||||
}
|
||||
public static void OnFixedUpdate()
|
||||
public static void OnCheckPlayerPosition(PlayerControl pc)
|
||||
{
|
||||
if (!IsEnable || !GameStates.IsInTask || Traps.Count == 0) return;
|
||||
|
||||
long now = GetTimeStamp();
|
||||
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
if (pc.PlayerId == SprayerId) return;
|
||||
|
||||
if (!LastUpdate.ContainsKey(pc.PlayerId)) LastUpdate.Add(pc.PlayerId, now);
|
||||
if (LastUpdate[pc.PlayerId] + 3 > now) return;
|
||||
LastUpdate[pc.PlayerId] = now;
|
||||
|
||||
foreach (var trap in Traps.ToArray())
|
||||
{
|
||||
if (pc.PlayerId == SprayerId) continue;
|
||||
|
||||
if (!LastUpdate.ContainsKey(pc.PlayerId)) LastUpdate.Add(pc.PlayerId, now);
|
||||
if (LastUpdate[pc.PlayerId] + 3 > now) continue;
|
||||
LastUpdate[pc.PlayerId] = now;
|
||||
|
||||
foreach (var trap in Traps.ToArray())
|
||||
if (Vector2.Distance(pc.Pos(), trap) <= 2f)
|
||||
{
|
||||
if (Vector2.Distance(pc.Pos(), trap) <= 2f)
|
||||
byte playerId = pc.PlayerId;
|
||||
var tempSpeed = Main.AllPlayerSpeed[playerId];
|
||||
Main.AllPlayerSpeed[playerId] = LoweredSpeed.GetFloat();
|
||||
LowerVisionList.Add(playerId);
|
||||
TrappedCount[playerId]++;
|
||||
if (TrappedCount[playerId] > MaxTrappedTimes.GetInt())
|
||||
{
|
||||
byte playerId = pc.PlayerId;
|
||||
var tempSpeed = Main.AllPlayerSpeed[playerId];
|
||||
Main.AllPlayerSpeed[playerId] = LoweredSpeed.GetFloat();
|
||||
LowerVisionList.Add(playerId);
|
||||
TrappedCount[playerId]++;
|
||||
if (TrappedCount[playerId] > MaxTrappedTimes.GetInt())
|
||||
pc.Suicide(realKiller: Sprayer_);
|
||||
TrappedCount.Remove(playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
pc.MarkDirtySettings();
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
pc.Suicide(realKiller: Sprayer_);
|
||||
TrappedCount.Remove(playerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
pc.MarkDirtySettings();
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
Main.AllPlayerSpeed[playerId] = tempSpeed;
|
||||
LowerVisionList.Remove(playerId);
|
||||
if (GameStates.IsInTask) pc.MarkDirtySettings();
|
||||
}, EffectDuration.GetFloat(), "Sprayer Revert Effects");
|
||||
}
|
||||
Main.AllPlayerSpeed[playerId] = tempSpeed;
|
||||
LowerVisionList.Remove(playerId);
|
||||
if (GameStates.IsInTask) pc.MarkDirtySettings();
|
||||
}, EffectDuration.GetFloat(), "Sprayer Revert Effects");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
Traps.Clear();
|
||||
|
||||
@@ -92,7 +92,7 @@ public static class Vengeance
|
||||
if (target == null) return false;
|
||||
if (IsRevenge) return true;
|
||||
|
||||
_ = new LateTask(target.TPtoRndVent, 0.01f);
|
||||
_ = new LateTask(() => { target.TPtoRndVent(); }, 0.01f);
|
||||
|
||||
Timer = RevengeTime.GetInt();
|
||||
Countdown(Timer, target);
|
||||
|
||||
+2
-1
@@ -18,6 +18,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Modules\zqihthf4.eqf~" />
|
||||
<None Remove="resources\modnews\english\TOHE+.v1.2.0.txt" />
|
||||
<None Remove="resources\modnews\english\TOHE+.v1.3.0.txt" />
|
||||
<None Remove="resources\modnews\english\TOHE+.v1.4.0.txt" />
|
||||
@@ -35,7 +36,7 @@
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2023.11.28" PrivateAssets="all" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.1.0-rc.1" />
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.682" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="Samboy063.Cpp2IL.Core" Version="2022.1.0-development.898" />
|
||||
<PackageReference Include="Samboy063.Cpp2IL.Core" Version="2022.1.0-pre-release.13" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -33,8 +33,8 @@ public class Main : BasePlugin
|
||||
public static ConfigEntry<string> DebugKeyInput { get; private set; }
|
||||
public static readonly string MainMenuText = " ";
|
||||
public const string PluginGuid = "com.gurge44.toheplus";
|
||||
public const string PluginVersion = "2.2.0";
|
||||
public const string PluginDisplayVersion = "2.2.0";
|
||||
public const string PluginVersion = "2.2.4";
|
||||
public const string PluginDisplayVersion = "2.2.4";
|
||||
public static readonly string SupportedAUVersion = "2023.10.24";
|
||||
public const int PluginCreate = 3;
|
||||
public const bool Canary = false;
|
||||
@@ -653,84 +653,80 @@ public enum CustomRoles
|
||||
|
||||
//Impostors
|
||||
|
||||
BountyHunter,
|
||||
FireWorks,
|
||||
Mafia,
|
||||
Godfather,
|
||||
SerialKiller,
|
||||
//ShapeMaster,
|
||||
Wildling,
|
||||
EvilGuesser,
|
||||
Minimalism,
|
||||
Zombie,
|
||||
Sniper,
|
||||
Vampire,
|
||||
Witch,
|
||||
Warlock,
|
||||
Assassin,
|
||||
Undertaker,
|
||||
Vindicator,
|
||||
Hacker,
|
||||
Miner,
|
||||
Escapee,
|
||||
Inhibitor,
|
||||
Librarian,
|
||||
Chronomancer,
|
||||
Nullifier,
|
||||
Stealth,
|
||||
Penguin,
|
||||
Sapper,
|
||||
Mastermind,
|
||||
Hitman,
|
||||
RiftMaker,
|
||||
Gambler,
|
||||
Puppeteer,
|
||||
TimeThief,
|
||||
EvilTracker,
|
||||
Hacker, // Anonymous
|
||||
AntiAdminer,
|
||||
Consort,
|
||||
Sans,
|
||||
Bomber,
|
||||
Nuker,
|
||||
BoobyTrap,
|
||||
Scavenger,
|
||||
Capitalism,
|
||||
Gangster,
|
||||
Cleaner,
|
||||
BallLightning,
|
||||
Greedier,
|
||||
CursedWolf,
|
||||
ImperiusCurse,
|
||||
QuickShooter,
|
||||
Eraser,
|
||||
OverKiller,
|
||||
Hangman,
|
||||
Sans, // Arrogance
|
||||
Bard,
|
||||
Mafioso,
|
||||
Trickster,
|
||||
Swooper,
|
||||
Cantankerous,
|
||||
Duellist,
|
||||
YinYanger,
|
||||
Crewpostor,
|
||||
Parasite,
|
||||
Disperser,
|
||||
Blackmailer,
|
||||
Bomber,
|
||||
BountyHunter,
|
||||
OverKiller, // Butcher
|
||||
Camouflager,
|
||||
Saboteur,
|
||||
Capitalism,
|
||||
Cantankerous,
|
||||
Chronomancer,
|
||||
EvilDiviner, // Consigliere
|
||||
Consort,
|
||||
Councillor,
|
||||
Dazzler,
|
||||
Crewpostor,
|
||||
CursedWolf,
|
||||
Deathpact,
|
||||
Devourer,
|
||||
EvilDiviner,
|
||||
Morphling,
|
||||
Twister,
|
||||
Blackmailer,
|
||||
Disperser,
|
||||
Duellist,
|
||||
Dazzler,
|
||||
Escapee,
|
||||
Eraser,
|
||||
EvilGuesser,
|
||||
EvilTracker,
|
||||
FireWorks,
|
||||
Gambler,
|
||||
Gangster,
|
||||
Godfather,
|
||||
Greedier,
|
||||
Hangman,
|
||||
Hitman,
|
||||
Inhibitor,
|
||||
Minimalism, // Killing Machine
|
||||
BallLightning, // Lightning
|
||||
Librarian,
|
||||
Lurker,
|
||||
Convict,
|
||||
Visionary,
|
||||
Mafia,
|
||||
Mafioso,
|
||||
Mastermind,
|
||||
SerialKiller, // Mercenary
|
||||
Miner,
|
||||
Morphling,
|
||||
Assassin, // Ninja
|
||||
Nuker,
|
||||
Nullifier,
|
||||
Parasite,
|
||||
Penguin,
|
||||
Puppeteer,
|
||||
QuickShooter,
|
||||
Refugee,
|
||||
RiftMaker,
|
||||
Saboteur,
|
||||
Sapper,
|
||||
Scavenger,
|
||||
Sniper,
|
||||
ImperiusCurse, // Soul Catcher
|
||||
Swooper,
|
||||
Stealth,
|
||||
TimeThief,
|
||||
BoobyTrap, // Trapster
|
||||
Trickster,
|
||||
Twister,
|
||||
Underdog,
|
||||
// Flashbang,
|
||||
Undertaker,
|
||||
Vampire,
|
||||
Vindicator,
|
||||
Visionary,
|
||||
Warlock,
|
||||
Wildling,
|
||||
Witch,
|
||||
YinYanger,
|
||||
Zombie,
|
||||
|
||||
//Crewmates (Vanilla)
|
||||
Engineer,
|
||||
@@ -744,178 +740,169 @@ public enum CustomRoles
|
||||
|
||||
// Crewmate
|
||||
|
||||
Luckey,
|
||||
Needy,
|
||||
SuperStar,
|
||||
CyberStar,
|
||||
Demolitionist,
|
||||
Ventguard,
|
||||
Express,
|
||||
NiceEraser,
|
||||
TaskManager,
|
||||
Shiftguard,
|
||||
Mole,
|
||||
Sentinel,
|
||||
Electric,
|
||||
Philantropist,
|
||||
Tornado,
|
||||
Insight,
|
||||
Tunneler,
|
||||
Detour,
|
||||
Gaulois,
|
||||
Druid,
|
||||
Drainer,
|
||||
CameraMan,
|
||||
NiceHacker,
|
||||
Spy,
|
||||
Ricochet,
|
||||
Doormaster,
|
||||
Tether,
|
||||
Admirer,
|
||||
Addict,
|
||||
Aid,
|
||||
Benefactor,
|
||||
GuessManager,
|
||||
Escort,
|
||||
DonutDelivery,
|
||||
Alchemist,
|
||||
Altruist,
|
||||
Analyzer,
|
||||
Mayor,
|
||||
Jailor,
|
||||
Paranoia,
|
||||
Psychic,
|
||||
SabotageMaster,
|
||||
Sheriff,
|
||||
Snitch,
|
||||
Enigma,
|
||||
Marshall,
|
||||
SpeedBooster,
|
||||
Lookout,
|
||||
Autocrat,
|
||||
Benefactor,
|
||||
Bodyguard,
|
||||
CameraMan,
|
||||
CyberStar, // Celebrity
|
||||
Chameleon,
|
||||
Cleaner,
|
||||
Cleanser,
|
||||
CopyCat,
|
||||
Bloodhound, // Coroner
|
||||
Crusader,
|
||||
Demolitionist,
|
||||
Deputy,
|
||||
Detective,
|
||||
Detour,
|
||||
Dictator,
|
||||
Doctor,
|
||||
Detective,
|
||||
SwordsMan,
|
||||
NiceGuesser,
|
||||
Transporter,
|
||||
NiceSwapper,
|
||||
Altruist,
|
||||
Transmitter,
|
||||
Autocrat,
|
||||
Nightmare,
|
||||
TimeManager,
|
||||
Veteran,
|
||||
Bodyguard,
|
||||
//Counterfeiter,
|
||||
Witness,
|
||||
Grenadier,
|
||||
Lighter,
|
||||
SecurityGuard,
|
||||
Medic,
|
||||
Divinator,
|
||||
Glitch,
|
||||
Judge,
|
||||
Mortician,
|
||||
Mediumshiper,
|
||||
Observer,
|
||||
DonutDelivery,
|
||||
Doormaster,
|
||||
DovesOfNeace,
|
||||
Monarch,
|
||||
CopyCat,
|
||||
Drainer,
|
||||
Druid,
|
||||
Electric,
|
||||
Enigma,
|
||||
Escort,
|
||||
Express,
|
||||
Farseer,
|
||||
Bloodhound,
|
||||
Tracker,
|
||||
Merchant,
|
||||
//Retributionist,
|
||||
Deputy,
|
||||
Divinator, // Fortune Teller
|
||||
Gaulois,
|
||||
Glitch,
|
||||
Grenadier,
|
||||
GuessManager,
|
||||
Guardian,
|
||||
Addict,
|
||||
Alchemist,
|
||||
Tracefinder,
|
||||
Ignitor,
|
||||
Oracle,
|
||||
Spiritualist,
|
||||
Chameleon,
|
||||
ParityCop,
|
||||
Admirer,
|
||||
TimeMaster,
|
||||
Insight,
|
||||
ParityCop, // Inspector
|
||||
Jailor,
|
||||
Judge,
|
||||
Needy, // Lazy Guy
|
||||
Lighter,
|
||||
Lookout,
|
||||
Luckey,
|
||||
Marshall,
|
||||
Mayor,
|
||||
SabotageMaster, // Mechanic
|
||||
Medic,
|
||||
Mediumshiper,
|
||||
Merchant,
|
||||
Monitor,
|
||||
Crusader,
|
||||
Cleanser,
|
||||
//Reverie,
|
||||
Mole,
|
||||
Monarch,
|
||||
Mortician,
|
||||
NiceEraser,
|
||||
NiceGuesser,
|
||||
NiceHacker,
|
||||
NiceSwapper,
|
||||
Nightmare,
|
||||
Observer,
|
||||
Oracle,
|
||||
Paranoia,
|
||||
Philantropist,
|
||||
Psychic,
|
||||
Ricochet,
|
||||
Sentinel,
|
||||
SecurityGuard,
|
||||
Sheriff,
|
||||
Shiftguard,
|
||||
Snitch,
|
||||
Spiritualist,
|
||||
Speedrunner,
|
||||
SpeedBooster,
|
||||
Spy,
|
||||
SuperStar,
|
||||
TaskManager,
|
||||
Tether,
|
||||
TimeManager,
|
||||
TimeMaster,
|
||||
Tornado,
|
||||
Tracker,
|
||||
Transmitter,
|
||||
Transporter,
|
||||
Tracefinder,
|
||||
Tunneler,
|
||||
Ventguard,
|
||||
Veteran,
|
||||
SwordsMan, // Vigilante
|
||||
Witness,
|
||||
|
||||
//Neutrals
|
||||
|
||||
Arsonist,
|
||||
HexMaster,
|
||||
Jester,
|
||||
God,
|
||||
Opportunist,
|
||||
Mario,
|
||||
Terrorist,
|
||||
Executioner,
|
||||
Bandit,
|
||||
Lawyer,
|
||||
Jackal,
|
||||
Poisoner,
|
||||
//NWitch,
|
||||
Innocent,
|
||||
Pelican,
|
||||
Revolutionist,
|
||||
NSerialKiller,
|
||||
Enderman,
|
||||
Mycologist,
|
||||
Bubble,
|
||||
Hookshot,
|
||||
Sprayer,
|
||||
PlagueDoctor,
|
||||
Postman,
|
||||
Reckless,
|
||||
Magician,
|
||||
WeaponMaster,
|
||||
Eclipse,
|
||||
Pyromaniac,
|
||||
Vengeance,
|
||||
HeadHunter,
|
||||
Imitator,
|
||||
Werewolf,
|
||||
Juggernaut,
|
||||
Infectious,
|
||||
FFF,
|
||||
Konan,
|
||||
Gamer,
|
||||
DarkHide,
|
||||
Workaholic,
|
||||
Speedrunner,
|
||||
Collector,
|
||||
Agitater,
|
||||
Provocateur,
|
||||
Sunnyboy,
|
||||
BloodKnight,
|
||||
Wraith,
|
||||
Totocalcio,
|
||||
Romantic,
|
||||
VengefulRomantic,
|
||||
RuthlessRomantic,
|
||||
Succubus,
|
||||
Virus,
|
||||
Pursuer,
|
||||
Phantom,
|
||||
Jinx,
|
||||
Maverick,
|
||||
//CursedSoul,
|
||||
//Pirate,
|
||||
Ritualist,
|
||||
Doppelganger,
|
||||
Pickpocket,
|
||||
Traitor,
|
||||
Vulture,
|
||||
PlagueBearer,
|
||||
Pestilence,
|
||||
Medusa,
|
||||
Sidekick,
|
||||
//Baker,
|
||||
//Famine,
|
||||
Spiritcaller,
|
||||
Amnesiac,
|
||||
Arsonist,
|
||||
Bandit,
|
||||
BloodKnight,
|
||||
Bubble,
|
||||
Collector,
|
||||
Gamer, // Demon
|
||||
Doppelganger,
|
||||
Doomsayer,
|
||||
//Masochist,
|
||||
// Flux,
|
||||
Eclipse,
|
||||
Enderman,
|
||||
Executioner,
|
||||
Totocalcio, // Follower
|
||||
God,
|
||||
FFF, // Hater
|
||||
HeadHunter,
|
||||
HexMaster,
|
||||
Hookshot,
|
||||
Imitator,
|
||||
Infectious,
|
||||
Innocent,
|
||||
Jackal,
|
||||
Jester,
|
||||
Jinx,
|
||||
Juggernaut,
|
||||
Konan,
|
||||
Lawyer,
|
||||
Magician,
|
||||
Mario,
|
||||
Maverick,
|
||||
Medusa,
|
||||
Mycologist,
|
||||
Opportunist,
|
||||
Pelican,
|
||||
Pestilence,
|
||||
Phantom,
|
||||
Pickpocket,
|
||||
PlagueBearer,
|
||||
PlagueDoctor,
|
||||
Poisoner,
|
||||
Postman,
|
||||
Provocateur,
|
||||
Pursuer,
|
||||
Pyromaniac,
|
||||
Reckless,
|
||||
Revolutionist,
|
||||
Ritualist,
|
||||
Romantic,
|
||||
RuthlessRomantic,
|
||||
NSerialKiller, // Serial Killer
|
||||
Sidekick,
|
||||
Spiritcaller,
|
||||
Sprayer,
|
||||
DarkHide, // Stalker
|
||||
Succubus,
|
||||
Sunnyboy,
|
||||
Terrorist,
|
||||
Traitor,
|
||||
Vengeance,
|
||||
VengefulRomantic,
|
||||
Virus,
|
||||
Vulture,
|
||||
Wraith,
|
||||
Werewolf,
|
||||
WeaponMaster,
|
||||
Workaholic,
|
||||
|
||||
//SoloKombat
|
||||
KB_Normal,
|
||||
@@ -926,66 +913,67 @@ public enum CustomRoles
|
||||
//GM
|
||||
GM,
|
||||
|
||||
// ????
|
||||
Convict,
|
||||
|
||||
// Sub-role after 500
|
||||
NotAssigned = 500,
|
||||
LastImpostor,
|
||||
Lovers,
|
||||
Ntr,
|
||||
Madmate,
|
||||
Watcher,
|
||||
Flashman,
|
||||
Torch,
|
||||
Seer,
|
||||
Brakar,
|
||||
Oblivious,
|
||||
Bewilder,
|
||||
Sunglasses,
|
||||
Workhorse,
|
||||
Fool,
|
||||
Avanger,
|
||||
Youtuber,
|
||||
Egoist,
|
||||
TicketsStealer,
|
||||
DualPersonality,
|
||||
Mimic,
|
||||
Guesser,
|
||||
Necroview,
|
||||
Reach,
|
||||
Charmed,
|
||||
Bait,
|
||||
Trapper,
|
||||
Infected,
|
||||
Onbound,
|
||||
Knighted,
|
||||
Contagious,
|
||||
Cleansed,
|
||||
Unreportable,
|
||||
DeadlyQuota,
|
||||
Damocles,
|
||||
Stressed,
|
||||
Rogue,
|
||||
Lucky,
|
||||
Unlucky,
|
||||
DoubleShot,
|
||||
// Reflective,
|
||||
Rascal,
|
||||
Soulless,
|
||||
Gravestone,
|
||||
Lazy,
|
||||
Autopsy,
|
||||
Loyal,
|
||||
EvilSpirit,
|
||||
Recruit,
|
||||
Admired,
|
||||
Glow,
|
||||
Diseased,
|
||||
Antidote,
|
||||
Swift,
|
||||
Autopsy,
|
||||
Avanger,
|
||||
Bait,
|
||||
Trapper, // Beartrap
|
||||
Bewilder,
|
||||
Charmed,
|
||||
Cleansed,
|
||||
Contagious,
|
||||
Damocles,
|
||||
DeadlyQuota,
|
||||
Diseased,
|
||||
Unreportable, // Disregarded
|
||||
DoubleShot,
|
||||
Egoist,
|
||||
EvilSpirit,
|
||||
Flashman,
|
||||
Fool,
|
||||
Ghoul,
|
||||
Glow,
|
||||
Gravestone,
|
||||
Guesser,
|
||||
Infected,
|
||||
Knighted,
|
||||
LastImpostor,
|
||||
Lazy,
|
||||
Lovers,
|
||||
Loyal,
|
||||
Lucky,
|
||||
Madmate,
|
||||
Mare,
|
||||
Mimic,
|
||||
Necroview,
|
||||
Ntr, // Neptune
|
||||
Nimble,
|
||||
Oblivious,
|
||||
Onbound,
|
||||
Physicist,
|
||||
// QuickFix
|
||||
Rascal,
|
||||
Reach,
|
||||
Recruit,
|
||||
Rogue,
|
||||
DualPersonality, // Schizophrenic
|
||||
Seer,
|
||||
Soulless,
|
||||
TicketsStealer, // Stealer
|
||||
Stressed,
|
||||
Swift,
|
||||
Sunglasses,
|
||||
Brakar, // Tiebreaker
|
||||
Torch,
|
||||
Unlucky,
|
||||
Watcher,
|
||||
Workhorse,
|
||||
Youtuber
|
||||
}
|
||||
//WinData
|
||||
public enum CustomWinner
|
||||
|
||||
Reference in new issue
Block a user