mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-20 11:39:54 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7ecca76f7 | ||
|
|
6b86c5ea87 | ||
|
|
57ec47d100 | ||
|
|
970712c4c5 | ||
|
|
730ea9afeb | ||
|
|
dde672ecfc | ||
|
|
badbc4e59a | ||
|
|
fe2e2b29af | ||
|
|
f2ccc0b5c7 | ||
|
|
9a4d085d88 | ||
|
|
a58997385c | ||
|
|
5062355a37 | ||
|
|
4f946a8f08 | ||
|
|
0a23a35bfb | ||
|
|
3a46be462a | ||
|
|
970281d3b1 |
No files matched your search
@@ -35,6 +35,7 @@ internal static class FFAManager
|
||||
public static OptionItem FFA_EnableRandomAbilities;
|
||||
public static OptionItem FFA_EnableRandomTwists;
|
||||
public static OptionItem FFA_ShieldIsOneTimeUse;
|
||||
public static OptionItem FFA_ChatDuringGame;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -80,6 +81,9 @@ internal static class FFAManager
|
||||
FFA_ShieldIsOneTimeUse = BooleanOptionItem.Create(67_223_013, "FFA_ShieldIsOneTimeUse", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
FFA_ChatDuringGame = BooleanOptionItem.Create(67_223_014, "FFA_ChatDuringGame", false, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.FFA)
|
||||
.SetColor(new Color32(0, 255, 165, byte.MaxValue));
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -97,10 +101,10 @@ internal static class FFAManager
|
||||
|
||||
foreach (PlayerControl pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
KillCount.TryAdd(pc.PlayerId, 0);
|
||||
KillCount[pc.PlayerId] = 0;
|
||||
}
|
||||
|
||||
_ = new LateTask(Utils.SetChatVisible, 7f, "Set Chat Visible for Everyone");
|
||||
if (FFA_ChatDuringGame.GetBool()) _ = new LateTask(Utils.SetChatVisible, 7f, "Set Chat Visible for Everyone");
|
||||
}
|
||||
private static void SendRPCSyncFFAPlayer(byte playerId)
|
||||
{
|
||||
|
||||
+93
-129
@@ -10,11 +10,12 @@ internal static class CustomRolesHelper
|
||||
{
|
||||
public static CustomRoles GetVNRole(this CustomRoles role)
|
||||
{
|
||||
bool UsePets = Options.UsePets.GetBool();
|
||||
return role.IsVanilla()
|
||||
? role
|
||||
: role switch
|
||||
{
|
||||
CustomRoles.Sniper => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Sniper => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Jester => Options.JesterCanVent.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
CustomRoles.Mayor => Options.MayorHasPortableButton.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
CustomRoles.Monitor => Monitor.CanVent.GetBool() ? CustomRoles.Engineer : CustomRoles.Crewmate,
|
||||
@@ -44,7 +45,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.EvilDiviner => CustomRoles.Impostor,
|
||||
CustomRoles.Wildling => Wildling.CanShapeshift.GetBool() ? CustomRoles.Shapeshifter : CustomRoles.Impostor,
|
||||
CustomRoles.Morphling => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Warlock => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Warlock => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.SerialKiller => CustomRoles.Impostor,
|
||||
CustomRoles.FireWorks => CustomRoles.Shapeshifter,
|
||||
CustomRoles.SpeedBooster => CustomRoles.Crewmate,
|
||||
@@ -60,9 +61,9 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Nullifier => CustomRoles.Impostor,
|
||||
CustomRoles.Stealth => CustomRoles.Impostor,
|
||||
CustomRoles.Penguin => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Sapper => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Sapper => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Mastermind => CustomRoles.Impostor,
|
||||
CustomRoles.RiftMaker => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.RiftMaker => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Gambler => CustomRoles.Impostor,
|
||||
CustomRoles.Hitman => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Saboteur => CustomRoles.Impostor,
|
||||
@@ -77,15 +78,15 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.TimeMaster => CustomRoles.Engineer,
|
||||
CustomRoles.CrewmateTOHE => CustomRoles.Crewmate,
|
||||
CustomRoles.Cleanser => CustomRoles.Crewmate,
|
||||
CustomRoles.Miner => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Miner => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Psychic => CustomRoles.Crewmate,
|
||||
CustomRoles.Needy => CustomRoles.Crewmate,
|
||||
CustomRoles.Twister => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Twister => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.SuperStar => CustomRoles.Crewmate,
|
||||
CustomRoles.Hacker => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Visionary => CustomRoles.Impostor,
|
||||
CustomRoles.Assassin => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Undertaker => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Assassin => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Undertaker => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Luckey => CustomRoles.Crewmate,
|
||||
CustomRoles.CyberStar => CustomRoles.Crewmate,
|
||||
CustomRoles.Demolitionist => CustomRoles.Crewmate,
|
||||
@@ -95,11 +96,11 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.TaskManager => CustomRoles.Crewmate,
|
||||
CustomRoles.Shiftguard => CustomRoles.Crewmate,
|
||||
CustomRoles.Mole => CustomRoles.Engineer,
|
||||
CustomRoles.Sentinel => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Sentinel => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Electric => CustomRoles.Crewmate,
|
||||
CustomRoles.Philantropist => CustomRoles.Crewmate,
|
||||
CustomRoles.Tornado => CustomRoles.Crewmate,
|
||||
CustomRoles.Druid => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Druid => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Insight => CustomRoles.Crewmate,
|
||||
CustomRoles.Tunneler => CustomRoles.Crewmate,
|
||||
CustomRoles.Detour => CustomRoles.Crewmate,
|
||||
@@ -110,17 +111,17 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Transmitter => CustomRoles.Crewmate,
|
||||
CustomRoles.Autocrat => CustomRoles.Crewmate,
|
||||
CustomRoles.Nightmare => CustomRoles.Crewmate,
|
||||
CustomRoles.CameraMan => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.CameraMan => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Spy => CustomRoles.Crewmate,
|
||||
CustomRoles.Ricochet => CustomRoles.Crewmate,
|
||||
CustomRoles.Tether => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Doormaster => Options.UsePets.GetBool() ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Aid => CustomRoles.Impostor,
|
||||
CustomRoles.Escort => CustomRoles.Impostor,
|
||||
CustomRoles.DonutDelivery => CustomRoles.Impostor,
|
||||
CustomRoles.Gaulois => CustomRoles.Impostor,
|
||||
CustomRoles.Analyzer => CustomRoles.Impostor,
|
||||
CustomRoles.Escapee => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Tether => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Doormaster => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Aid => UsePets && Aid.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Escort => UsePets && Escort.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.DonutDelivery => UsePets && DonutDelivery.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Gaulois => UsePets && Gaulois.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Analyzer => UsePets && Analyzer.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Escapee => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.NiceGuesser => CustomRoles.Crewmate,
|
||||
CustomRoles.EvilGuesser => CustomRoles.Impostor,
|
||||
CustomRoles.Detective => CustomRoles.Crewmate,
|
||||
@@ -130,8 +131,8 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Mario => CustomRoles.Engineer,
|
||||
CustomRoles.AntiAdminer => CustomRoles.Impostor,
|
||||
CustomRoles.Sans => CustomRoles.Impostor,
|
||||
CustomRoles.Bomber => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Nuker => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Bomber => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Nuker => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.BoobyTrap => CustomRoles.Impostor,
|
||||
CustomRoles.Scavenger => CustomRoles.Impostor,
|
||||
CustomRoles.Transporter => CustomRoles.Crewmate,
|
||||
@@ -153,7 +154,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.CursedWolf => CustomRoles.Impostor,
|
||||
CustomRoles.Collector => CustomRoles.Crewmate,
|
||||
CustomRoles.ImperiusCurse => CustomRoles.Shapeshifter,
|
||||
CustomRoles.QuickShooter => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.QuickShooter => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Eraser => CustomRoles.Impostor,
|
||||
CustomRoles.OverKiller => CustomRoles.Impostor,
|
||||
CustomRoles.Hangman => CustomRoles.Shapeshifter,
|
||||
@@ -168,7 +169,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Crewpostor => CustomRoles.Engineer,
|
||||
CustomRoles.Observer => CustomRoles.Crewmate,
|
||||
CustomRoles.DovesOfNeace => CustomRoles.Engineer,
|
||||
CustomRoles.Disperser => Options.UsePets.GetBool() ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Disperser => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.Camouflager => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Dazzler => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Devourer => CustomRoles.Shapeshifter,
|
||||
@@ -285,6 +286,7 @@ internal static class CustomRolesHelper
|
||||
|
||||
public static RoleTypes GetDYRole(this CustomRoles role)
|
||||
{
|
||||
bool UsePets = Options.UsePets.GetBool();
|
||||
return role switch
|
||||
{
|
||||
//SoloKombat
|
||||
@@ -294,40 +296,40 @@ internal static class CustomRolesHelper
|
||||
//Move And Stop
|
||||
CustomRoles.Tasker => RoleTypes.Crewmate,
|
||||
//Standard
|
||||
CustomRoles.Sheriff => RoleTypes.Impostor,
|
||||
CustomRoles.Crusader => RoleTypes.Impostor,
|
||||
CustomRoles.CopyCat => RoleTypes.Impostor,
|
||||
CustomRoles.Sheriff => UsePets && Sheriff.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Crusader => UsePets && Crusader.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.CopyCat => UsePets && CopyCat.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
//CustomRoles.CursedSoul => RoleTypes.Impostor,
|
||||
CustomRoles.Admirer => RoleTypes.Impostor,
|
||||
CustomRoles.Admirer => UsePets && Gaulois.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Refugee => RoleTypes.Impostor,
|
||||
CustomRoles.Amnesiac => RoleTypes.Impostor,
|
||||
CustomRoles.Agitater => RoleTypes.Impostor,
|
||||
CustomRoles.Monarch => RoleTypes.Impostor,
|
||||
CustomRoles.Deputy => RoleTypes.Impostor,
|
||||
CustomRoles.Monarch => UsePets && Monarch.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Deputy => UsePets && Deputy.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Arsonist => RoleTypes.Impostor,
|
||||
CustomRoles.Jackal => RoleTypes.Impostor,
|
||||
CustomRoles.Medusa => RoleTypes.Impostor,
|
||||
CustomRoles.Sidekick => RoleTypes.Impostor,
|
||||
CustomRoles.SwordsMan => RoleTypes.Impostor,
|
||||
CustomRoles.SwordsMan => UsePets && SwordsMan.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
//CustomRoles.Reverie => RoleTypes.Impostor,
|
||||
CustomRoles.Innocent => RoleTypes.Impostor,
|
||||
CustomRoles.Pelican => RoleTypes.Impostor,
|
||||
//CustomRoles.Counterfeiter => RoleTypes.Impostor,
|
||||
CustomRoles.Aid => RoleTypes.Impostor,
|
||||
CustomRoles.Escort => RoleTypes.Impostor,
|
||||
CustomRoles.DonutDelivery => RoleTypes.Impostor,
|
||||
CustomRoles.Gaulois => RoleTypes.Impostor,
|
||||
CustomRoles.Analyzer => RoleTypes.Impostor,
|
||||
CustomRoles.Witness => RoleTypes.Impostor,
|
||||
CustomRoles.Aid => UsePets && Aid.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Escort => UsePets && Escort.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.DonutDelivery => UsePets && DonutDelivery.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Gaulois => UsePets && Gaulois.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Analyzer => UsePets && Analyzer.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Witness => UsePets && Options.WitnessUsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Pursuer => RoleTypes.Impostor,
|
||||
CustomRoles.Revolutionist => RoleTypes.Impostor,
|
||||
CustomRoles.FFF => RoleTypes.Impostor,
|
||||
CustomRoles.Medic => RoleTypes.Impostor,
|
||||
CustomRoles.Medic => UsePets && Medic.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Gamer => RoleTypes.Impostor,
|
||||
CustomRoles.HexMaster => RoleTypes.Impostor,
|
||||
CustomRoles.Wraith => RoleTypes.Impostor,
|
||||
CustomRoles.Glitch => RoleTypes.Impostor,
|
||||
CustomRoles.Jailor => RoleTypes.Impostor,
|
||||
CustomRoles.Jailor => UsePets && Jailor.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Juggernaut => RoleTypes.Impostor,
|
||||
CustomRoles.Jinx => RoleTypes.Impostor,
|
||||
CustomRoles.DarkHide => RoleTypes.Impostor,
|
||||
@@ -362,7 +364,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Succubus => RoleTypes.Impostor,
|
||||
CustomRoles.Infectious => RoleTypes.Impostor,
|
||||
CustomRoles.Virus => RoleTypes.Impostor,
|
||||
CustomRoles.Farseer => RoleTypes.Impostor,
|
||||
CustomRoles.Farseer => UsePets && Farseer.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Ritualist => RoleTypes.Impostor,
|
||||
CustomRoles.Pickpocket => RoleTypes.Impostor,
|
||||
CustomRoles.Traitor => RoleTypes.Impostor,
|
||||
@@ -1000,86 +1002,6 @@ internal static class CustomRolesHelper
|
||||
|
||||
}
|
||||
|
||||
public static bool IsNeutralWithGuessAccess(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
//SoloKombat
|
||||
CustomRoles.KB_Normal or
|
||||
//FFA
|
||||
CustomRoles.Killer or
|
||||
//Move And Stop
|
||||
CustomRoles.Tasker or
|
||||
//Standard
|
||||
CustomRoles.Jester or
|
||||
CustomRoles.Agitater or
|
||||
CustomRoles.Doppelganger or
|
||||
CustomRoles.Opportunist or
|
||||
CustomRoles.Bandit or
|
||||
CustomRoles.Mario or
|
||||
CustomRoles.HexMaster or
|
||||
CustomRoles.Crewpostor or
|
||||
//CustomRoles.NWitch or
|
||||
CustomRoles.Wraith or
|
||||
CustomRoles.Parasite or
|
||||
CustomRoles.Terrorist or
|
||||
CustomRoles.Executioner or
|
||||
CustomRoles.Medusa or
|
||||
CustomRoles.Juggernaut or
|
||||
CustomRoles.Vulture or
|
||||
CustomRoles.Jinx or
|
||||
CustomRoles.Lawyer or
|
||||
CustomRoles.Arsonist or
|
||||
CustomRoles.Jackal or
|
||||
CustomRoles.Sidekick or
|
||||
CustomRoles.God or
|
||||
CustomRoles.Innocent or
|
||||
CustomRoles.Pursuer or
|
||||
// CustomRoles.Sidekick or
|
||||
CustomRoles.Poisoner or
|
||||
CustomRoles.NSerialKiller or
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Bubble or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Sprayer or
|
||||
CustomRoles.PlagueDoctor or
|
||||
CustomRoles.Magician or
|
||||
CustomRoles.WeaponMaster or
|
||||
CustomRoles.Reckless or
|
||||
CustomRoles.Postman or
|
||||
CustomRoles.Eclipse or
|
||||
CustomRoles.Pyromaniac or
|
||||
CustomRoles.Vengeance or
|
||||
CustomRoles.HeadHunter or
|
||||
CustomRoles.Imitator or
|
||||
CustomRoles.Werewolf or
|
||||
CustomRoles.Pelican or
|
||||
CustomRoles.Revolutionist or
|
||||
CustomRoles.FFF or
|
||||
CustomRoles.Traitor or
|
||||
CustomRoles.Konan or
|
||||
CustomRoles.Gamer or
|
||||
CustomRoles.DarkHide or
|
||||
CustomRoles.Infectious or
|
||||
CustomRoles.Workaholic or
|
||||
CustomRoles.Collector or
|
||||
CustomRoles.Provocateur or
|
||||
CustomRoles.Sunnyboy or
|
||||
CustomRoles.Phantom or
|
||||
CustomRoles.BloodKnight or
|
||||
CustomRoles.Romantic or
|
||||
CustomRoles.Totocalcio or
|
||||
CustomRoles.VengefulRomantic or
|
||||
CustomRoles.RuthlessRomantic or
|
||||
CustomRoles.Virus or
|
||||
CustomRoles.Succubus or
|
||||
CustomRoles.Spiritcaller or
|
||||
CustomRoles.Doomsayer or
|
||||
CustomRoles.PlagueBearer or
|
||||
//CustomRoles.Pirate or
|
||||
CustomRoles.Pestilence;
|
||||
}
|
||||
|
||||
public static bool IsEvilAddons(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
@@ -1104,7 +1026,7 @@ internal static class CustomRolesHelper
|
||||
}
|
||||
public static bool IsTasklessCrewmate(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
return !role.UsesPetInsteadOfKill() && role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Admirer or
|
||||
CustomRoles.Medic or
|
||||
@@ -1126,7 +1048,8 @@ internal static class CustomRolesHelper
|
||||
}
|
||||
public static bool PetActivatedAbility(this CustomRoles role)
|
||||
{
|
||||
return role is
|
||||
return Options.UsePets.GetBool() && role switch
|
||||
{
|
||||
CustomRoles.Doormaster or
|
||||
CustomRoles.Tether or
|
||||
CustomRoles.Mayor or
|
||||
@@ -1164,11 +1087,56 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Enderman or
|
||||
CustomRoles.Mycologist or
|
||||
CustomRoles.Hookshot or
|
||||
CustomRoles.Sprayer;
|
||||
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,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
public static bool UsesPetInsteadOfKill(this CustomRoles role)
|
||||
{
|
||||
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,
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
public static bool NeedUpdateOnLights(this CustomRoles role)
|
||||
{
|
||||
return role.IsNK() || role is
|
||||
return (!role.UsesPetInsteadOfKill()) && (role.GetDYRole() != RoleTypes.GuardianAngel || role is
|
||||
CustomRoles.Sheriff or
|
||||
CustomRoles.Medic or
|
||||
CustomRoles.CopyCat or
|
||||
@@ -1252,7 +1220,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Mare or
|
||||
CustomRoles.Bandit or
|
||||
CustomRoles.Agitater or
|
||||
CustomRoles.Deputy;
|
||||
CustomRoles.Deputy);
|
||||
}
|
||||
|
||||
public static bool IsBetrayalAddon(this CustomRoles role)
|
||||
@@ -1306,11 +1274,7 @@ internal static class CustomRolesHelper
|
||||
}
|
||||
public static bool CheckAddonConflictV2(CustomRoles addon, CustomRoles mainRole)
|
||||
{
|
||||
if (!addon.IsAdditionRole()) return false;
|
||||
|
||||
if (mainRole is CustomRoles.GuardianAngelTOHE or CustomRoles.God) return false;
|
||||
if (mainRole is CustomRoles.GM || addon is CustomRoles.Lovers) return false;
|
||||
return addon switch
|
||||
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,
|
||||
|
||||
+113
-91
@@ -1,5 +1,6 @@
|
||||
using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
using InnerNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -26,69 +27,68 @@ internal class EAC
|
||||
public static bool ReceiveRpc(PlayerControl pc, byte callId, MessageReader reader)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return false;
|
||||
if (pc == null || reader == null || pc.AmOwner) return false;
|
||||
if (pc == null || reader == null) return false;
|
||||
try
|
||||
{
|
||||
MessageReader sr = MessageReader.Get(reader);
|
||||
var rpc = (RpcCalls)callId;
|
||||
switch (rpc)
|
||||
{
|
||||
case RpcCalls.SetName:
|
||||
string name = sr.ReadString();
|
||||
if (sr.BytesRemaining > 0 && sr.ReadBoolean()) return false;
|
||||
if (
|
||||
((name.Contains("<size") || name.Contains("size>")) && name.Contains('?') && !name.Contains("color")) ||
|
||||
name.Length > 160 ||
|
||||
name.Count(f => f.Equals("\"\\n\"")) > 3 ||
|
||||
name.Count(f => f.Equals("\n")) > 3 ||
|
||||
name.Count(f => f.Equals("\r")) > 3 ||
|
||||
name.Contains('░') ||
|
||||
name.Contains('▄') ||
|
||||
name.Contains('█') ||
|
||||
name.Contains('▌') ||
|
||||
name.Contains('▒') ||
|
||||
name.Contains("习近平")
|
||||
)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置游戏名称");
|
||||
Logger.Fatal($"非法修改玩家【{pc.GetClientId()}:{pc.GetRealName()}】的游戏名称,已驳回", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
//case RpcCalls.SetName:
|
||||
// string name = sr.ReadString();
|
||||
// if (sr.BytesRemaining > 0 && sr.ReadBoolean()) return false;
|
||||
// if (
|
||||
// ((name.Contains("<size") || name.Contains("size>")) && name.Contains('?') && !name.Contains("color")) ||
|
||||
// name.Length > 160 ||
|
||||
// name.Count(f => f.Equals("\"\\n\"")) > 3 ||
|
||||
// name.Count(f => f.Equals("\n")) > 3 ||
|
||||
// name.Count(f => f.Equals("\r")) > 3 ||
|
||||
// name.Contains('░') ||
|
||||
// name.Contains('▄') ||
|
||||
// name.Contains('█') ||
|
||||
// name.Contains('▌') ||
|
||||
// name.Contains('▒') ||
|
||||
// name.Contains("Xi Jinping")
|
||||
// )
|
||||
// {
|
||||
// WarnHost();
|
||||
// Report(pc, "Illegal setting of game name");
|
||||
// Logger.Fatal($"Illegal modification of the game name of player [{pc.GetClientId()}:{pc.GetRealName()}] has been rejected", "EAC");
|
||||
// return true;
|
||||
// }
|
||||
// break;
|
||||
case RpcCalls.SetRole:
|
||||
var role = (RoleTypes)sr.ReadUInt16();
|
||||
if (GameStates.IsLobby && (role is RoleTypes.CrewmateGhost or RoleTypes.ImpostorGhost))
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置状态为幽灵");
|
||||
Logger.Fatal($"非法设置玩家【{pc.GetClientId()}:{pc.GetRealName()}】的状态为幽灵,已驳回", "EAC");
|
||||
Report(pc, "Illegal setting status to ghost");
|
||||
Logger.Fatal($"Illegal setting of the status of player [{pc.GetClientId()}:{pc.GetRealName()}] to ghost, has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case RpcCalls.SendChat:
|
||||
var text = sr.ReadString();
|
||||
if (text.StartsWith("/")) return false;
|
||||
if (
|
||||
text.Contains('░') ||
|
||||
text.Contains('▄') ||
|
||||
text.Contains('█') ||
|
||||
text.Contains('▌') ||
|
||||
text.Contains('▒') ||
|
||||
text.Contains("习近平")
|
||||
text.Contains("Xi Jinping")
|
||||
)
|
||||
{
|
||||
Report(pc, "非法消息");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】发送非法消息,已驳回", "EAC");
|
||||
Report(pc, "Illegal message");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sent an illegal message, which has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
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");
|
||||
Logger.Fatal($"非法设置玩家【{pc.GetClientId()}:{pc.GetRealName()}】的游戏名称,已驳回", "EAC");
|
||||
Logger.Fatal($"Illegal setting of the game name of the player [{pc.GetClientId()}:{pc.GetRealName()}] has been rejected", "EAC");
|
||||
return true;
|
||||
case RpcCalls.ReportDeadBody:
|
||||
if (!GameStates.IsInGame)
|
||||
@@ -96,7 +96,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Report body out of game A");
|
||||
HandleCheat(pc, "Report body out of game A");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非游戏内开会,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] has a non-in-game meeting and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (ReportTimes.TryGetValue(pc.PlayerId, out int rtimes))
|
||||
@@ -106,7 +106,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Spam report bodies A");
|
||||
HandleCheat(pc, "Spam report bodies A");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】刷报告尸体满14次,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] reported corpses 14 times and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "Set color in game");
|
||||
HandleCheat(pc, "Set color in game");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】游戏内设置颜色,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] sets the color in the game and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (pc.Data.DefaultOutfit.ColorId != -1 &&
|
||||
@@ -127,9 +127,16 @@ internal class EAC
|
||||
|| color < 0 || color > 18))
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置颜色");
|
||||
Report(pc, "Illegal color setting");
|
||||
AmongUsClient.Instance.KickPlayer(pc.GetClientId(), false);
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置颜色,已驳回", "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;
|
||||
@@ -139,15 +146,33 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(pc, "CheckMurder in Lobby");
|
||||
HandleCheat(pc, "CheckMurder in Lobby");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法检查击杀,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally checked for kill and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
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($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】直接击杀,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] killed directly, rejected", "EAC");
|
||||
return true;
|
||||
case RpcCalls.CheckShapeshift:
|
||||
if (GameStates.IsLobby)
|
||||
{
|
||||
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)
|
||||
@@ -159,11 +184,12 @@ internal class EAC
|
||||
HandleCheat(pc, GetString("EAC.CheatDetected.EAC"));
|
||||
return true;
|
||||
case 7:
|
||||
case 8:
|
||||
if (!GameStates.IsLobby)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置颜色");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置颜色,已驳回", "EAC");
|
||||
Report(pc, "Illegal color setting");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally set the color and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -172,8 +198,8 @@ internal class EAC
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置游戏名称");
|
||||
Logger.Fatal($"非法修改玩家【{pc.GetClientId()}:{pc.GetRealName()}】的游戏名称,已驳回", "EAC");
|
||||
Report(pc, "Illegal setting of game name");
|
||||
Logger.Fatal($"Illegal modification of the game name of player [{pc.GetClientId()}:{pc.GetRealName()}] has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
@@ -181,54 +207,50 @@ internal class EAC
|
||||
if (GameStates.IsLobby)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法击杀");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法击杀,已驳回", "EAC");
|
||||
Report(pc, "illegal kill");
|
||||
Logger.Fatal($"Player [{pc.GetClientId()}:{pc.GetRealName()}] illegally killed and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 41:
|
||||
case 38:
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置宠物");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置宠物,已驳回", "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, "非法设置皮肤");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置皮肤,已驳回", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 42:
|
||||
if (GameStates.IsInGame)
|
||||
{
|
||||
WarnHost();
|
||||
Report(pc, "非法设置面部装扮");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置面部装扮,已驳回", "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, "非法设置帽子");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置帽子,已驳回", "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, "非法设置游戏名称");
|
||||
Logger.Fatal($"玩家【{pc.GetClientId()}:{pc.GetRealName()}】非法设置名称,已驳回", "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;
|
||||
@@ -262,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:
|
||||
@@ -271,22 +293,22 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Bad Sabotage A : Non Imp");
|
||||
HandleCheat(player, "Bad Sabotage A : Non Imp");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage A,已驳回", "EAC");
|
||||
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage A, rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SystemTypes.LifeSupp:
|
||||
if (Mapid != 0 && Mapid != 1 && Mapid != 3) goto YesCheat;
|
||||
else if (amount != 64 && amount != 65) goto YesCheat;
|
||||
if (Mapid is not 0 and not 1 and not 3) goto YesCheat;
|
||||
else if (amount is not 64 and not 65) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.Comms:
|
||||
if (amount == 0)
|
||||
{
|
||||
if (Mapid == 1 || Mapid == 5) goto YesCheat;
|
||||
if (Mapid is 1 or 5) goto YesCheat;
|
||||
}
|
||||
else if (amount == 64 || amount == 65 || amount == 32 || amount == 33 || amount == 16 || amount == 17)
|
||||
else if (amount is 64 or 65 or 32 or 33 or 16 or 17)
|
||||
{
|
||||
if (!(Mapid == 1 || Mapid == 5)) goto YesCheat;
|
||||
if (!(Mapid is 1 or 5)) goto YesCheat;
|
||||
}
|
||||
else goto YesCheat;
|
||||
break;
|
||||
@@ -299,16 +321,16 @@ internal class EAC
|
||||
break;
|
||||
case SystemTypes.Laboratory:
|
||||
if (Mapid != 2) goto YesCheat;
|
||||
else if (!(amount == 64 || amount == 65 || amount == 32 || amount == 33)) goto YesCheat;
|
||||
else if (!(amount is 64 or 65 or 32 or 33)) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.Reactor:
|
||||
if (Mapid == 2 || Mapid == 4) goto YesCheat;
|
||||
else if (!(amount == 64 || amount == 65 || amount == 32 || amount == 33)) goto YesCheat;
|
||||
if (Mapid is 2 or 4) goto YesCheat;
|
||||
else if (!(amount is 64 or 65 or 32 or 33)) goto YesCheat;
|
||||
//Airship use heli sabotage /Other use 64,65 | 32,33
|
||||
break;
|
||||
case SystemTypes.HeliSabotage:
|
||||
if (Mapid != 4) goto YesCheat;
|
||||
else if (!(amount == 64 || amount == 65 || amount == 16 || amount == 17 || amount == 32 || amount == 33)) goto YesCheat;
|
||||
else if (!(amount is 64 or 65 or 16 or 17 or 32 or 33)) goto YesCheat;
|
||||
break;
|
||||
case SystemTypes.MushroomMixupSabotage:
|
||||
goto YesCheat;
|
||||
@@ -318,7 +340,7 @@ internal class EAC
|
||||
{
|
||||
WarnHost();
|
||||
Report(player, "Bad Sabotage D : In Meeting");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage D,已驳回", "EAC");
|
||||
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage D, rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
//There may be cases where a player is fixing reactor and a meeting start, triggering EAC check in meeting
|
||||
@@ -330,7 +352,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Bad Sabotage C : Hack send RPC");
|
||||
HandleCheat(player, "Bad Sabotage C");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage C,已驳回", "EAC");
|
||||
Logger.Fatal($"Player【{player.GetClientId()}:{player.GetRealName()}】Bad Sabotage C, rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -353,7 +375,7 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Report body out of game");
|
||||
HandleCheat(player, "Report body out of game");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】非游戏内开会,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{player.GetClientId()}:{player.GetRealName()}] is not meeting in the game and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -364,13 +386,13 @@ internal class EAC
|
||||
WarnHost();
|
||||
Report(player, "Spam report bodies");
|
||||
HandleCheat(player, "Spam report bodies");
|
||||
Logger.Fatal($"玩家【{player.GetClientId()}:{player.GetRealName()}】刷报告尸体满14次,已驳回", "EAC");
|
||||
Logger.Fatal($"Player [{player.GetClientId()}:{player.GetRealName()}] reported corpses 14 times and has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
if (GameStates.IsMeeting)
|
||||
{
|
||||
//Cancel rpc report body if a meeting is already held
|
||||
Logger.Info($"玩家【{player.GetClientId()}:{player.GetRealName()}】在会议期间开会,已驳回", "EAC");
|
||||
Logger.Info($"Player [{player.GetClientId()}:{player.GetRealName()}] held a meeting during the meeting and it has been rejected", "EAC");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -383,8 +405,8 @@ internal class EAC
|
||||
{
|
||||
string msg = $"{pc.GetClientId()}|{pc.FriendCode}|{pc.Data.PlayerName}|{pc.GetClient().GetHashedPuid()}|{reason}";
|
||||
//Cloud.SendData(msg);
|
||||
Logger.Fatal($"EAC报告:{msg}", "EAC Cloud");
|
||||
Logger.SendInGame(string.Format(GetString("Message.NoticeByEAC"), $"{pc?.Data?.PlayerName} | {pc.GetClient().GetHashedPuid()}", reason));
|
||||
Logger.Fatal($"EAC report: {msg}", "EAC Cloud");
|
||||
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;
|
||||
@@ -202,6 +203,7 @@ static class ExtendedPlayerControl
|
||||
// player.ResetKillCooldown();
|
||||
//}
|
||||
|
||||
public static void AddKCDAsAbilityCD(this PlayerControl pc) => AddAbilityCD(pc, (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out var KCD) ? KCD : Options.DefaultKillCooldown));
|
||||
public static void AddAbilityCD(this PlayerControl pc, bool includeDuration = true) => Utils.AddAbilityCD(pc.GetCustomRole(), pc.PlayerId, includeDuration);
|
||||
public static void AddAbilityCD(this PlayerControl pc, int CD) => Main.AbilityCD[pc.PlayerId] = (GetTimeStamp(), CD);
|
||||
public static bool HasAbilityCD(this PlayerControl pc) => Main.AbilityCD.ContainsKey(pc.PlayerId);
|
||||
@@ -218,6 +220,12 @@ static class ExtendedPlayerControl
|
||||
public static void SetKillCooldown(this PlayerControl player, float time = -1f, PlayerControl target = null, bool forceAnime = false)
|
||||
{
|
||||
if (player == null) return;
|
||||
if (player.GetCustomRole().PetActivatedAbility())
|
||||
{
|
||||
if (time == -1f) player.AddKCDAsAbilityCD();
|
||||
else player.AddAbilityCD((int)Math.Round(time));
|
||||
return;
|
||||
}
|
||||
if (!player.CanUseKillButton()) return;
|
||||
player.AddKillTimerToDict(CD: time);
|
||||
if (target == null) target = player;
|
||||
@@ -616,8 +624,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 => !IsActive(SystemTypes.Electrical) && !IsActive(SystemTypes.Laboratory) && !IsActive(SystemTypes.Comms) && !IsActive(SystemTypes.LifeSupp) && !IsActive(SystemTypes.Reactor),
|
||||
CustomRoles.Saboteur => IsActive(SystemTypes.Electrical) || IsActive(SystemTypes.Laboratory) || IsActive(SystemTypes.Comms) || IsActive(SystemTypes.LifeSupp) || IsActive(SystemTypes.Reactor),
|
||||
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.Sniper => Sniper.CanUseKillButton(pc),
|
||||
CustomRoles.Sheriff => Sheriff.CanUseKillButton(pc.PlayerId),
|
||||
CustomRoles.Crusader => Crusader.CanUseKillButton(pc.PlayerId),
|
||||
@@ -889,14 +897,23 @@ static class ExtendedPlayerControl
|
||||
{
|
||||
if (Main.AllPlayerKillCooldown.TryGetValue(pc.PlayerId, out var kcd)) resultKCD = kcd;
|
||||
else resultKCD = 0f;
|
||||
|
||||
if (half)
|
||||
{
|
||||
resultKCD /= 2f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resultKCD = CD;
|
||||
}
|
||||
|
||||
if (Main.KillTimers.TryGetValue(pc.PlayerId, out var timer) && timer > resultKCD) return;
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill() && resultKCD > 0f)
|
||||
{
|
||||
pc.AddAbilityCD((int)Math.Round(resultKCD));
|
||||
}
|
||||
|
||||
if (Main.KillTimers.TryGetValue(pc.PlayerId, out var timer) && timer > resultKCD) return;
|
||||
Main.KillTimers[pc.PlayerId] = resultKCD;
|
||||
}
|
||||
|
||||
@@ -1383,6 +1400,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();
|
||||
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");
|
||||
@@ -1421,7 +1444,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);
|
||||
|
||||
+12
-12
@@ -39,7 +39,7 @@ static class LocateArrow
|
||||
LocateArrows.Clear();
|
||||
}
|
||||
/// <summary>
|
||||
/// 新たにターゲット矢印対象を登録
|
||||
/// Register a new target arrow object
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -51,7 +51,7 @@ static class LocateArrow
|
||||
LocateArrows[arrowInfo] = "・";
|
||||
}
|
||||
/// <summary>
|
||||
/// ターゲットの削除
|
||||
/// Delete target
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -65,7 +65,7 @@ static class LocateArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// タイプの同じターゲットの全削除
|
||||
/// Delete all targets for the specified seer
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void RemoveAllTarget(byte seer)
|
||||
@@ -77,7 +77,7 @@ static class LocateArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 見ることのできるすべてのターゲット矢印を取得
|
||||
/// Get all visible target arrows
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <returns></returns>
|
||||
@@ -91,8 +91,8 @@ static class LocateArrow
|
||||
return arrows;
|
||||
}
|
||||
/// <summary>
|
||||
/// FixedUpdate毎にターゲット矢印を確認
|
||||
/// 更新があったらNotifyRolesを発行
|
||||
/// Check target arrow every FixedUpdate
|
||||
/// Issue NotifyRoles when there are updates
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void OnFixedUpdate(PlayerControl seer)
|
||||
@@ -115,20 +115,20 @@ static class LocateArrow
|
||||
update = true;
|
||||
continue;
|
||||
}
|
||||
//対象の方角ベクトルを取る
|
||||
// Take the direction vector of the target
|
||||
var dir = loc - seer.transform.position;
|
||||
int index;
|
||||
if (dir.magnitude < 2)
|
||||
{
|
||||
//近い時はドット表示
|
||||
// Display a dot when close
|
||||
index = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
//-22.5~22.5度を0とするindexに変換
|
||||
// 下が0度、左側が+180まで右側が-180まで
|
||||
// 180度足すことで上が0度の時計回り
|
||||
// 45度単位のindexにするため45/2を加算
|
||||
// Convert to index with -22.5 to 22.5 degrees as 0
|
||||
// Bottom is 0 degrees, left side is +180, right side is -180
|
||||
// Adding 180 degrees clockwise with top being 0 degrees
|
||||
// Add 45/2 to make index in 45 degree units
|
||||
var angle = Vector3.SignedAngle(Vector3.down, dir, Vector3.back) + 180 + 22.5;
|
||||
index = ((int)(angle / 45)) % 8;
|
||||
}
|
||||
|
||||
+19
-3
@@ -118,7 +118,8 @@ public static class Options
|
||||
"Ban",
|
||||
"Kick",
|
||||
"NoticeMe",
|
||||
"NoticeEveryone"
|
||||
"NoticeEveryone",
|
||||
"OnlyCancel"
|
||||
];
|
||||
public static readonly string[] ConfirmEjectionsMode =
|
||||
[
|
||||
@@ -331,6 +332,7 @@ public static class Options
|
||||
public static OptionItem BodyguardKillsKiller;
|
||||
public static OptionItem WitnessCD;
|
||||
public static OptionItem WitnessTime;
|
||||
public static OptionItem WitnessUsePet;
|
||||
public static OptionItem DQNumOfKillsNeeded;
|
||||
public static OptionItem ParanoiaNumOfUseButton;
|
||||
public static OptionItem ParanoiaVentCooldown;
|
||||
@@ -370,6 +372,8 @@ public static class Options
|
||||
public static OptionItem UnderdogCanKillWithMorePlayersAlive;
|
||||
public static OptionItem UnderdogKillCooldownWithMorePlayersAlive;
|
||||
|
||||
public static OptionItem GodfatherCancelVote;
|
||||
|
||||
public static OptionItem NimbleCD;
|
||||
public static OptionItem NimbleInVentTime;
|
||||
public static OptionItem PhysicistCD;
|
||||
@@ -1315,6 +1319,7 @@ public static class Options
|
||||
RoleLoadingText = "Impostor roles\nGodfather";
|
||||
|
||||
SetupRoleOptions(555420, TabGroup.ImpostorRoles, CustomRoles.Godfather);
|
||||
GodfatherCancelVote = CreateVoteCancellingUseSetting(555422, CustomRoles.Godfather, TabGroup.ImpostorRoles);
|
||||
RoleLoadingText = "Impostor roles\nMorphling";
|
||||
Morphling.SetupCustomOption();
|
||||
RoleLoadingText = "Impostor roles\nNemesis";
|
||||
@@ -1790,6 +1795,7 @@ public static class Options
|
||||
WitnessTime = IntegerOptionItem.Create(8553, "WitnessTime", new(0, 90, 1), 10, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Witness])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
WitnessUsePet = CreatePetUseSetting(8554, CustomRoles.Witness);
|
||||
RoleLoadingText = "Crewmate roles\nVigilante";
|
||||
SwordsMan.SetupCustomOption();
|
||||
//Reverie.SetupCustomOption();
|
||||
@@ -2737,7 +2743,7 @@ public static class Options
|
||||
RemovePetsAtDeadPlayers = BooleanOptionItem.Create(60294, "RemovePetsAtDeadPlayers", false, TabGroup.SystemSettings, false)
|
||||
.SetColor(Color.magenta);
|
||||
|
||||
CheatResponses = StringOptionItem.Create(19319, "CheatResponses", CheatResponsesName, 0, TabGroup.SystemSettings, false)
|
||||
CheatResponses = StringOptionItem.Create(19319, "CheatResponses", CheatResponsesName, 2, TabGroup.SystemSettings, false)
|
||||
.SetHeader(true);
|
||||
|
||||
//HighLevelAntiCheat = StringOptionItem.Create(19320, "HighLevelAntiCheat", CheatResponsesName, 0, TabGroup.SystemSettings, false)
|
||||
@@ -3735,6 +3741,16 @@ public static class Options
|
||||
.SetParent(CustomRoleSpawnChances[role])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
|
||||
public static OptionItem CreatePetUseSetting(int id, CustomRoles role) =>
|
||||
BooleanOptionItem.Create(id, "UsePetInsteadOfKillButton", false, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[role])
|
||||
.SetColor(Color.magenta);
|
||||
|
||||
public static OptionItem CreateVoteCancellingUseSetting(int id, CustomRoles role, TabGroup tab) =>
|
||||
BooleanOptionItem.Create(id, "UseVoteCancellingAfterVote", false, tab, false)
|
||||
.SetParent(CustomRoleSpawnChances[role])
|
||||
.SetColor(Color.yellow);
|
||||
|
||||
public class OverrideTasksData
|
||||
{
|
||||
public static Dictionary<CustomRoles, OverrideTasksData> AllData = [];
|
||||
@@ -3768,7 +3784,7 @@ public static class Options
|
||||
numShortTasks.ReplacementDictionary = replacementDic;
|
||||
|
||||
if (!AllData.ContainsKey(role)) AllData.Add(role, this);
|
||||
else Logger.Warn("重複したCustomRolesを対象とするOverrideTasksDataが作成されました", "OverrideTasksData");
|
||||
else Logger.Warn("OverrideTasksData created for duplicate CustomRoles", "OverrideTasksData");
|
||||
}
|
||||
public static OverrideTasksData Create(int idStart, TabGroup tab, CustomRoles role) => new(idStart, tab, role);
|
||||
}
|
||||
|
||||
+12
-12
@@ -40,7 +40,7 @@ static class TargetArrow
|
||||
TargetArrows.Clear();
|
||||
}
|
||||
/// <summary>
|
||||
/// 新たにターゲット矢印対象を登録
|
||||
/// Register a new target arrow object
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -52,7 +52,7 @@ static class TargetArrow
|
||||
TargetArrows[arrowInfo] = "・";
|
||||
}
|
||||
/// <summary>
|
||||
/// ターゲットの削除
|
||||
/// Delete target
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <param name="target"></param>
|
||||
@@ -66,7 +66,7 @@ static class TargetArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// タイプの同じターゲットの全削除
|
||||
/// Delete all targets for the specified seer
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void RemoveAllTarget(byte seer)
|
||||
@@ -78,7 +78,7 @@ static class TargetArrow
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 見ることのできるすべてのターゲット矢印を取得
|
||||
/// Get all visible target arrows
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
/// <returns></returns>
|
||||
@@ -92,8 +92,8 @@ static class TargetArrow
|
||||
return arrows;
|
||||
}
|
||||
/// <summary>
|
||||
/// FixedUpdate毎にターゲット矢印を確認
|
||||
/// 更新があったらNotifyRolesを発行
|
||||
/// Check target arrow every FixedUpdate
|
||||
/// Issue NotifyRoles when there are updates
|
||||
/// </summary>
|
||||
/// <param name="seer"></param>
|
||||
public static void OnFixedUpdate(PlayerControl seer)
|
||||
@@ -117,20 +117,20 @@ static class TargetArrow
|
||||
update = true;
|
||||
continue;
|
||||
}
|
||||
//対象の方角ベクトルを取る
|
||||
// Take the direction vector of the target
|
||||
var dir = target.transform.position - seer.transform.position;
|
||||
int index;
|
||||
if (dir.magnitude < 2)
|
||||
{
|
||||
//近い時はドット表示
|
||||
// Display a dot when close
|
||||
index = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
//-22.5~22.5度を0とするindexに変換
|
||||
// 下が0度、左側が+180まで右側が-180まで
|
||||
// 180度足すことで上が0度の時計回り
|
||||
// 45度単位のindexにするため45/2を加算
|
||||
// Convert to index with -22.5 to 22.5 degrees as 0
|
||||
// Bottom is 0 degrees, left side is +180, right side is -180
|
||||
// Adding 180 degrees clockwise with top being 0 degrees
|
||||
// Add 45/2 to make index in 45 degree units
|
||||
var angle = Vector3.SignedAngle(Vector3.down, dir, Vector3.back) + 180 + 22.5;
|
||||
index = ((int)(angle / 45)) % 8;
|
||||
}
|
||||
|
||||
+40
-17
@@ -490,7 +490,7 @@ public static class Utils
|
||||
switch (role)
|
||||
{
|
||||
case CustomRoles.GM:
|
||||
case CustomRoles.Sheriff:
|
||||
case CustomRoles.Sheriff when !Options.UsePets.GetBool() || !Sheriff.UsePet.GetBool():
|
||||
case CustomRoles.Arsonist:
|
||||
case CustomRoles.Jackal:
|
||||
case CustomRoles.Sidekick:
|
||||
@@ -514,7 +514,7 @@ public static class Utils
|
||||
case CustomRoles.Imitator:
|
||||
case CustomRoles.Werewolf:
|
||||
case CustomRoles.Bandit:
|
||||
case CustomRoles.Jailor:
|
||||
case CustomRoles.Jailor when !Options.UsePets.GetBool() || !Jailor.UsePet.GetBool():
|
||||
case CustomRoles.Traitor:
|
||||
case CustomRoles.Glitch:
|
||||
case CustomRoles.Pickpocket:
|
||||
@@ -522,7 +522,7 @@ public static class Utils
|
||||
case CustomRoles.Jinx:
|
||||
case CustomRoles.Parasite:
|
||||
case CustomRoles.Agitater:
|
||||
case CustomRoles.Crusader:
|
||||
case CustomRoles.Crusader when !Options.UsePets.GetBool() || !Crusader.UsePet.GetBool():
|
||||
case CustomRoles.Refugee:
|
||||
case CustomRoles.Jester:
|
||||
//case CustomRoles.Pirate:
|
||||
@@ -532,7 +532,7 @@ public static class Utils
|
||||
case CustomRoles.Mario:
|
||||
case CustomRoles.Vulture:
|
||||
case CustomRoles.God:
|
||||
case CustomRoles.SwordsMan:
|
||||
case CustomRoles.SwordsMan when !Options.UsePets.GetBool() || !SwordsMan.UsePet.GetBool():
|
||||
case CustomRoles.Innocent:
|
||||
case CustomRoles.Pelican:
|
||||
case CustomRoles.Medusa:
|
||||
@@ -549,7 +549,7 @@ public static class Utils
|
||||
case CustomRoles.Collector:
|
||||
case CustomRoles.ImperiusCurse:
|
||||
case CustomRoles.Provocateur:
|
||||
case CustomRoles.Medic:
|
||||
case CustomRoles.Medic when !Options.UsePets.GetBool() || !Medic.UsePet.GetBool():
|
||||
case CustomRoles.BloodKnight:
|
||||
case CustomRoles.Camouflager:
|
||||
case CustomRoles.Totocalcio:
|
||||
@@ -558,20 +558,20 @@ public static class Utils
|
||||
case CustomRoles.RuthlessRomantic:
|
||||
case CustomRoles.Succubus:
|
||||
//case CustomRoles.CursedSoul:
|
||||
case CustomRoles.Admirer:
|
||||
case CustomRoles.Admirer when !Options.UsePets.GetBool() || !Admirer.UsePet.GetBool():
|
||||
case CustomRoles.Amnesiac:
|
||||
case CustomRoles.Infectious:
|
||||
case CustomRoles.Monarch:
|
||||
case CustomRoles.Deputy:
|
||||
case CustomRoles.Monarch when !Options.UsePets.GetBool() || !Monarch.UsePet.GetBool():
|
||||
case CustomRoles.Deputy when !Options.UsePets.GetBool() || !Deputy.UsePet.GetBool():
|
||||
case CustomRoles.Virus:
|
||||
case CustomRoles.Farseer:
|
||||
case CustomRoles.Farseer when !Options.UsePets.GetBool() || !Farseer.UsePet.GetBool():
|
||||
//case CustomRoles.Counterfeiter:
|
||||
case CustomRoles.Aid:
|
||||
case CustomRoles.Escort:
|
||||
case CustomRoles.DonutDelivery:
|
||||
case CustomRoles.Gaulois:
|
||||
case CustomRoles.Analyzer:
|
||||
case CustomRoles.Witness:
|
||||
case CustomRoles.Aid when !Options.UsePets.GetBool() || !Aid.UsePet.GetBool():
|
||||
case CustomRoles.Escort when !Options.UsePets.GetBool() || !Escort.UsePet.GetBool():
|
||||
case CustomRoles.DonutDelivery when !Options.UsePets.GetBool() || !DonutDelivery.UsePet.GetBool():
|
||||
case CustomRoles.Gaulois when !Options.UsePets.GetBool() || !Gaulois.UsePet.GetBool():
|
||||
case CustomRoles.Analyzer when !Options.UsePets.GetBool() || !Analyzer.UsePet.GetBool():
|
||||
case CustomRoles.Witness when !Options.UsePets.GetBool() || !Options.WitnessUsePet.GetBool():
|
||||
case CustomRoles.Pursuer:
|
||||
case CustomRoles.Spiritcaller:
|
||||
case CustomRoles.PlagueBearer:
|
||||
@@ -623,7 +623,7 @@ public static class Utils
|
||||
}
|
||||
}
|
||||
|
||||
if (CopyCat.playerIdList.Contains(p.PlayerId) && ForRecompute) hasTasks = false;
|
||||
if (CopyCat.playerIdList.Contains(p.PlayerId) && ForRecompute && (!Options.UsePets.GetBool() || CopyCat.UsePet.GetBool())) hasTasks = false;
|
||||
|
||||
return hasTasks;
|
||||
}
|
||||
@@ -2549,6 +2549,11 @@ public static class Utils
|
||||
}
|
||||
public static void AddAbilityCD(CustomRoles role, byte playerId, bool includeDuration = true)
|
||||
{
|
||||
if (role.UsesPetInsteadOfKill())
|
||||
{
|
||||
Main.AbilityCD[playerId] = (GetTimeStamp(), (int)Math.Round(Main.AllPlayerKillCooldown.TryGetValue(playerId, out var KCD) ? KCD : Options.DefaultKillCooldown));
|
||||
return;
|
||||
}
|
||||
int CD = role switch
|
||||
{
|
||||
CustomRoles.Doormaster => Doormaster.VentCooldown.GetInt(),
|
||||
@@ -2650,6 +2655,8 @@ public static class Utils
|
||||
if (Options.AirshipVariableElectrical.GetBool())
|
||||
AirshipElectricalDoors.Initialize();
|
||||
|
||||
Main.DontCancelVoteList.Clear();
|
||||
|
||||
DoorsReset.ResetDoors();
|
||||
KeepProtection.ProtectEveryone();
|
||||
|
||||
@@ -2891,7 +2898,23 @@ public static class Utils
|
||||
neutralnum++;
|
||||
}
|
||||
}
|
||||
return $"{(notify ? "<color=#777777>" : string.Empty)}There {(impnum == 1 ? "is" : "are")}{(notify ? ' ' : '\n')}{(notify ? "<#ffffff>" : "<b>")}{impnum}{(notify ? "</color>" : "</b>")} <color=#ff1919>{(impnum == 1 ? "Impostor" : "Impostors")}</color> and {(notify ? "<#ffffff>" : "<b>")}{neutralnum}{(notify ? "</color>" : "</b>")} <color=#ffab1b>{(neutralnum == 1 ? "Neutral Killer" : "Neutral Killers")}</color> left.{(notify ? "</color>" : string.Empty)}";
|
||||
return (notify ? "<#777777>" : string.Empty) +
|
||||
(impnum == 1 ? GetString("RemainingText.Prefix.SingleImp") : GetString("RemainingText.Prefix.PluralImp")) +
|
||||
(notify ? " " : "\n") +
|
||||
(notify ? "<#ffffff>" : "<b>") +
|
||||
impnum +
|
||||
(notify ? "</color>" : "</b>") +
|
||||
" " +
|
||||
$"<#ff1919>{(impnum == 1 ? GetString("RemainingText.ImpSingle") : GetString("RemainingText.ImpPlural"))}</color>" +
|
||||
" & " +
|
||||
(notify ? "<#ffffff>" : "<b>") +
|
||||
neutralnum +
|
||||
(notify ? "</color>" : "</b>") +
|
||||
" " +
|
||||
$"<#ffab1b>{(neutralnum == 1 ? GetString("RemainingText.NKSingle") : GetString("RemainingText.NKPlural"))}</color>" +
|
||||
GetString("RemainingText.Suffix") +
|
||||
"." +
|
||||
(notify ? "</color>" : string.Empty);
|
||||
}
|
||||
public static string RemoveHtmlTagsTemplate(this string str) => Regex.Replace(str, string.Empty, string.Empty);
|
||||
public static string RemoveHtmlTags(this string str) => Regex.Replace(str, "<[^>]*?>", string.Empty);
|
||||
|
||||
@@ -11,7 +11,6 @@ using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using static TOHE.Translator;
|
||||
|
||||
|
||||
@@ -33,7 +32,9 @@ internal class ChatCommands
|
||||
|
||||
public static bool Prefix(ChatController __instance)
|
||||
{
|
||||
if (__instance.quickChatField.visible) return true;
|
||||
if (__instance.freeChatField.textArea.text == string.Empty) return false;
|
||||
if (!GameStates.IsModHost && !AmongUsClient.Instance.AmHost) return true;
|
||||
__instance.timeSinceLastMessage = 3f;
|
||||
|
||||
var text = __instance.freeChatField.textArea.text;
|
||||
|
||||
@@ -47,7 +47,7 @@ class ChatControllerUpdatePatch
|
||||
}
|
||||
}
|
||||
|
||||
public class ChatManager
|
||||
public static class ChatManager
|
||||
{
|
||||
public static bool cancel;
|
||||
private static readonly List<string> chatHistory = [];
|
||||
@@ -152,6 +152,7 @@ public class ChatManager
|
||||
|
||||
public static void SendPreviousMessagesToAll(bool realMessagesOnly = false)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost || !GameStates.IsModHost) return;
|
||||
ChatUpdatePatch.DoBlockChat = true;
|
||||
string msg = Utils.EmptyMessage();
|
||||
List<CustomRoles> roles = Enum.GetValues(typeof(CustomRoles)).Cast<CustomRoles>().Where(x => x is not CustomRoles.KB_Normal and not CustomRoles.Killer and not CustomRoles.Tasker).ToList();
|
||||
|
||||
@@ -40,7 +40,9 @@ class GameEndChecker
|
||||
//ゲーム終了時
|
||||
if (CustomWinnerHolder.WinnerTeam != CustomWinner.Default)
|
||||
{
|
||||
//カモフラージュ強制解除
|
||||
NameNotifyManager.Reset();
|
||||
NotifyRoles(ForceLoop: true);
|
||||
|
||||
Main.AllPlayerControls.Do(pc => Camouflage.RpcSetSkin(pc, ForceRevert: true, RevertToDefault: true));
|
||||
|
||||
if (reason == GameOverReason.ImpostorBySabotage && (CustomRoles.Jackal.RoleExist() || CustomRoles.Sidekick.RoleExist()) && Jackal.CanWinBySabotageWhenNoImpAlive.GetBool() && !Main.AllAlivePlayerControls.Any(x => x.GetCustomRole().IsImpostorTeam()))
|
||||
|
||||
+12
-2
@@ -101,10 +101,20 @@ internal class InnerNetClientCanBanPatch
|
||||
[HarmonyPatch(typeof(InnerNetClient), nameof(InnerNetClient.KickPlayer))]
|
||||
internal class KickPlayerPatch
|
||||
{
|
||||
public static void Prefix(InnerNetClient __instance, int clientId, bool ban)
|
||||
public static bool Prefix(InnerNetClient __instance, int clientId, bool ban)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost) return true;
|
||||
|
||||
if (AmongUsClient.Instance.ClientId == clientId)
|
||||
{
|
||||
Logger.SendInGame(string.Format("Game Attempting to {0} Host, Blocked the attempt.", ban ? "Ban" : "Kick"));
|
||||
Logger.Info("Game attempted to kick/ban host....", "KickPlayerPatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ban) BanManager.AddBanPlayer(AmongUsClient.Instance.GetRecentClient(clientId));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(ResolutionManager), nameof(ResolutionManager.SetResolution))]
|
||||
|
||||
+16
-2
@@ -580,7 +580,7 @@ class HudManagerPatch
|
||||
LowerInfoText.enabled = false;
|
||||
}
|
||||
|
||||
if (player.CanUseKillButton())
|
||||
if (player.CanUseKillButton() && !player.GetCustomRole().UsesPetInsteadOfKill())
|
||||
{
|
||||
__instance.KillButton?.ToggleVisible(player.IsAlive() && GameStates.IsInTask);
|
||||
player.Data.Role.CanUseKillButton = true;
|
||||
@@ -591,9 +591,18 @@ 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;
|
||||
if (player.PlayerId == 0 && player.inVent && GameStates.IsInTask)
|
||||
{
|
||||
__instance.ImpostorVentButton.canInteract = true;
|
||||
__instance.ImpostorVentButton.enabled = true;
|
||||
__instance.ImpostorVentButton.isCoolingDown = false;
|
||||
__instance.ImpostorVentButton.SetEnabled();
|
||||
__instance.ImpostorVentButton.currentTarget = TryMoveToVentPatch.HostVentTarget;
|
||||
__instance.ImpostorVentButton.SetTarget(TryMoveToVentPatch.HostVentTarget);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -773,6 +782,11 @@ class VentButtonDoClickPatch
|
||||
{
|
||||
var pc = PlayerControl.LocalPlayer;
|
||||
{
|
||||
if (pc.inVent)
|
||||
{
|
||||
pc.MyPhysics.RpcExitVent(TryMoveToVentPatch.HostVentTarget.Id);
|
||||
return true;
|
||||
}
|
||||
if (!pc.Is(CustomRoles.Swooper) || !pc.Is(CustomRoles.Wraith) || !pc.Is(CustomRoles.Chameleon) || pc.inVent || __instance.currentTarget == null || !pc.CanMove || !__instance.isActiveAndEnabled) return true;
|
||||
pc?.MyPhysics?.RpcEnterVent(__instance.currentTarget.Id);
|
||||
return false;
|
||||
|
||||
@@ -512,8 +512,12 @@ class IntroCutsceneDestroyPatch
|
||||
{
|
||||
if (Main.NormalOptions.MapId != 4)
|
||||
{
|
||||
Main.AllPlayerControls.Do(pc => pc.RpcResetAbilityCooldown());
|
||||
Main.AllPlayerControls.Do(pc => pc.AddAbilityCD());
|
||||
foreach (var pc in Main.AllAlivePlayerControls)
|
||||
{
|
||||
pc.RpcResetAbilityCooldown();
|
||||
if (pc.GetCustomRole().UsesPetInsteadOfKill()) pc.AddAbilityCD(10);
|
||||
else pc.AddAbilityCD();
|
||||
}
|
||||
if (Options.StartingKillCooldown.GetInt() != 10 && Options.StartingKillCooldown.GetInt() > 0)
|
||||
{
|
||||
_ = new LateTask(() =>
|
||||
|
||||
+93
-44
@@ -87,40 +87,36 @@ class CheckForEndVotingPatch
|
||||
{
|
||||
switch (pc.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Divinator:
|
||||
case CustomRoles.Divinator when !Divinator.CancelVote.GetBool():
|
||||
Divinator.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Oracle:
|
||||
case CustomRoles.Oracle when !Oracle.CancelVote.GetBool():
|
||||
Oracle.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Eraser:
|
||||
case CustomRoles.Eraser when !Eraser.CancelVote.GetBool():
|
||||
Eraser.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Tether:
|
||||
case CustomRoles.Tether when !Tether.CancelVote.GetBool():
|
||||
Tether.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Ricochet:
|
||||
case CustomRoles.Ricochet when !Ricochet.CancelVote.GetBool():
|
||||
Ricochet.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Cleanser:
|
||||
case CustomRoles.Cleanser when !Cleanser.CancelVote.GetBool():
|
||||
Cleanser.OnVote(pc, voteTarget);
|
||||
break;
|
||||
//case CustomRoles.Jailor:
|
||||
// Jailor.OnVote(pc, voteTarget);
|
||||
// break;
|
||||
case CustomRoles.NiceEraser:
|
||||
case CustomRoles.NiceEraser when !NiceEraser.CancelVote.GetBool():
|
||||
NiceEraser.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Tracker:
|
||||
case CustomRoles.Tracker when !Tracker.CancelVote.GetBool():
|
||||
Tracker.OnVote(pc, voteTarget);
|
||||
break;
|
||||
case CustomRoles.Godfather:
|
||||
if (pc == null || voteTarget == null) break;
|
||||
case CustomRoles.Godfather when !Options.GodfatherCancelVote.GetBool():
|
||||
Main.GodfatherTarget = voteTarget.PlayerId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (pc.GetCustomRole() == CustomRoles.Godfather) Main.GodfatherTarget = byte.MaxValue;
|
||||
else if (pc.Is(CustomRoles.Godfather)) Main.GodfatherTarget = byte.MaxValue;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < __instance.playerStates.Count; i++)
|
||||
@@ -408,19 +404,16 @@ class CheckForEndVotingPatch
|
||||
var role = GetString(exiledPlayer.GetCustomRole().ToString());
|
||||
var crole = exiledPlayer.GetCustomRole();
|
||||
var coloredRole = Utils.GetDisplayRoleName(exileId, true);
|
||||
if (Options.ConfirmEgoistOnEject.GetBool() && player.Is(CustomRoles.Egoist))
|
||||
coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Egoist), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
// if (Options.ConfirmSidekickOnEject.GetBool() && player.Is(CustomRoles.Sidekick))
|
||||
// coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Sidekick), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.ConfirmLoversOnEject.GetBool() && player.Is(CustomRoles.Lovers))
|
||||
coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.RascalAppearAsMadmate.GetBool() && player.Is(CustomRoles.Rascal))
|
||||
coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetRoleString("Mad-") + coloredRole.RemoveHtmlTags());
|
||||
|
||||
if (Options.ConfirmEgoistOnEject.GetBool() && player.Is(CustomRoles.Egoist)) coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Egoist), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.ConfirmLoversOnEject.GetBool() && player.Is(CustomRoles.Lovers)) coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Lovers), GetRoleString("Temp.Blank") + coloredRole.RemoveHtmlTags());
|
||||
if (Options.RascalAppearAsMadmate.GetBool() && player.Is(CustomRoles.Rascal)) coloredRole = Utils.ColorString(Utils.GetRoleColor(CustomRoles.Madmate), GetRoleString("Mad-") + coloredRole.RemoveHtmlTags());
|
||||
|
||||
var name = string.Empty;
|
||||
int impnum = 0;
|
||||
int neutralnum = 0;
|
||||
|
||||
if (CustomRolesHelper.RoleExist(CustomRoles.Bard))
|
||||
if (CustomRoles.Bard.RoleExist())
|
||||
{
|
||||
Main.BardCreations++;
|
||||
try { name = ModUpdater.Get("https://v1.hitokoto.cn/?encode=text"); }
|
||||
@@ -500,18 +493,18 @@ class CheckForEndVotingPatch
|
||||
case (0, 0): // Crewmates win
|
||||
name += GetString("GG");
|
||||
break;
|
||||
case ( > 0, > 0): // Both imps and neutrals remain
|
||||
case (> 0, > 0): // Both imps and neutrals remain
|
||||
name += impnum switch
|
||||
{
|
||||
1 => "1 <color=#ff1919>Impostor</color> <color=#777777>&</color> ",
|
||||
2 => "2 <color=#ff1919>Impostors</color> <color=#777777>&</color> ",
|
||||
3 => "3 <color=#ff1919>Impostors</color> <color=#777777>&</color> ",
|
||||
1 => $"1 <color=#ff1919>{GetString("RemainingText.ImpSingle")}</color> <color=#777777>&</color> ",
|
||||
2 => $"2 <color=#ff1919>{GetString("RemainingText.ImpPlural")}</color> <color=#777777>&</color> ",
|
||||
3 => $"3 <color=#ff1919>{GetString("RemainingText.ImpPlural")}</color> <color=#777777>&</color> ",
|
||||
_ => string.Empty,
|
||||
};
|
||||
if (neutralnum == 1) name += "1 <color=#ffab1b>Neutral</color> <color=#777777>remains.</color>";
|
||||
else name += $"{neutralnum} <color=#ffab1b>Neutrals</color> <color=#777777>remain.</color>";
|
||||
if (neutralnum == 1) name += $"1 <color=#ffab1b>{GetString("RemainingText.NKSingle")}</color> <color=#777777>{GetString("RemainingText.EjectionSuffix.NKSingle")}</color>";
|
||||
else name += $"{neutralnum} <color=#ffab1b>{GetString("RemainingText.NKPlural")}</color> <color=#777777>{GetString("RemainingText.EjectionSuffix.NKPlural")}</color>";
|
||||
break;
|
||||
case ( > 0, 0): // Only imps remain
|
||||
case (> 0, 0): // Only imps remain
|
||||
name += impnum switch
|
||||
{
|
||||
1 => GetString("OneImpRemain"),
|
||||
@@ -1336,11 +1329,9 @@ class MeetingHudOnDestroyPatch
|
||||
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CastVote))]
|
||||
class MeetingHudCastVotePatch
|
||||
{
|
||||
public static bool Prefix()
|
||||
{
|
||||
return true; // return false to use the vote as a trigger
|
||||
}
|
||||
public static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
private static readonly Dictionary<byte, (MeetingHud MEETING_HUD, PlayerVoteArea SOURCE_PLAYER_VOTE_AREA, PlayerControl SOURCE_PLAYER)> ShouldCancelVoteList = [];
|
||||
|
||||
public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
{
|
||||
PlayerVoteArea pva_src = null;
|
||||
PlayerVoteArea pva_target = null;
|
||||
@@ -1353,7 +1344,7 @@ class MeetingHudCastVotePatch
|
||||
if (pva_src == null)
|
||||
{
|
||||
Logger.Error("Src PlayerVoteArea not found", "MeetingHudCastVotePatch.Prefix");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (pva_target == null)
|
||||
{
|
||||
@@ -1365,7 +1356,7 @@ class MeetingHudCastVotePatch
|
||||
if (pc_src == null)
|
||||
{
|
||||
Logger.Error("Src PlayerControl is null", "MeetingHudCastVotePatch.Prefix");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (pc_target == null)
|
||||
{
|
||||
@@ -1373,21 +1364,79 @@ class MeetingHudCastVotePatch
|
||||
isSkip = true;
|
||||
}
|
||||
|
||||
Logger.Info($"{pc_src.GetNameWithRole().RemoveHtmlTags()} => {(isSkip ? "Skip" : pc_target.GetNameWithRole().RemoveHtmlTags())}", "Vote");
|
||||
bool isVoteCanceled = false;
|
||||
|
||||
//pva_src.UnsetVote(); // Uncomment to use the vote as a trigger
|
||||
//__instance.RpcClearVote(pc_src.GetClientId()); // Uncomment to use the vote as a trigger
|
||||
if (!Main.DontCancelVoteList.Contains(srcPlayerId))
|
||||
{
|
||||
if (!isSkip)
|
||||
{
|
||||
switch (pc_src.GetCustomRole())
|
||||
{
|
||||
case CustomRoles.Divinator when Divinator.CancelVote.GetBool():
|
||||
if (Divinator.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Oracle when Oracle.CancelVote.GetBool():
|
||||
if (Oracle.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Eraser when Eraser.CancelVote.GetBool():
|
||||
if (Eraser.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Tether when Tether.CancelVote.GetBool():
|
||||
if (Tether.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Ricochet when Ricochet.CancelVote.GetBool():
|
||||
if (Ricochet.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Cleanser when Cleanser.CancelVote.GetBool():
|
||||
if (Cleanser.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.NiceEraser when NiceEraser.CancelVote.GetBool():
|
||||
if (NiceEraser.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Tracker when Tracker.CancelVote.GetBool():
|
||||
if (Tracker.OnVote(pc_src, pc_target)) CancelVote();
|
||||
break;
|
||||
case CustomRoles.Godfather when Options.GodfatherCancelVote.GetBool():
|
||||
Main.GodfatherTarget = pc_target.PlayerId;
|
||||
CancelVote();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CancelVote()
|
||||
{
|
||||
ShouldCancelVoteList.TryAdd(srcPlayerId, (__instance, pva_src, pc_src));
|
||||
isVoteCanceled = true;
|
||||
}
|
||||
|
||||
Logger.Info($"{pc_src.GetNameWithRole().RemoveHtmlTags()} => {(isSkip ? "Skip" : pc_target.GetNameWithRole().RemoveHtmlTags())}{(isVoteCanceled ? " (Canceled)" : string.Empty)}", "Vote");
|
||||
|
||||
return isSkip || !isVoteCanceled; // return false to use the vote as a trigger; skips and invalid votes are never canceled
|
||||
}
|
||||
public static void Postfix([HarmonyArgument(0)] byte srcPlayerId)
|
||||
{
|
||||
if (!ShouldCancelVoteList.TryGetValue(srcPlayerId, out var info)) return;
|
||||
|
||||
MeetingHud __instance = info.MEETING_HUD;
|
||||
PlayerVoteArea pva_src = info.SOURCE_PLAYER_VOTE_AREA;
|
||||
PlayerControl pc_src = info.SOURCE_PLAYER;
|
||||
|
||||
try { pva_src.UnsetVote(); } catch { }
|
||||
__instance.RpcClearVote(pc_src.GetClientId());
|
||||
|
||||
ShouldCancelVoteList.Remove(srcPlayerId);
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.CmdCastVote))]
|
||||
class MeetingHudCmdCastVotePatch
|
||||
{
|
||||
public static bool Prefix()
|
||||
public static bool Prefix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
{
|
||||
return MeetingHudCastVotePatch.Prefix();
|
||||
return MeetingHudCastVotePatch.Prefix(__instance, srcPlayerId, suspectPlayerId);
|
||||
}
|
||||
public static void Postfix(MeetingHud __instance, [HarmonyArgument(0)] byte srcPlayerId, [HarmonyArgument(1)] byte suspectPlayerId)
|
||||
public static void Postfix([HarmonyArgument(0)] byte srcPlayerId)
|
||||
{
|
||||
MeetingHudCastVotePatch.Postfix(__instance, srcPlayerId, suspectPlayerId);
|
||||
MeetingHudCastVotePatch.Postfix(srcPlayerId);
|
||||
}
|
||||
}
|
||||
+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.IsImpostor() ? 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]);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -7,6 +8,7 @@ using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using TOHE.Roles.Impostor;
|
||||
using TOHE.Roles.Neutral;
|
||||
using UnityEngine;
|
||||
using static TOHE.Translator;
|
||||
|
||||
namespace TOHE;
|
||||
@@ -98,6 +100,11 @@ class ExternalRpcPetPatch
|
||||
|
||||
PlayerControl[] AllAlivePlayers = Main.AllAlivePlayerControls;
|
||||
|
||||
bool hasKillTarget = false;
|
||||
PlayerControl target = SelectKillButtonTarget(pc);
|
||||
if (target != null) hasKillTarget = true;
|
||||
if (!pc.CanUseKillButton()) hasKillTarget = false;
|
||||
|
||||
switch (pc.GetCustomRole())
|
||||
{
|
||||
// Crewmates
|
||||
@@ -304,6 +311,75 @@ class ExternalRpcPetPatch
|
||||
pc.Notify(sb.ToString());
|
||||
break;
|
||||
|
||||
case CustomRoles.Gaulois when hasKillTarget:
|
||||
Gaulois.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Aid when hasKillTarget:
|
||||
Aid.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Escort when hasKillTarget:
|
||||
Escort.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.DonutDelivery when hasKillTarget:
|
||||
DonutDelivery.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Analyzer when hasKillTarget:
|
||||
Analyzer.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Jailor when hasKillTarget:
|
||||
Jailor.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Sheriff when hasKillTarget:
|
||||
if (Sheriff.OnCheckMurder(pc, target)) pc.RpcCheckAndMurder(target);
|
||||
else pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.SwordsMan when hasKillTarget:
|
||||
if (SwordsMan.OnCheckMurder(pc)) if (!pc.RpcCheckAndMurder(target)) pc.AddKCDAsAbilityCD();
|
||||
else pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Witness when hasKillTarget:
|
||||
if (Main.AllKillers.ContainsKey(target.PlayerId))
|
||||
pc.Notify(GetString("WitnessFoundKiller"));
|
||||
else pc.Notify(GetString("WitnessFoundInnocent"));
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Medic when hasKillTarget:
|
||||
Medic.OnCheckMurderFormedicaler(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Monarch when hasKillTarget:
|
||||
Monarch.OnCheckMurder(pc, target);
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.CopyCat when hasKillTarget:
|
||||
if (CopyCat.OnCheckMurder(pc, target)) if (!pc.RpcCheckAndMurder(target)) pc.AddKCDAsAbilityCD();
|
||||
pc.AddKCDAsAbilityCD();
|
||||
break;
|
||||
case CustomRoles.Farseer when hasKillTarget:
|
||||
pc.AddAbilityCD(Farseer.FarseerRevealTime.GetInt());
|
||||
if (!Main.isRevealed[(pc.PlayerId, target.PlayerId)] && !Main.FarseerTimer.ContainsKey(pc.PlayerId))
|
||||
{
|
||||
Main.FarseerTimer.TryAdd(pc.PlayerId, (target, 0f));
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: target, ForceLoop: true);
|
||||
RPC.SetCurrentRevealTarget(pc.PlayerId, target.PlayerId);
|
||||
}
|
||||
break;
|
||||
case CustomRoles.Deputy when hasKillTarget:
|
||||
Deputy.OnCheckMurder(pc, target);
|
||||
break;
|
||||
case CustomRoles.Admirer when hasKillTarget:
|
||||
Admirer.OnCheckMurder(pc, target);
|
||||
break;
|
||||
case CustomRoles.Crusader when hasKillTarget:
|
||||
Crusader.OnCheckMurder(pc, target);
|
||||
break;
|
||||
|
||||
// Impostors
|
||||
|
||||
case CustomRoles.Sniper:
|
||||
@@ -326,7 +402,7 @@ class ExternalRpcPetPatch
|
||||
if (!Options.WarlockCanKillAllies.GetBool() && p.GetCustomRole().IsImpostor()) continue;
|
||||
if (p.Is(CustomRoles.Pestilence)) continue;
|
||||
if (Pelican.IsEaten(p.PlayerId) || Medic.ProtectList.Contains(p.PlayerId)) continue;
|
||||
dis = UnityEngine.Vector2.Distance(cppos, p.Pos());
|
||||
dis = Vector2.Distance(cppos, p.Pos());
|
||||
cpdistance.Add(p, dis);
|
||||
Logger.Info($"{p?.Data?.PlayerName}'s distance: {dis}", "Warlock");
|
||||
}
|
||||
@@ -391,7 +467,7 @@ class ExternalRpcPetPatch
|
||||
{
|
||||
if (!tg.IsModClient()) tg.KillFlash();
|
||||
var pos = pc.Pos();
|
||||
var dis = UnityEngine.Vector2.Distance(pos, tg.Pos());
|
||||
var dis = Vector2.Distance(pos, tg.Pos());
|
||||
|
||||
if (!tg.IsAlive() || Pelican.IsEaten(tg.PlayerId) || Medic.ProtectList.Contains(tg.PlayerId) || (tg.Is(CustomRoleTypes.Impostor) && Options.ImpostorsSurviveBombs.GetBool()) || tg.inVent || tg.Is(CustomRoles.Pestilence)) continue;
|
||||
if (dis > Options.BomberRadius.GetFloat()) continue;
|
||||
@@ -416,7 +492,7 @@ class ExternalRpcPetPatch
|
||||
{
|
||||
if (!tg.IsModClient()) tg.KillFlash();
|
||||
var pos = pc.Pos();
|
||||
var dis = UnityEngine.Vector2.Distance(pos, tg.Pos());
|
||||
var dis = Vector2.Distance(pos, tg.Pos());
|
||||
|
||||
if (!tg.IsAlive() || Pelican.IsEaten(tg.PlayerId) || Medic.ProtectList.Contains(tg.PlayerId) || tg.inVent || tg.Is(CustomRoles.Pestilence)) continue;
|
||||
if (dis > Options.NukeRadius.GetFloat()) continue;
|
||||
@@ -469,8 +545,15 @@ class ExternalRpcPetPatch
|
||||
break;
|
||||
}
|
||||
|
||||
if (pc.Is(CustomRoles.Sniper) && Sniper.IsAim[pc.PlayerId]) return;
|
||||
if (pc.HasAbilityCD() || (pc.Is(CustomRoles.Sniper) && Sniper.IsAim[pc.PlayerId])) return;
|
||||
|
||||
pc.AddAbilityCD();
|
||||
}
|
||||
|
||||
public static PlayerControl SelectKillButtonTarget(PlayerControl pc)
|
||||
{
|
||||
var players = pc.GetPlayersInAbilityRangeSorted();
|
||||
var target = players.Count == 0 ? null : players[0];
|
||||
return target;
|
||||
}
|
||||
}
|
||||
@@ -1238,12 +1238,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#####")));
|
||||
|
||||
@@ -1947,6 +1941,7 @@ class ReportDeadBodyPatch
|
||||
{
|
||||
Damocles.OnReport();
|
||||
}
|
||||
Damocles.OnMeetingStart();
|
||||
|
||||
if (player.Is(CustomRoles.Stressed))
|
||||
{
|
||||
@@ -2239,21 +2234,19 @@ class FixedUpdatePatch
|
||||
{
|
||||
if (Main.AbilityCD.TryGetValue(playerId, out var timer))
|
||||
{
|
||||
if (timer.START_TIMESTAMP + timer.TOTALCD < GetTimeStamp())
|
||||
if (timer.START_TIMESTAMP + timer.TOTALCD < GetTimeStamp() || !player.IsAlive())
|
||||
{
|
||||
Main.AbilityCD.Remove(playerId);
|
||||
}
|
||||
if (!player.IsModClient()) NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
}
|
||||
|
||||
if (Main.AbilityCD.ContainsKey(playerId) && !player.IsModClient()) NotifyRoles(SpecifySeer: player, SpecifyTarget: player);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lowLoad)
|
||||
{
|
||||
YinYanger.OnFixedUpdate();
|
||||
Duellist.OnFixedUpdate();
|
||||
if (!lowLoad)
|
||||
{
|
||||
YinYanger.OnFixedUpdate();
|
||||
Duellist.OnFixedUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
if (GameStates.IsInTask && Agitater.IsEnable && Agitater.AgitaterHasBombed && Agitater.CurrentBombedPlayer == playerId)
|
||||
@@ -3124,6 +3117,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($"{__instance.name} => {otherVent.name}", "HostVentTarget");
|
||||
HostVentTarget = otherVent;
|
||||
}
|
||||
}
|
||||
}
|
||||
[HarmonyPatch(typeof(Vent), nameof(Vent.ExitVent))]
|
||||
class ExitVentPatch
|
||||
{
|
||||
@@ -3131,6 +3137,12 @@ class ExitVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "ExitVent");
|
||||
|
||||
if (pc.PlayerId == 0)
|
||||
{
|
||||
Logger.Info(__instance.name, "HostVentTarget");
|
||||
TryMoveToVentPatch.HostVentTarget = __instance;
|
||||
}
|
||||
|
||||
Drainer.OnAnyoneExitVent(pc, __instance.Id);
|
||||
}
|
||||
}
|
||||
@@ -3141,6 +3153,12 @@ class EnterVentPatch
|
||||
{
|
||||
Logger.Info($" {pc.GetNameWithRole()}, Vent ID: {__instance.Id} ({__instance.name})", "EnterVent");
|
||||
|
||||
if (pc.PlayerId == 0)
|
||||
{
|
||||
Logger.Info(__instance.name, "HostVentTarget");
|
||||
TryMoveToVentPatch.HostVentTarget = __instance;
|
||||
}
|
||||
|
||||
Drainer.OnAnyoneEnterVent(pc, __instance);
|
||||
Analyzer.OnAnyoneEnterVent(pc);
|
||||
|
||||
@@ -3781,3 +3799,27 @@ class PlayerControlSetRolePatch
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetRole))]
|
||||
class PlayerControlLocalSetRolePatch
|
||||
{
|
||||
public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] RoleTypes role)
|
||||
{
|
||||
if (!AmongUsClient.Instance.AmHost && !GameStates.IsModHost)
|
||||
{
|
||||
var moddedRole = role switch
|
||||
{
|
||||
RoleTypes.Impostor => CustomRoles.ImpostorTOHE,
|
||||
RoleTypes.Shapeshifter => CustomRoles.ShapeshifterTOHE,
|
||||
RoleTypes.Crewmate => CustomRoles.CrewmateTOHE,
|
||||
RoleTypes.Engineer => CustomRoles.EngineerTOHE,
|
||||
RoleTypes.Scientist => CustomRoles.ScientistTOHE,
|
||||
_ => CustomRoles.NotAssigned,
|
||||
};
|
||||
if (moddedRole != CustomRoles.NotAssigned)
|
||||
{
|
||||
Main.PlayerStates[__instance.PlayerId].SetMainRole(moddedRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using AmongUs.GameOptions;
|
||||
using HarmonyLib;
|
||||
using Hazel;
|
||||
using InnerNet;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using TOHE.Modules;
|
||||
using TOHE.Roles.Crewmate;
|
||||
@@ -147,6 +146,7 @@ class OnPlayerLeftPatch
|
||||
Main.PlayerStates[data.Character.PlayerId].deathReason = PlayerState.DeathReason.Disconnected;
|
||||
Main.PlayerStates[data.Character.PlayerId].SetDead();
|
||||
}
|
||||
NameNotifyManager.Notice.Remove(data.Character.PlayerId);
|
||||
AntiBlackout.OnDisconnect(data.Character.Data);
|
||||
PlayerGameOptionsSender.RemoveSender(data.Character);
|
||||
}
|
||||
|
||||
+37
-28
@@ -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;
|
||||
}
|
||||
|
||||
@@ -160,37 +162,44 @@ 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();
|
||||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||||
}
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
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();
|
||||
if (player.Is(CustomRoles.Stressed) && Stressed.countRepairSabotage) Stressed.OnRepairSabotage(player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static void CheckAndOpenDoorsRange(ShipStatus __instance, int amount, int min, int max)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TOHE.Patches;
|
||||
|
||||
|
||||
+535
-523
File diff suppressed because it is too large.
Load diff
@@ -75,6 +75,8 @@ curtsyboth#4114,1f9bbee79,龙傲天》//MalumMenu
|
||||
shyfortune#7692,526f950da,B站日常无语的无语君 //AUM
|
||||
0a4f7e294,Melani //no friendcode hacker
|
||||
sprysign#5596,064c15bb6,Onion
|
||||
musksolid#9543,troutdusky#6471,a9b3569f5,c40cfe547,caf7d691c,covid20 //Spoofed MalumMenu
|
||||
errantlug#6514,79f0cbe07,Kerbpoetic //AUM
|
||||
|
||||
## Griefer
|
||||
setmolar#4374,藏族顶针
|
||||
|
||||
+22
-3
@@ -1198,6 +1198,7 @@
|
||||
"Kick","踢出","Kick","Кикнуть","踢出","踢出"
|
||||
"NoticeMe","通知我","Notify me","Уведомить меня","通知我","通知我"
|
||||
"NoticeEveryone","通知所有人(除了它)","Notify everyone","Уведомить всех","通知所有人(除了他)","通知所有人(除了它)"
|
||||
"OnlyCancel","","Cancel Action Only","","",""
|
||||
"CheatResponses","检测到外挂时","When a cheating player is found","Когда обнаружен взлом","檢測到外掛時","检测到外挂时"
|
||||
"NeutralRoleWinTogether","同种职业<color=#7f8c8d>中立</color>玩家共同胜利","<color=#7f8c8d>Neutrals</color> win together","<color=#7f8c8d>Нейтралы</color> побеждают вместе","同種職業的<color=#7f8c8d>中立</color>玩家共同獲勝","同种职业<color=#7f8c8d>中立</color>玩家共同胜利"
|
||||
"NeutralWinTogether","全体<color=#7f8c8d>中立</color>阵营玩家共同胜利","All <color=#7f8c8d>Neutrals</color> win together","<color=#7f8c8d>Нейтралы</color> побеждают вместе","全體<color=#7f8c8d>中立</color>陣營玩家共同獲勝","全体<color=#7f8c8d>中立</color>阵营玩家共同胜利"
|
||||
@@ -1223,6 +1224,17 @@
|
||||
"ArsonistMinPlayersToIgnite","","Minimum Doused Players required to Ignite","","",""
|
||||
"ArsonistMaxPlayersToIgnite","","Maximum Amount of Doused Players at once","","",""
|
||||
|
||||
"## Remaining Killers Text / Confirm Ejections Text"
|
||||
"RemainingText.Prefix.SingleImp","","There is","","",""
|
||||
"RemainingText.Prefix.PluralImp","","There are","","",""
|
||||
"RemainingText.ImpSingle","","Impostor","","",""
|
||||
"RemainingText.ImpPlural","","Impostors","","",""
|
||||
"RemainingText.NKSingle","","Neutral Killer","","",""
|
||||
"RemainingText.NKPlural","","Neutral Killers","","",""
|
||||
"RemainingText.Suffix","","left","","",""
|
||||
"RemainingText.EjectionSuffix.NKSingle","","remains.","","",""
|
||||
"RemainingText.EjectionSuffix.NKPlural","","remain.","","",""
|
||||
|
||||
"## 详细设定 / Advanced Settings"
|
||||
"Cooldown","冷却时间","Cooldown","Откат","冷卻時間","冷却时间"
|
||||
"KillCooldown","击杀冷却时间","Kill Cooldown","Откат убийства","殺人冷卻時間","击杀冷却时间"
|
||||
@@ -1439,9 +1451,11 @@
|
||||
"NotifyGodAlive","如果神存活则在会议上通知所有人","Inform players at meetings that God is still alive","Сообщать игрокам на встрече что Дьявол ещё жив","若神存活則在會議上通知所有人","如果神存活则在会议上通知所有人"
|
||||
"TransporterTeleportMax","传送次数上限","Max number of teleports","Максимальное колличество телепортов","傳送次數上限","传送次数上限"
|
||||
"TriggerKill","击杀","Kill","Убийство","殺死","击杀"
|
||||
"UsePetInsteadOfKillButton","","Use Pet Button As Kill Button","","",""
|
||||
"UsePets","","Use Pet button instead of Vent / Shapeshift","","",""
|
||||
"PetToAssign","","Pet to Assign to Everyone","","",""
|
||||
"UseVoteCancelling","","Use Vote Cancelling Method instead of Commands","","",""
|
||||
"UseVoteCancellingAfterVote","","Can Vote Normally After Using Ability (Vote)","","",""
|
||||
"AbilityOnCooldown","","<color=#ffff00>Ability on cooldown!</color>","","",""
|
||||
"KillCooldownOnStrangle","","Kill Cooldown after Strangling","","",""
|
||||
"CDPT","","<color=#00ffa5>CD:</color> <color=#ffffff><b>{0}</b>s</color>","","",""
|
||||
@@ -2859,19 +2873,19 @@
|
||||
"EnigmaClueLevel2","","The Killer's Level is below 50!","","",""
|
||||
"EnigmaClueLevel3","","The Killer's Level is between {0} and {1}!","","",""
|
||||
"EnigmaClueLevel4","","The Killer's Level is {0}!","","",""
|
||||
"EnigmaClueFriendCode","","The Killer's Friendcode is {0}!","","",""
|
||||
"EnigmaClueFriendCode","","The Killer's Friend Code is {0}!","","",""
|
||||
"EnigmaClueHatTitle","","Enigma Hat Clue!","","",""
|
||||
"EnigmaClueVisorTitle","","Enigma Visor Clue!","","",""
|
||||
"EnigmaClueSkinTitle","","Enigma Skin Clue!","","",""
|
||||
"EnigmaCluePetTitle","","Enigma Pet Clue!","","",""
|
||||
"EnigmaClueNameTitle","","Enigma Name Clue!","","",""
|
||||
"EnigmaClueNameLengthTitle","","Enigma Name lenght Clue!","","",""
|
||||
"EnigmaClueNameLengthTitle","","Enigma Name Length Clue!","","",""
|
||||
"EnigmaClueColorTitle","","Enigma Color Clue!","","",""
|
||||
"EnigmaClueLocationTitle","","Enigma Location Clue!","","",""
|
||||
"EnigmaClueStatusTitle","","Enigma Status Clue!","","",""
|
||||
"EnigmaClueRoleTitle","","Enigma Role Clue!","","",""
|
||||
"EnigmaClueLevelTitle","","Enigma Level Clue!","","",""
|
||||
"EnigmaClueFriendCodeTitle","","Enigma Friendcode Clue!","","",""
|
||||
"EnigmaClueFriendCodeTitle","","Enigma Friend Code Clue!","","",""
|
||||
"EnigmaClueTitle","","Enigma Clue!","","",""
|
||||
|
||||
"## Plague Doctor"
|
||||
@@ -3033,6 +3047,10 @@
|
||||
"WeaponMasterInfoLong","","(Neutral):\nAs the Weapon Master, you can cycle between your weapons by petting your pet/calling a sabotage.\n\nThe Sword weapon is a normal kill method.\n\nThe Axe weapon kills everyone in a certain radius when you make a kill. You have a higher kill cooldown while using this weapon.\n\nThe Lance weapon sets your kill range to the maximum, and you don't lunge toward your kills. You can't vent while using this weapon.\n\nWhile using your Shield, you can survive an attack once. You can't kill while using your shield.","","",""
|
||||
"WMRadius","","Axe Mode Death Radius","","",""
|
||||
"WMShieldAlreadyUsed","","Your shield was already used","","",""
|
||||
"Sword","","Sword","","",""
|
||||
"Axe","","Axe","","",""
|
||||
"Lance","","Lance","","",""
|
||||
"Shield","","Shield","","",""
|
||||
|
||||
"## Eclipse"
|
||||
"Eclipse","","Eclipse","","",""
|
||||
@@ -3316,6 +3334,7 @@
|
||||
"FFA_TargetIsShielded","","<color=#ffff00>The player you tried to kill is shielded!</color>","","",""
|
||||
"FFA_ShieldIsOneTimeUse","","Shields break after 1 kill attempt","","",""
|
||||
"FFA_ShieldBroken","","<color=#ffff00>Someone tried to kill you, your shield is now broken!</color>","","",""
|
||||
"FFA_ChatDuringGame","","Chat During Game","","",""
|
||||
"FFAChatMessageNotify","","[<color=#00ffff>Chat</color>] <color=#00ffa5>{0}:</color> {1}","","",""
|
||||
"Killer","","FREE FOR ALL","","",""
|
||||
"KillerInfo","","Kill Everyone to Win","","",""
|
||||
|
||||
|
Can't render this file because it is too large.
|
@@ -54,7 +54,12 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
|
||||
public static void Update(PlayerControl pc)
|
||||
{
|
||||
if (lastUpdate >= GetTimeStamp() || !GameStates.IsInTask || !pc.IsAlive()) return;
|
||||
if (lastUpdate >= GetTimeStamp() || !GameStates.IsInTask || pc == null) return;
|
||||
if (!pc.IsAlive())
|
||||
{
|
||||
Main.PlayerStates[pc.PlayerId].RemoveSubRole(CustomRoles.Damocles);
|
||||
return;
|
||||
}
|
||||
lastUpdate = GetTimeStamp();
|
||||
|
||||
Timer--;
|
||||
@@ -65,7 +70,7 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
pc.Suicide();
|
||||
}
|
||||
|
||||
if (pc.IsModClient() && pc.PlayerId != 0) SendRPC();
|
||||
if (pc.IsNonHostModClient()) SendRPC();
|
||||
NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
}
|
||||
|
||||
@@ -111,10 +116,14 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
PreviouslyEnteredVents.Clear();
|
||||
|
||||
Timer += TimeAfterMeeting;
|
||||
Timer += 9;
|
||||
countRepairSabotage = true;
|
||||
}
|
||||
|
||||
public static void OnMeetingStart()
|
||||
{
|
||||
Timer += 9;
|
||||
}
|
||||
|
||||
public static void OnCrewmateEjected()
|
||||
{
|
||||
Timer = (int)Math.Round(Timer * 1.3);
|
||||
@@ -142,4 +151,4 @@ namespace TOHE.Roles.AddOns.Impostor
|
||||
|
||||
public static string GetProgressText() => string.Format(GetString("DamoclesTimeLeft"), Timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,14 +13,19 @@ public static class Admirer
|
||||
|
||||
public static OptionItem AdmireCooldown;
|
||||
public static OptionItem KnowTargetRole;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int AdmireLimit;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Admirer, 1);
|
||||
AdmireCooldown = FloatOptionItem.Create(Id + 10, "AdmireCooldown", new(1f, 180f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Admirer])
|
||||
AdmireCooldown = FloatOptionItem.Create(Id + 10, "AdmireCooldown", new(1f, 180f, 1f), 15f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Admirer])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
KnowTargetRole = BooleanOptionItem.Create(Id + 13, "AdmirerKnowTargetRole", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Admirer]);
|
||||
KnowTargetRole = BooleanOptionItem.Create(Id + 13, "AdmirerKnowTargetRole", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Admirer]);
|
||||
UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Admirer);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -32,7 +37,7 @@ public static class Admirer
|
||||
playerIdList.Add(playerId);
|
||||
AdmireLimit = 1;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
+10
-6
@@ -2,7 +2,6 @@ namespace TOHE.Roles.Crewmate
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
@@ -18,16 +17,21 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem AidDur;
|
||||
public static OptionItem AidCD;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Aid);
|
||||
AidCD = FloatOptionItem.Create(Id + 10, "AidCD", new(0f, 60f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
AidCD = FloatOptionItem.Create(Id + 10, "AidCD", new(0f, 60f, 1f), 15f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
AidDur = FloatOptionItem.Create(Id + 11, "AidDur", new(0f, 60f, 1f), 10f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
AidDur = FloatOptionItem.Create(Id + 11, "AidDur", new(0f, 60f, 1f), 10f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Aid])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Aid);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -40,7 +44,7 @@ namespace TOHE.Roles.Crewmate
|
||||
playerIdList.Add(playerId);
|
||||
UseLimit.Add(playerId, UseLimitOpt.GetInt());
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem SeeKillCount;
|
||||
private static OptionItem SeeVentCount;
|
||||
private static OptionItem SeeRoleBasis;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
private static readonly Dictionary<string, string> replacementDict = new() { { "Analyze", ColorString(GetRoleColor(CustomRoles.Analyzer), "Analyze") } };
|
||||
|
||||
@@ -45,6 +46,7 @@ namespace TOHE.Roles.Crewmate
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
SeeRoleBasis = BooleanOptionItem.Create(Id + 15, "AnalyzerSeeRoleBasis", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
UsePet = CreatePetUseSetting(Id + 16, CustomRoles.Analyzer);
|
||||
}
|
||||
|
||||
public static bool CanUseKillButton => CurrentTarget.ID == byte.MaxValue && UseLimit > 0;
|
||||
@@ -85,7 +87,7 @@ namespace TOHE.Roles.Crewmate
|
||||
playerId = id;
|
||||
UseLimit = UseLimitOpt.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(id))
|
||||
Main.ResetCamPlayerList.Add(id);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
{
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
|
||||
@@ -16,6 +16,7 @@ public static class Cleanser
|
||||
|
||||
public static OptionItem CleanserUsesOpt;
|
||||
public static OptionItem CleansedCanGetAddon;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -23,7 +24,7 @@ public static class Cleanser
|
||||
CleanserUsesOpt = IntegerOptionItem.Create(Id + 10, "MaxCleanserUses", new(1, 14, 1), 3, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Cleanser])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CleansedCanGetAddon = BooleanOptionItem.Create(Id + 11, "CleansedCanGetAddon", false, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Cleanser]);
|
||||
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 12, CustomRoles.Cleanser, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -73,18 +74,18 @@ public static class Cleanser
|
||||
CleanserUses.Add(CleanserId, 0);
|
||||
}
|
||||
|
||||
public static void OnVote(PlayerControl voter, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl voter, PlayerControl target)
|
||||
{
|
||||
if (!voter.Is(CustomRoles.Cleanser)) return;
|
||||
if (DidVote[voter.PlayerId]) return;
|
||||
if (!voter.Is(CustomRoles.Cleanser)) return false;
|
||||
if (DidVote[voter.PlayerId] || Main.DontCancelVoteList.Contains(voter.PlayerId)) return false;
|
||||
DidVote[voter.PlayerId] = true;
|
||||
if (CleanserUses[voter.PlayerId] >= CleanserUsesOpt.GetInt()) return;
|
||||
if (CleanserUses[voter.PlayerId] >= CleanserUsesOpt.GetInt()) return false;
|
||||
if (target.PlayerId == voter.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("CleanserRemoveSelf"), voter.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (CleanserTarget[voter.PlayerId] != byte.MaxValue) return;
|
||||
if (CleanserTarget[voter.PlayerId] != byte.MaxValue) return false;
|
||||
|
||||
CleanserUses[voter.PlayerId]++;
|
||||
CleanserTarget[voter.PlayerId] = target.PlayerId;
|
||||
@@ -92,6 +93,9 @@ public static class Cleanser
|
||||
CleansedPlayers.Add(target.PlayerId);
|
||||
Utils.SendMessage(string.Format(GetString("CleanserRemovedRole"), target.GetRealName()), voter.PlayerId, title: Utils.ColorString(Utils.GetRoleColor(CustomRoles.Cleanser), GetString("CleanserTitle")));
|
||||
SendRPC(voter.PlayerId);
|
||||
|
||||
Main.DontCancelVoteList.Add(voter.PlayerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AfterMeetingTasks()
|
||||
|
||||
@@ -17,6 +17,7 @@ public static class CopyCat
|
||||
public static OptionItem CanKill;
|
||||
public static OptionItem CopyCrewVar;
|
||||
public static OptionItem MiscopyLimitOpt;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -27,6 +28,7 @@ public static class CopyCat
|
||||
CopyCrewVar = BooleanOptionItem.Create(Id + 13, "CopyCrewVar", true, TabGroup.OtherRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.CopyCat]);
|
||||
MiscopyLimitOpt = IntegerOptionItem.Create(Id + 12, "CopyCatMiscopyLimit", new(0, 14, 1), 2, TabGroup.OtherRoles, false).SetParent(CanKill)
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 14, CustomRoles.CopyCat);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -41,7 +43,8 @@ public static class CopyCat
|
||||
playerIdList.Add(playerId);
|
||||
CurrentKillCooldown.Add(playerId, KillCooldown.GetFloat());
|
||||
MiscopyLimit.TryAdd(playerId, MiscopyLimitOpt.GetInt());
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@ public static class Crusader
|
||||
{
|
||||
private static readonly int Id = 20050;
|
||||
private static List<byte> playerIdList = [];
|
||||
public static Dictionary<byte, int> CrusaderLimit = [];
|
||||
|
||||
public static OptionItem SkillLimitOpt;
|
||||
public static OptionItem SkillCooldown;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static Dictionary<byte, float> CurrentKillCooldown = [];
|
||||
public static Dictionary<byte, int> CrusaderLimit = [];
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -19,6 +22,7 @@ public static class Crusader
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
SkillLimitOpt = IntegerOptionItem.Create(Id + 11, "CrusaderSkillLimit", new(1, 10, 1), 2, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Crusader])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 12, CustomRoles.Crusader);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -31,8 +35,7 @@ public static class Crusader
|
||||
CrusaderLimit.TryAdd(playerId, SkillLimitOpt.GetInt());
|
||||
CurrentKillCooldown.Add(playerId, SkillCooldown.GetFloat());
|
||||
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class Deputy
|
||||
public static OptionItem HandcuffMax;
|
||||
public static OptionItem DeputyHandcuffCDForTarget;
|
||||
private static OptionItem DeputyHandcuffDelay;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int HandcuffLimit;
|
||||
|
||||
@@ -29,6 +30,7 @@ public static class Deputy
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
DeputyHandcuffDelay = IntegerOptionItem.Create(Id + 11, "DeputyHandcuffDelay", new(0, 20, 1), 5, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Deputy])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Deputy);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -40,7 +42,7 @@ public static class Deputy
|
||||
playerIdList.Add(playerId);
|
||||
HandcuffLimit = HandcuffMax.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class Divinator
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem ShowSpecificRole;
|
||||
public static OptionItem AbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static List<byte> didVote = [];
|
||||
public static Dictionary<byte, float> CheckLimit = [];
|
||||
@@ -29,6 +30,7 @@ public static class Divinator
|
||||
HideVote = BooleanOptionItem.Create(Id + 14, "DivinatorHideVote", false, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Divinator]);
|
||||
AbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 15, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Divinator])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 11, CustomRoles.Divinator, TabGroup.CrewmateRoles);
|
||||
OverrideTasksData.Create(Id + 21, TabGroup.CrewmateRoles, CustomRoles.Divinator);
|
||||
}
|
||||
public static void Init()
|
||||
@@ -58,16 +60,16 @@ public static class Divinator
|
||||
float uses = reader.ReadSingle();
|
||||
CheckLimit[playerId] = uses;
|
||||
}
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (CheckLimit[player.PlayerId] < 1)
|
||||
{
|
||||
Utils.SendMessage(GetString("DivinatorCheckReachLimit"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckLimit[player.PlayerId] -= 1;
|
||||
@@ -76,7 +78,7 @@ public static class Divinator
|
||||
if (player.PlayerId == target.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("DivinatorCheckSelfMsg") + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
string msg;
|
||||
@@ -548,5 +550,8 @@ public static class Divinator
|
||||
}*/
|
||||
|
||||
Utils.SendMessage(GetString("DivinatorCheck") + "\n" + msg + "\n\n" + string.Format(GetString("DivinatorCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Divinator), GetString("DivinatorCheckMsgTitle")));
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
private static OptionItem CD;
|
||||
private static OptionItem UseLimit;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int DeliverLimit;
|
||||
|
||||
@@ -24,6 +25,7 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimit = IntegerOptionItem.Create(Id + 12, "AbilityUseLimit", new(1, 20, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.DonutDelivery])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.DonutDelivery);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -39,7 +41,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
DeliverLimit = UseLimit.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
private static OptionItem CD;
|
||||
private static OptionItem UseLimit;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int BlockLimit;
|
||||
|
||||
@@ -26,6 +27,7 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimit = IntegerOptionItem.Create(Id + 11, "AbilityUseLimit", new(1, 20, 1), 3, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Escort])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 12, CustomRoles.Escort);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -39,7 +41,7 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
BlockLimit = UseLimit.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem FarseerCooldown;
|
||||
public static OptionItem FarseerRevealTime;
|
||||
public static OptionItem Vision;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
private static readonly System.Collections.Generic.List<CustomRoles> randomRolesForTrickster =
|
||||
[
|
||||
@@ -109,6 +110,7 @@ namespace TOHE.Roles.Crewmate
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
Vision = FloatOptionItem.Create(Id + 12, "FarseerVision", new(0f, 1f, 0.05f), 0.25f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Farseer])
|
||||
.SetValueFormat(OptionFormat.Multiplier);
|
||||
UsePet = CreatePetUseSetting(Id + 13, CustomRoles.Farseer);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -117,7 +119,8 @@ namespace TOHE.Roles.Crewmate
|
||||
public static void Add(byte playerId)
|
||||
{
|
||||
isEnable = true;
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
@@ -145,7 +148,8 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
else if (ar_time >= FarseerRevealTime.GetFloat())//時間以上一緒にいて塗れた時
|
||||
{
|
||||
player.SetKillCooldown();
|
||||
if (UsePets.GetBool()) player.AddKCDAsAbilityCD();
|
||||
else player.SetKillCooldown();
|
||||
Main.FarseerTimer.Remove(player.PlayerId);//塗が完了したのでDictionaryから削除
|
||||
Main.isRevealed[(player.PlayerId, ar_target.PlayerId)] = true;//塗り完了
|
||||
player.RpcSetRevealtPlayer(ar_target, true);
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem CD;
|
||||
private static OptionItem AdditionalSpeed;
|
||||
private static OptionItem UseLimitOpt;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static List<byte> IncreasedSpeedPlayerList = [];
|
||||
|
||||
@@ -28,6 +29,7 @@ namespace TOHE.Roles.Crewmate
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 7, "AbilityUseLimit", new(1, 14, 1), 3, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Gaulois])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 8, CustomRoles.Gaulois);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -41,6 +43,10 @@ namespace TOHE.Roles.Crewmate
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
UseLimit.Add(playerId, UseLimitOpt.GetInt());
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
public static bool IsEnable => playerIdList.Count > 0;
|
||||
@@ -91,6 +97,7 @@ namespace TOHE.Roles.Crewmate
|
||||
IncreasedSpeedPlayerList.Add(target.PlayerId);
|
||||
UseLimit[killer.PlayerId]--;
|
||||
|
||||
killer.SetKillCooldown();
|
||||
SendRPC(killer.PlayerId);
|
||||
SendRPCAddPlayerToList(target.PlayerId);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public static class Jailor
|
||||
|
||||
public static OptionItem JailCooldown;
|
||||
public static OptionItem notifyJailedOnMeeting;
|
||||
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -24,6 +24,7 @@ public static class Jailor
|
||||
JailCooldown = FloatOptionItem.Create(Id + 10, "JailorJailCooldown", new(0f, 60f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Jailor])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
notifyJailedOnMeeting = BooleanOptionItem.Create(Id + 18, "notifyJailedOnMeeting", true, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Jailor]);
|
||||
UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Jailor);
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
@@ -41,7 +42,7 @@ public static class Jailor
|
||||
JailorHasExe.Add(playerId, false);
|
||||
JailorDidVote.Add(playerId, false);
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public static class Medic
|
||||
private static OptionItem ResetCooldown;
|
||||
public static OptionItem GuesserIgnoreShield;
|
||||
private static OptionItem AmountOfShields;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static readonly string[] MedicWhoCanSeeProtectName =
|
||||
[
|
||||
@@ -65,6 +66,7 @@ public static class Medic
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.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);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -81,7 +83,7 @@ public static class Medic
|
||||
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()} : {ProtectLimit[playerId]} shields left", "Medicaler");
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public static class Monarch
|
||||
|
||||
public static OptionItem KnightCooldown;
|
||||
public static OptionItem KnightMax;
|
||||
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static int KnightLimit;
|
||||
|
||||
@@ -24,6 +24,7 @@ public static class Monarch
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
KnightMax = IntegerOptionItem.Create(Id + 12, "MonarchKnightMax", new(1, 15, 1), 2, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Monarch])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
UsePet = CreatePetUseSetting(Id + 11, CustomRoles.Monarch);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -35,7 +36,7 @@ public static class Monarch
|
||||
playerIdList.Add(playerId);
|
||||
KnightLimit = KnightMax.GetInt();
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ internal static class NiceEraser
|
||||
|
||||
private static OptionItem EraseLimitOpt;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
private static List<byte> didVote = [];
|
||||
public static Dictionary<byte, int> EraseLimit = [];
|
||||
@@ -23,6 +24,7 @@ internal static class NiceEraser
|
||||
EraseLimitOpt = IntegerOptionItem.Create(Id + 2, "EraseLimit", new(1, 15, 1), 1, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceEraser])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
HideVote = BooleanOptionItem.Create(Id + 3, "NiceEraserHideVote", false, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.NiceEraser]);
|
||||
CancelVote = Options.CreateVoteCancellingUseSetting(Id + 4, CustomRoles.NiceEraser, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -55,24 +57,24 @@ internal static class NiceEraser
|
||||
}
|
||||
public static string GetProgressText(byte playerId) => Utils.ColorString(EraseLimit[playerId] > 0 ? Utils.GetRoleColor(CustomRoles.NiceEraser) : Color.gray, EraseLimit.TryGetValue(playerId, out var x) ? $"({x})" : "Invalid");
|
||||
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return;
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return false;
|
||||
|
||||
if (target.PlayerId == player.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target.GetCustomRole().IsNeutral())
|
||||
{
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNeutralNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId)) EraseLimit[player.PlayerId]--;
|
||||
@@ -83,7 +85,10 @@ internal static class NiceEraser
|
||||
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.NiceEraser), GetString("EraserEraseMsgTitle")));
|
||||
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
if (GameStates.IsInTask) Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
|
||||
+22
-18
@@ -15,6 +15,7 @@ public static class Oracle
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem FailChance;
|
||||
public static OptionItem OracleAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static List<byte> didVote = [];
|
||||
public static Dictionary<byte, float> CheckLimit = [];
|
||||
@@ -33,6 +34,7 @@ public static class Oracle
|
||||
OracleAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 14, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Oracle])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 11, CustomRoles.Oracle, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -61,16 +63,16 @@ public static class Oracle
|
||||
float uses = reader.ReadSingle();
|
||||
CheckLimit[playerId] = uses;
|
||||
}
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (CheckLimit[player.PlayerId] < 1)
|
||||
{
|
||||
Utils.SendMessage(GetString("OracleCheckReachLimit"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
CheckLimit[player.PlayerId] -= 1;
|
||||
@@ -79,7 +81,7 @@ public static class Oracle
|
||||
if (player.PlayerId == target.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("OracleCheckSelfMsg") + "\n\n" + string.Format(GetString("OracleCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
string text;
|
||||
@@ -94,20 +96,20 @@ public static class Oracle
|
||||
if (random_number_1 <= FailChance.GetInt())
|
||||
{
|
||||
int random_number_2 = IRandom.Instance.Next(1, 3);
|
||||
if (text == "Crew")
|
||||
switch (text)
|
||||
{
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
if (random_number_2 == 2) text = "Imp";
|
||||
}
|
||||
if (text == "Neut")
|
||||
{
|
||||
if (random_number_2 == 1) text = "Crew";
|
||||
if (random_number_2 == 2) text = "Imp";
|
||||
}
|
||||
if (text == "Imp")
|
||||
{
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
if (random_number_2 == 2) text = "Crew";
|
||||
case "Crew":
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
else if (random_number_2 == 2) text = "Imp";
|
||||
break;
|
||||
case "Neut":
|
||||
if (random_number_2 == 1) text = "Crew";
|
||||
if (random_number_2 == 2) text = "Imp";
|
||||
break;
|
||||
case "Imp":
|
||||
if (random_number_2 == 1) text = "Neut";
|
||||
if (random_number_2 == 2) text = "Crew";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,5 +118,7 @@ public static class Oracle
|
||||
|
||||
Utils.SendMessage(GetString("OracleCheck") + "\n" + msg + "\n\n" + string.Format(GetString("OracleCheckLimit"), CheckLimit[player.PlayerId]), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Oracle), GetString("OracleCheckMsgTitle")));
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -17,15 +17,17 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem RicochetAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupSingleRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Ricochet, 1);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 10, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
RicochetAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 11, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.5f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Ricochet])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 12, CustomRoles.Ricochet, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -82,12 +84,9 @@ namespace TOHE.Roles.Crewmate
|
||||
|
||||
return true;
|
||||
}
|
||||
public static void OnVote(PlayerControl pc, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl pc, PlayerControl target)
|
||||
{
|
||||
if (target == null) return;
|
||||
if (pc == null) return;
|
||||
if (pc.PlayerId == target.PlayerId) return;
|
||||
if (!pc.Is(CustomRoles.Ricochet)) return;
|
||||
if (target == null || pc == null || pc.PlayerId == target.PlayerId || !pc.Is(CustomRoles.Ricochet) || Main.DontCancelVoteList.Contains(pc.PlayerId)) return false;
|
||||
|
||||
if (UseLimit[pc.PlayerId] >= 1)
|
||||
{
|
||||
@@ -95,7 +94,10 @@ namespace TOHE.Roles.Crewmate
|
||||
ProtectAgainst = target.PlayerId;
|
||||
SendRPC(pc.PlayerId);
|
||||
SendRPCSyncTarget(ProtectAgainst);
|
||||
Main.DontCancelVoteList.Add(pc.PlayerId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@ public static class Sheriff
|
||||
public static OptionItem NonCrewCanKillCrew;
|
||||
public static OptionItem NonCrewCanKillImp;
|
||||
public static OptionItem NonCrewCanKillNeutral;
|
||||
public static OptionItem UsePet;
|
||||
public static Dictionary<CustomRoles, OptionItem> KillTargetOptions = [];
|
||||
public static Dictionary<byte, int> ShotLimit = [];
|
||||
public static Dictionary<byte, float> CurrentKillCooldown = [];
|
||||
@@ -63,6 +64,7 @@ public static class Sheriff
|
||||
NonCrewCanKillImp = BooleanOptionItem.Create(Id + 19, "SheriffMadCanKillImp", true, TabGroup.CrewmateRoles, false).SetParent(SetNonCrewCanKill);
|
||||
NonCrewCanKillCrew = BooleanOptionItem.Create(Id + 21, "SheriffMadCanKillCrew", true, TabGroup.CrewmateRoles, false).SetParent(SetNonCrewCanKill);
|
||||
NonCrewCanKillNeutral = BooleanOptionItem.Create(Id + 20, "SheriffMadCanKillNeutral", true, TabGroup.CrewmateRoles, false).SetParent(SetNonCrewCanKill);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 29, CustomRoles.Sheriff);
|
||||
}
|
||||
public static void SetUpNeutralOptions(int Id)
|
||||
{
|
||||
@@ -94,7 +96,7 @@ public static class Sheriff
|
||||
ShotLimit.TryAdd(playerId, ShotLimitOpt.GetInt());
|
||||
Logger.Info($"{Utils.GetPlayerById(playerId)?.GetNameWithRole().RemoveHtmlTags()} : Shot Limit - {ShotLimit[playerId]}", "Sheriff");
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ namespace TOHE.Roles.Crewmate
|
||||
using Hazel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
|
||||
@@ -11,11 +11,14 @@ public static class SwordsMan
|
||||
//public static bool isKilled = false;
|
||||
public static List<byte> killed = [];
|
||||
public static OptionItem CanVent;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
Options.SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.SwordsMan);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", false, TabGroup.CrewmateRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.SwordsMan]);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", false, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SwordsMan]);
|
||||
UsePet = Options.CreatePetUseSetting(Id + 10, CustomRoles.SwordsMan);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -32,7 +35,7 @@ public static class SwordsMan
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!AmongUsClient.Instance.AmHost || (Options.UsePets.GetBool() && UsePet.GetBool())) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace TOHE.Roles.Crewmate
|
||||
public static OptionItem VentCooldown;
|
||||
public static OptionItem UseLimitOpt;
|
||||
public static OptionItem TetherAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
@@ -25,10 +26,11 @@ namespace TOHE.Roles.Crewmate
|
||||
VentCooldown = FloatOptionItem.Create(Id + 10, "VentCooldown", new(0f, 70f, 1f), 15f, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 11, "AbilityUseLimit", new(0, 20, 1), 1, TabGroup.CrewmateRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
TetherAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 12, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 0.4f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tether])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 13, CustomRoles.Tether, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -94,12 +96,9 @@ namespace TOHE.Roles.Crewmate
|
||||
}, 0.5f, "Tether No Target Boot From Vent");
|
||||
}
|
||||
}
|
||||
public static void OnVote(PlayerControl pc, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl pc, PlayerControl target)
|
||||
{
|
||||
if (pc == null) return;
|
||||
if (target == null) return;
|
||||
if (!pc.Is(CustomRoles.Tether)) return;
|
||||
if (pc.PlayerId == target.PlayerId) return;
|
||||
if (pc == null || target == null || !pc.Is(CustomRoles.Tether) || pc.PlayerId == target.PlayerId || Main.DontCancelVoteList.Contains(pc.PlayerId)) return false;
|
||||
|
||||
if (UseLimit[pc.PlayerId] >= 1)
|
||||
{
|
||||
@@ -107,7 +106,10 @@ namespace TOHE.Roles.Crewmate
|
||||
Target = target.PlayerId;
|
||||
SendRPC(pc.PlayerId);
|
||||
SendRPCSyncTarget(Target);
|
||||
Main.DontCancelVoteList.Add(pc.PlayerId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace TOHE.Roles.Crewmate
|
||||
private static OptionItem CanGetColoredArrow;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem TrackerAbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
public static bool CanSeeLastRoomInMeeting;
|
||||
|
||||
@@ -37,6 +38,7 @@ namespace TOHE.Roles.Crewmate
|
||||
TrackerAbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(Id + 9, "AbilityUseGainWithEachTaskCompleted", new(0f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Tracker])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CancelVote = CreateVoteCancellingUseSetting(Id + 4, CustomRoles.Tracker, TabGroup.CrewmateRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -74,12 +76,9 @@ namespace TOHE.Roles.Crewmate
|
||||
}
|
||||
public static string GetTargetMark(PlayerControl seer, PlayerControl target) => !(seer == null || target == null) && TrackerTarget.ContainsKey(seer.PlayerId) && TrackerTarget[seer.PlayerId].Contains(target.PlayerId) ? Utils.ColorString(seer.GetRoleColor(), "◀") : string.Empty;
|
||||
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null) return;
|
||||
if (TrackLimit[player.PlayerId] < 1) return;
|
||||
if (player.PlayerId == target.PlayerId) return;
|
||||
if (TrackerTarget[player.PlayerId].Contains(target.PlayerId)) return;
|
||||
if (player == null || target == null || TrackLimit[player.PlayerId] < 1 || player.PlayerId == target.PlayerId || TrackerTarget[player.PlayerId].Contains(target.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
|
||||
TrackLimit[player.PlayerId]--;
|
||||
|
||||
@@ -87,6 +86,9 @@ namespace TOHE.Roles.Crewmate
|
||||
TargetArrow.Add(player.PlayerId, target.PlayerId);
|
||||
|
||||
SendRPC(player.PlayerId, target.PlayerId);
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void OnReportDeadBody()
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Neutral;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
|
||||
@@ -27,6 +27,7 @@ internal static class Eraser
|
||||
private static OptionItem EraseMethod;
|
||||
private static OptionItem WhenTargetIsNeutral;
|
||||
public static OptionItem HideVote;
|
||||
public static OptionItem CancelVote;
|
||||
|
||||
private static List<byte> didVote = [];
|
||||
private static Dictionary<byte, int> EraseLimit = [];
|
||||
@@ -40,6 +41,7 @@ internal static class Eraser
|
||||
EraseLimitOpt = IntegerOptionItem.Create(Id + 12, "EraseLimit", new(1, 15, 1), 1, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Eraser])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
HideVote = BooleanOptionItem.Create(Id + 13, "EraserHideVote", false, TabGroup.OtherRoles, false).SetParent(Options.CustomRoleSpawnChances[CustomRoles.Eraser]);
|
||||
CancelVote = Options.CreateVoteCancellingUseSetting(Id + 14, CustomRoles.Eraser, TabGroup.OtherRoles);
|
||||
}
|
||||
public static void Init()
|
||||
{
|
||||
@@ -103,24 +105,24 @@ internal static class Eraser
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void OnVote(PlayerControl player, PlayerControl target)
|
||||
public static bool OnVote(PlayerControl player, PlayerControl target)
|
||||
{
|
||||
if (player == null || target == null || EraseMethod.GetInt() == 0) return;
|
||||
if (didVote.Contains(player.PlayerId)) return;
|
||||
if (player == null || target == null || EraseMethod.GetInt() == 0) return false;
|
||||
if (didVote.Contains(player.PlayerId) || Main.DontCancelVoteList.Contains(player.PlayerId)) return false;
|
||||
didVote.Add(player.PlayerId);
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return;
|
||||
if (EraseLimit.ContainsKey(player.PlayerId) && EraseLimit[player.PlayerId] < 1) return false;
|
||||
|
||||
if (target.PlayerId == player.PlayerId)
|
||||
{
|
||||
Utils.SendMessage(GetString("EraserEraseSelf"), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target.GetCustomRole().IsNeutral())
|
||||
{
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNeutralNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")));
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EraseLimit.ContainsKey(player.PlayerId)) EraseLimit[player.PlayerId]--;
|
||||
@@ -131,7 +133,10 @@ internal static class Eraser
|
||||
|
||||
Utils.SendMessage(string.Format(GetString("EraserEraseNotice"), target.GetRealName()), player.PlayerId, Utils.ColorString(Utils.GetRoleColor(CustomRoles.Eraser), GetString("EraserEraseMsgTitle")));
|
||||
|
||||
Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
if (GameStates.IsInTask) Utils.NotifyRoles(SpecifySeer: player, SpecifyTarget: target);
|
||||
|
||||
Main.DontCancelVoteList.Add(player.PlayerId);
|
||||
return true;
|
||||
}
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
@@ -143,8 +148,7 @@ internal static class Eraser
|
||||
foreach (byte pc in PlayerToErase.ToArray())
|
||||
{
|
||||
var player = Utils.GetPlayerById(pc);
|
||||
if (player == null)
|
||||
continue;
|
||||
if (player == null) continue;
|
||||
player.RpcSetCustomRole(CustomRolesHelper.GetErasedRole(player.GetCustomRole()));
|
||||
player.Notify(GetString("LostRoleByEraser"));
|
||||
Logger.Info($"{player.GetNameWithRole().RemoveHtmlTags()} 被擦除了", "Eraser");
|
||||
|
||||
@@ -2,7 +2,6 @@ using AmongUs.GameOptions;
|
||||
using Hazel;
|
||||
using Il2CppSystem.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
using static TOHE.Utils;
|
||||
|
||||
@@ -53,7 +53,7 @@ internal static class QuickShooter
|
||||
}
|
||||
public static void OnShapeshift(PlayerControl pc, bool shapeshifting)
|
||||
{
|
||||
if (Main.KillTimers[pc.PlayerId] == 0 && shapeshifting)
|
||||
if (Main.KillTimers[pc.PlayerId] <= 0 && shapeshifting)
|
||||
{
|
||||
ShotLimit[pc.PlayerId]++;
|
||||
SendRPC(pc.PlayerId);
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace TOHE.Roles.Impostor
|
||||
byte playerId = reader.ReadByte();
|
||||
YinYangedPlayers.Add(playerId);
|
||||
}
|
||||
else YinYangedPlayers.Clear();
|
||||
}
|
||||
|
||||
public static bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
@@ -100,8 +101,8 @@ namespace TOHE.Roles.Impostor
|
||||
public static void OnReportDeadBody()
|
||||
{
|
||||
if (!IsEnable) return;
|
||||
YinYanger_?.ResetKillCooldown();
|
||||
YinYangedPlayers.Clear();
|
||||
YinYanger_?.ResetKillCooldown();
|
||||
SendRPC(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,12 +85,14 @@ namespace TOHE.Roles.Neutral
|
||||
}
|
||||
pc.Suicide(realKiller: Bubble_);
|
||||
}
|
||||
EncasedPlayers.Remove(id);
|
||||
}
|
||||
}
|
||||
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_);
|
||||
EncasedPlayers.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
+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,5 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using System.Collections.Generic;
|
||||
using static TOHE.Options;
|
||||
|
||||
namespace TOHE.Roles.Neutral;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using TOHE.Roles.Crewmate;
|
||||
using UnityEngine;
|
||||
namespace TOHE.Roles.Neutral;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using Hazel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Utils;
|
||||
|
||||
@@ -3,6 +3,7 @@ using Hazel;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using static TOHE.Options;
|
||||
using static TOHE.Translator;
|
||||
|
||||
namespace TOHE.Roles.Neutral;
|
||||
|
||||
@@ -98,7 +99,7 @@ public static class WeaponMaster
|
||||
Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
break;
|
||||
case 3 when shieldUsed:
|
||||
WM.Notify(Translator.GetString("WMShieldAlreadyUsed"));
|
||||
WM.Notify(GetString("WMShieldAlreadyUsed"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -119,13 +120,10 @@ public static class WeaponMaster
|
||||
{
|
||||
foreach (PlayerControl player in Main.AllAlivePlayerControls)
|
||||
{
|
||||
if (Pelican.IsEaten(player.PlayerId)) continue;
|
||||
if (player == killer) continue;
|
||||
if (player.Is(CustomRoles.Pestilence) || Main.VeteranInProtect.ContainsKey(target.PlayerId)) continue;
|
||||
if (Pelican.IsEaten(player.PlayerId) || player == killer || player.Is(CustomRoles.Pestilence) || Main.VeteranInProtect.ContainsKey(target.PlayerId)) continue;
|
||||
if (Vector2.Distance(killer.transform.position, player.transform.position) <= Radius.GetFloat())
|
||||
{
|
||||
player.SetRealKiller(killer);
|
||||
player.Kill(player);
|
||||
player.Suicide(PlayerState.DeathReason.Kill, killer);
|
||||
}
|
||||
}
|
||||
killer.SetKillCooldown(time: HighKCD.GetFloat());
|
||||
@@ -134,7 +132,7 @@ public static class WeaponMaster
|
||||
case 2:
|
||||
if (killer.RpcCheckAndMurder(target, true))
|
||||
{
|
||||
target.Kill(target);
|
||||
target.Suicide(PlayerState.DeathReason.Kill, killer);
|
||||
killer.SetKillCooldown();
|
||||
}
|
||||
return false;
|
||||
@@ -173,10 +171,10 @@ public static class WeaponMaster
|
||||
{
|
||||
return mode switch
|
||||
{
|
||||
0 => "Sword",
|
||||
1 => "Axe",
|
||||
2 => "Lance",
|
||||
3 => "Shield",
|
||||
0 => GetString("Sword"),
|
||||
1 => GetString("Axe"),
|
||||
2 => GetString("lance"),
|
||||
3 => GetString("Shield"),
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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.1.2";
|
||||
public const string PluginDisplayVersion = "2.1.2";
|
||||
public const string PluginVersion = "2.2.1";
|
||||
public const string PluginDisplayVersion = "2.2.1";
|
||||
public static readonly string SupportedAUVersion = "2023.10.24";
|
||||
public const int PluginCreate = 3;
|
||||
public const bool Canary = false;
|
||||
@@ -95,6 +95,7 @@ public class Main : BasePlugin
|
||||
public static float RefixCooldownDelay;
|
||||
public static bool ProcessShapeshifts = true;
|
||||
public static Dictionary<byte, (long START_TIMESTAMP, int TOTALCD)> AbilityCD = [];
|
||||
public static List<byte> DontCancelVoteList = [];
|
||||
private static GameData.PlayerInfo lastVotedPlayerInfo;
|
||||
public static string LastVotedPlayer;
|
||||
public static byte NimblePlayer = byte.MaxValue;
|
||||
@@ -642,13 +643,16 @@ public enum CustomRoles
|
||||
{
|
||||
//Default
|
||||
Crewmate = 0,
|
||||
//Impostor(Vanilla)
|
||||
|
||||
//Impostors (Vanilla)
|
||||
Impostor,
|
||||
Shapeshifter,
|
||||
// Vanilla Remakes
|
||||
ImpostorTOHE,
|
||||
ShapeshifterTOHE,
|
||||
//Impostor
|
||||
|
||||
//Impostors
|
||||
|
||||
BountyHunter,
|
||||
FireWorks,
|
||||
Mafia,
|
||||
@@ -727,7 +731,8 @@ public enum CustomRoles
|
||||
Refugee,
|
||||
Underdog,
|
||||
// Flashbang,
|
||||
//Crewmate(Vanilla)
|
||||
|
||||
//Crewmates (Vanilla)
|
||||
Engineer,
|
||||
GuardianAngel,
|
||||
Scientist,
|
||||
@@ -736,7 +741,9 @@ public enum CustomRoles
|
||||
EngineerTOHE,
|
||||
GuardianAngelTOHE,
|
||||
ScientistTOHE,
|
||||
//Crewmate
|
||||
|
||||
// Crewmate
|
||||
|
||||
Luckey,
|
||||
Needy,
|
||||
SuperStar,
|
||||
@@ -831,7 +838,9 @@ public enum CustomRoles
|
||||
Crusader,
|
||||
Cleanser,
|
||||
//Reverie,
|
||||
//Neutral
|
||||
|
||||
//Neutrals
|
||||
|
||||
Arsonist,
|
||||
HexMaster,
|
||||
Jester,
|
||||
|
||||
Reference in new issue
Block a user