mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-21 21:43:34 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8ef3f0a9f | ||
|
|
28d448a93a | ||
|
|
8614486bb7 | ||
|
|
0ca51a468b | ||
|
|
b614ec7dfa | ||
|
|
8df2c8fa81 | ||
|
|
21b4a1ead8 | ||
|
|
6f1bc6a415 | ||
|
|
339fabc04b | ||
|
|
026ee4d322 |
No files matched your search
@@ -3,10 +3,10 @@ namespace EHR;
|
||||
|
||||
public enum CustomRoles
|
||||
{
|
||||
//Default
|
||||
// Default
|
||||
Crewmate = 0,
|
||||
|
||||
//Impostors (Vanilla)
|
||||
// Impostors (Vanilla)
|
||||
Impostor,
|
||||
Shapeshifter,
|
||||
|
||||
@@ -14,7 +14,7 @@ public enum CustomRoles
|
||||
ImpostorEHR,
|
||||
ShapeshifterEHR,
|
||||
|
||||
//Impostors
|
||||
// Impostors
|
||||
|
||||
Hacker, // Anonymous
|
||||
AntiAdminer,
|
||||
@@ -49,6 +49,7 @@ public enum CustomRoles
|
||||
Freezer,
|
||||
Gambler,
|
||||
Gangster,
|
||||
Generator,
|
||||
Godfather,
|
||||
Greedier,
|
||||
Hangman,
|
||||
@@ -100,7 +101,7 @@ public enum CustomRoles
|
||||
YinYanger,
|
||||
Zombie,
|
||||
|
||||
//Crewmates (Vanilla)
|
||||
// Crewmates (Vanilla)
|
||||
Engineer,
|
||||
GuardianAngel,
|
||||
Scientist,
|
||||
@@ -111,14 +112,14 @@ public enum CustomRoles
|
||||
GuardianAngelEHR,
|
||||
ScientistEHR,
|
||||
|
||||
// Crewmate
|
||||
// Crewmates
|
||||
|
||||
Addict,
|
||||
Adventurer,
|
||||
Aid,
|
||||
Alchemist,
|
||||
Altruist,
|
||||
Analyzer,
|
||||
Analyst,
|
||||
Autocrat,
|
||||
Beacon,
|
||||
Benefactor,
|
||||
@@ -187,8 +188,9 @@ public enum CustomRoles
|
||||
Rabbit,
|
||||
Randomizer,
|
||||
Ricochet,
|
||||
Sentinel,
|
||||
SecurityGuard,
|
||||
Sentinel,
|
||||
Sentry,
|
||||
Sheriff,
|
||||
Shiftguard,
|
||||
Snitch,
|
||||
@@ -212,7 +214,7 @@ public enum CustomRoles
|
||||
SwordsMan, // Vigilante
|
||||
Witness,
|
||||
|
||||
//Neutrals
|
||||
// Neutrals
|
||||
|
||||
Agitater,
|
||||
Amnesiac,
|
||||
@@ -220,6 +222,7 @@ public enum CustomRoles
|
||||
Bandit,
|
||||
BloodKnight,
|
||||
Bubble,
|
||||
Cherokious,
|
||||
Collector,
|
||||
Deathknight,
|
||||
Gamer, // Demon
|
||||
@@ -268,6 +271,7 @@ public enum CustomRoles
|
||||
Ritualist,
|
||||
Romantic,
|
||||
RuthlessRomantic,
|
||||
SchrodingersCat,
|
||||
NSerialKiller, // Serial Killer
|
||||
Sidekick,
|
||||
SoulHunter,
|
||||
@@ -288,25 +292,25 @@ public enum CustomRoles
|
||||
WeaponMaster,
|
||||
Workaholic,
|
||||
|
||||
//SoloKombat
|
||||
// Solo Kombat
|
||||
KB_Normal,
|
||||
|
||||
//FFA
|
||||
// FFA
|
||||
Killer,
|
||||
|
||||
//MoveAndStop
|
||||
// Move And Stop
|
||||
Tasker,
|
||||
|
||||
//HotPotato
|
||||
// Hot Potato
|
||||
Potato,
|
||||
|
||||
//H&S
|
||||
// H&S
|
||||
Hider,
|
||||
Seeker,
|
||||
Fox,
|
||||
Troll,
|
||||
|
||||
//GM
|
||||
// GM
|
||||
GM,
|
||||
|
||||
// ????
|
||||
|
||||
+18
-14
@@ -3,10 +3,10 @@ namespace EHR;
|
||||
|
||||
public enum CustomRoles
|
||||
{
|
||||
//Default
|
||||
// Default
|
||||
Crewmate = 0,
|
||||
|
||||
//Impostors (Vanilla)
|
||||
// Impostors (Vanilla)
|
||||
Impostor,
|
||||
Shapeshifter,
|
||||
|
||||
@@ -14,7 +14,7 @@ public enum CustomRoles
|
||||
ImpostorEHR,
|
||||
ShapeshifterEHR,
|
||||
|
||||
//Impostors
|
||||
// Impostors
|
||||
|
||||
Hacker, // Anonymous
|
||||
AntiAdminer,
|
||||
@@ -49,6 +49,7 @@ public enum CustomRoles
|
||||
Freezer,
|
||||
Gambler,
|
||||
Gangster,
|
||||
Generator,
|
||||
Godfather,
|
||||
Greedier,
|
||||
Hangman,
|
||||
@@ -100,7 +101,7 @@ public enum CustomRoles
|
||||
YinYanger,
|
||||
Zombie,
|
||||
|
||||
//Crewmates (Vanilla)
|
||||
// Crewmates (Vanilla)
|
||||
Engineer,
|
||||
GuardianAngel,
|
||||
Scientist,
|
||||
@@ -111,14 +112,14 @@ public enum CustomRoles
|
||||
GuardianAngelEHR,
|
||||
ScientistEHR,
|
||||
|
||||
// Crewmate
|
||||
// Crewmates
|
||||
|
||||
Addict,
|
||||
Adventurer,
|
||||
Aid,
|
||||
Alchemist,
|
||||
Altruist,
|
||||
Analyzer,
|
||||
Analyst,
|
||||
Autocrat,
|
||||
Beacon,
|
||||
Benefactor,
|
||||
@@ -187,8 +188,9 @@ public enum CustomRoles
|
||||
Rabbit,
|
||||
Randomizer,
|
||||
Ricochet,
|
||||
Sentinel,
|
||||
SecurityGuard,
|
||||
Sentinel,
|
||||
Sentry,
|
||||
Sheriff,
|
||||
Shiftguard,
|
||||
Snitch,
|
||||
@@ -212,7 +214,7 @@ public enum CustomRoles
|
||||
SwordsMan, // Vigilante
|
||||
Witness,
|
||||
|
||||
//Neutrals
|
||||
// Neutrals
|
||||
|
||||
Agitater,
|
||||
Amnesiac,
|
||||
@@ -220,6 +222,7 @@ public enum CustomRoles
|
||||
Bandit,
|
||||
BloodKnight,
|
||||
Bubble,
|
||||
Cherokious,
|
||||
Collector,
|
||||
Deathknight,
|
||||
Gamer, // Demon
|
||||
@@ -268,6 +271,7 @@ public enum CustomRoles
|
||||
Ritualist,
|
||||
Romantic,
|
||||
RuthlessRomantic,
|
||||
SchrodingersCat,
|
||||
NSerialKiller, // Serial Killer
|
||||
Sidekick,
|
||||
SoulHunter,
|
||||
@@ -288,25 +292,25 @@ public enum CustomRoles
|
||||
WeaponMaster,
|
||||
Workaholic,
|
||||
|
||||
//SoloKombat
|
||||
// Solo Kombat
|
||||
KB_Normal,
|
||||
|
||||
//FFA
|
||||
// FFA
|
||||
Killer,
|
||||
|
||||
//MoveAndStop
|
||||
// Move And Stop
|
||||
Tasker,
|
||||
|
||||
//HotPotato
|
||||
// Hot Potato
|
||||
Potato,
|
||||
|
||||
//H&S
|
||||
// H&S
|
||||
Hider,
|
||||
Seeker,
|
||||
Fox,
|
||||
Troll,
|
||||
|
||||
//GM
|
||||
// GM
|
||||
GM,
|
||||
|
||||
// ????
|
||||
|
||||
@@ -99,6 +99,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Dictator => CustomRoles.Crewmate,
|
||||
CustomRoles.Inhibitor => CustomRoles.Impostor,
|
||||
CustomRoles.Kidnapper => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Generator => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Blackmailer => CustomRoles.Impostor,
|
||||
CustomRoles.Commander => CustomRoles.Shapeshifter,
|
||||
CustomRoles.Freezer => CustomRoles.Shapeshifter,
|
||||
@@ -170,6 +171,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Altruist => CustomRoles.Crewmate,
|
||||
CustomRoles.Transmitter => CustomRoles.Crewmate,
|
||||
CustomRoles.Autocrat => CustomRoles.Crewmate,
|
||||
CustomRoles.Sentry => CustomRoles.Crewmate,
|
||||
CustomRoles.Perceiver => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Convener => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Mathematician => CustomRoles.Crewmate,
|
||||
@@ -183,7 +185,7 @@ internal static class CustomRolesHelper
|
||||
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.Analyst => UsePets && Analyst.UsePet.GetBool() ? CustomRoles.Crewmate : CustomRoles.Impostor,
|
||||
CustomRoles.Escapee => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
CustomRoles.NiceGuesser => CustomRoles.Crewmate,
|
||||
CustomRoles.EvilGuesser => CustomRoles.Impostor,
|
||||
@@ -230,6 +232,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Bard => CustomRoles.Impostor,
|
||||
CustomRoles.Swooper => CustomRoles.Impostor,
|
||||
CustomRoles.Crewpostor => CustomRoles.Engineer,
|
||||
CustomRoles.Cherokious => CustomRoles.Engineer,
|
||||
CustomRoles.Observer => CustomRoles.Crewmate,
|
||||
CustomRoles.DovesOfNeace => UsePets ? CustomRoles.Crewmate : CustomRoles.Engineer,
|
||||
CustomRoles.Disperser => UsePets ? CustomRoles.Impostor : CustomRoles.Shapeshifter,
|
||||
@@ -312,7 +315,7 @@ internal static class CustomRolesHelper
|
||||
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.Analyst => UsePets && Analyst.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Witness => UsePets && Options.WitnessUsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
|
||||
CustomRoles.Pursuer => RoleTypes.Impostor,
|
||||
CustomRoles.Revolutionist => RoleTypes.Impostor,
|
||||
@@ -339,6 +342,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Sprayer => RoleTypes.Impostor,
|
||||
CustomRoles.PlagueDoctor => RoleTypes.Impostor,
|
||||
CustomRoles.Postman => RoleTypes.Impostor,
|
||||
CustomRoles.SchrodingersCat => RoleTypes.Impostor,
|
||||
CustomRoles.Impartial => RoleTypes.Impostor,
|
||||
CustomRoles.Predator => RoleTypes.Impostor,
|
||||
CustomRoles.Reckless => RoleTypes.Impostor,
|
||||
@@ -377,6 +381,7 @@ internal static class CustomRolesHelper
|
||||
public static bool IsNonNK(this CustomRoles role) => role is
|
||||
CustomRoles.Jester or
|
||||
CustomRoles.Postman or
|
||||
CustomRoles.SchrodingersCat or
|
||||
CustomRoles.Impartial or
|
||||
CustomRoles.Predator or
|
||||
CustomRoles.SoulHunter or
|
||||
@@ -413,6 +418,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Succubus or
|
||||
CustomRoles.Gamer or
|
||||
CustomRoles.Crewpostor or
|
||||
CustomRoles.Cherokious or
|
||||
CustomRoles.Necromancer or
|
||||
CustomRoles.Agitater or
|
||||
CustomRoles.Wraith or
|
||||
@@ -477,6 +483,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Amnesiac or
|
||||
CustomRoles.God or
|
||||
CustomRoles.Postman or
|
||||
CustomRoles.SchrodingersCat or
|
||||
CustomRoles.Predator or
|
||||
CustomRoles.Pursuer or
|
||||
CustomRoles.FFF or
|
||||
@@ -533,6 +540,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Underdog or
|
||||
CustomRoles.Inhibitor or
|
||||
CustomRoles.Kidnapper or
|
||||
CustomRoles.Generator or
|
||||
CustomRoles.Blackmailer or
|
||||
CustomRoles.Commander or
|
||||
CustomRoles.Freezer or
|
||||
@@ -631,7 +639,7 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Escort or
|
||||
CustomRoles.DonutDelivery or
|
||||
CustomRoles.Gaulois or
|
||||
CustomRoles.Analyzer or
|
||||
CustomRoles.Analyst or
|
||||
CustomRoles.Witness or
|
||||
CustomRoles.Monarch or
|
||||
CustomRoles.Jailor or
|
||||
@@ -654,7 +662,7 @@ internal static class CustomRolesHelper
|
||||
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.Analyst when Analyst.UsePet.GetBool() => true,
|
||||
CustomRoles.Jailor when Jailor.UsePet.GetBool() => true,
|
||||
CustomRoles.Sheriff when Sheriff.UsePet.GetBool() => true,
|
||||
CustomRoles.SwordsMan when SwordsMan.UsePet.GetBool() => true,
|
||||
@@ -678,7 +686,9 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Tunneler,
|
||||
CustomRoles.Tornado,
|
||||
CustomRoles.Swiftclaw,
|
||||
CustomRoles.Adventurer
|
||||
CustomRoles.Adventurer,
|
||||
CustomRoles.Sentry,
|
||||
CustomRoles.Cherokious
|
||||
];
|
||||
|
||||
public static bool OnlySpawnsWithPets(this CustomRoles role) => OnlySpawnsWithPetsRoleList.Contains(role);
|
||||
@@ -737,6 +747,10 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Pickpocket or
|
||||
CustomRoles.TicketsStealer;
|
||||
|
||||
public static bool ForceCancelShapeshift(this CustomRoles role) => role is
|
||||
CustomRoles.Hangman or
|
||||
CustomRoles.Generator;
|
||||
|
||||
public static bool CheckAddonConflictV2(CustomRoles addon, CustomRoles mainRole) => addon.IsAdditionRole() && mainRole is not CustomRoles.GuardianAngelEHR and not CustomRoles.God and not CustomRoles.GM && addon switch
|
||||
{
|
||||
CustomRoles.Autopsy when mainRole is CustomRoles.Doctor or CustomRoles.Tracefinder or CustomRoles.Scientist or CustomRoles.ScientistEHR or CustomRoles.Sunnyboy => false,
|
||||
@@ -1171,8 +1185,10 @@ internal static class CustomRolesHelper
|
||||
CustomRoles.Refugee => CountTypes.Impostor,
|
||||
CustomRoles.Glitch => CountTypes.Glitch,
|
||||
CustomRoles.Spiritcaller => CountTypes.Spiritcaller,
|
||||
CustomRoles.Cherokious => CountTypes.Cherokious,
|
||||
CustomRoles.DarkHide => DarkHide.SnatchesWin.GetBool() ? CountTypes.Crew : CountTypes.DarkHide,
|
||||
CustomRoles.Arsonist => !Options.ArsonistCanIgniteAnytime.GetBool() ? CountTypes.Crew : CountTypes.Arsonist,
|
||||
CustomRoles.SchrodingersCat => SchrodingersCat.WinsWithCrewIfNotAttacked.GetBool() ? CountTypes.Crew : CountTypes.OutOfGame,
|
||||
|
||||
_ => role.Is(Team.Impostor) ? CountTypes.Impostor : CountTypes.Crew
|
||||
};
|
||||
@@ -1321,5 +1337,6 @@ public enum CountTypes
|
||||
Pestilence,
|
||||
PlagueBearer,
|
||||
Glitch,
|
||||
Arsonist
|
||||
Arsonist,
|
||||
Cherokious
|
||||
}
|
||||
@@ -86,26 +86,33 @@ namespace EHR.Modules
|
||||
{
|
||||
if (CustomTeams.Count == 0 || CustomTeamPlayerIds.Count == 0) return false;
|
||||
|
||||
CustomTeamPlayerIds.Do(x => x.Value.RemoveWhere(p =>
|
||||
try
|
||||
{
|
||||
var pc = Utils.GetPlayerById(p);
|
||||
return pc == null || pc.Data.Disconnected;
|
||||
}));
|
||||
|
||||
var aliveTeamPlayers = CustomTeamPlayerIds.ToDictionary(x => x.Key, x => x.Value);
|
||||
aliveTeamPlayers.Do(x => x.Value.RemoveWhere(p => !Utils.GetPlayerById(p).IsAlive()));
|
||||
|
||||
var team = aliveTeamPlayers.Keys.First();
|
||||
if (aliveTeamPlayers.Count == 1 && Main.AllAlivePlayerControls.All(x =>
|
||||
CustomTeamPlayerIds.Do(x => x.Value.RemoveWhere(p =>
|
||||
{
|
||||
var customTeam = GetCustomTeam(x.PlayerId);
|
||||
return customTeam != null && customTeam.Equals(team);
|
||||
}))
|
||||
var pc = Utils.GetPlayerById(p);
|
||||
return pc == null || pc.Data.Disconnected;
|
||||
}));
|
||||
|
||||
var aliveTeamPlayers = CustomTeamPlayerIds.ToDictionary(x => x.Key, x => x.Value);
|
||||
aliveTeamPlayers.Do(x => x.Value.RemoveWhere(p => !Utils.GetPlayerById(p).IsAlive()));
|
||||
|
||||
var team = aliveTeamPlayers.Keys.First();
|
||||
if (aliveTeamPlayers.Count == 1 && Main.AllAlivePlayerControls.All(x =>
|
||||
{
|
||||
var customTeam = GetCustomTeam(x.PlayerId);
|
||||
return customTeam != null && customTeam.Equals(team);
|
||||
}))
|
||||
{
|
||||
WinnerTeam = team;
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.CustomTeam);
|
||||
CustomWinnerHolder.WinnerIds = aliveTeamPlayers.Values.First();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
WinnerTeam = team;
|
||||
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.CustomTeam);
|
||||
CustomWinnerHolder.WinnerIds = aliveTeamPlayers.Values.First();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -256,22 +256,23 @@ static class ExtendedPlayerControl
|
||||
public static float GetAbilityUseLimit(this PlayerControl pc) => Main.AbilityUseLimit.GetValueOrDefault(pc.PlayerId, float.NaN);
|
||||
public static float GetAbilityUseLimit(this byte playerId) => Main.AbilityUseLimit.GetValueOrDefault(playerId, float.NaN);
|
||||
|
||||
public static void RpcRemoveAbilityUse(this PlayerControl pc)
|
||||
public static void RpcRemoveAbilityUse(this PlayerControl pc, bool log = true)
|
||||
{
|
||||
float current = pc.GetAbilityUseLimit();
|
||||
if (float.IsNaN(current) || current <= 0f) return;
|
||||
pc.SetAbilityUseLimit(current - 1);
|
||||
pc.SetAbilityUseLimit(current - 1, log: log);
|
||||
}
|
||||
public static void RpcIncreaseAbilityUseLimitBy(this PlayerControl pc, float get)
|
||||
|
||||
public static void RpcIncreaseAbilityUseLimitBy(this PlayerControl pc, float get, bool log = true)
|
||||
{
|
||||
float current = pc.GetAbilityUseLimit();
|
||||
if (float.IsNaN(current)) return;
|
||||
pc.SetAbilityUseLimit(current + get);
|
||||
pc.SetAbilityUseLimit(current + get, log: log);
|
||||
}
|
||||
|
||||
public static void SetAbilityUseLimit(this PlayerControl pc, float limit, bool rpc = true) => pc.PlayerId.SetAbilityUseLimit(limit, rpc);
|
||||
public static void SetAbilityUseLimit(this PlayerControl pc, float limit, bool rpc = true, bool log = true) => pc.PlayerId.SetAbilityUseLimit(limit, rpc, log);
|
||||
|
||||
public static void SetAbilityUseLimit(this byte playerId, float limit, bool rpc = true)
|
||||
public static void SetAbilityUseLimit(this byte playerId, float limit, bool rpc = true, bool log = true)
|
||||
{
|
||||
if (float.IsNaN(limit) || limit is < 0f or > 100f || (Main.AbilityUseLimit.TryGetValue(playerId, out var beforeLimit) && Math.Abs(beforeLimit - limit) < 0.01f)) return;
|
||||
|
||||
@@ -287,7 +288,7 @@ static class ExtendedPlayerControl
|
||||
|
||||
var pc = GetPlayerById(playerId);
|
||||
NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
Logger.Info($" {pc.GetNameWithRole()} => {Math.Round(limit, 1)}", "SetAbilityUseLimit");
|
||||
if (log) Logger.Info($" {pc.GetNameWithRole()} => {Math.Round(limit, 1)}", "SetAbilityUseLimit");
|
||||
}
|
||||
|
||||
public static void Suicide(this PlayerControl pc, PlayerState.DeathReason deathReason = PlayerState.DeathReason.Suicide, PlayerControl realKiller = null)
|
||||
|
||||
@@ -71,7 +71,7 @@ public static class NameColorManager
|
||||
}
|
||||
|
||||
// Custom Teams
|
||||
if (CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId)) color = Main.RoleColors[target.GetCustomRole()];
|
||||
if (CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && Options.CTAPlayersCanSeeEachOthersRoles.GetBool()) color = Main.RoleColors[target.GetCustomRole()];
|
||||
|
||||
// Add-ons
|
||||
if (seer.Is(CustomRoles.Rogue) && target.Is(CustomRoles.Rogue) && Options.RogueKnowEachOther.GetBool()) color = Main.RoleColors[CustomRoles.Rogue];
|
||||
|
||||
+36
-6
@@ -217,6 +217,7 @@ public static class Options
|
||||
public static OptionItem DisableShieldAnimations;
|
||||
public static OptionItem DisableCrackedGlass;
|
||||
public static OptionItem DisableShapeshiftAnimations;
|
||||
public static OptionItem DisableAllShapeshiftAnimations;
|
||||
public static OptionItem DisableKillAnimationOnGuess;
|
||||
public static OptionItem DisableVanillaRoles;
|
||||
public static OptionItem SabotageCooldownControl;
|
||||
@@ -870,6 +871,9 @@ public static class Options
|
||||
public static OptionItem EndWhenPlayerBug;
|
||||
public static OptionItem RemovePetsAtDeadPlayers;
|
||||
|
||||
public static OptionItem CTAPlayersCanWinWithOriginalTeam;
|
||||
public static OptionItem CTAPlayersCanSeeEachOthersRoles;
|
||||
|
||||
public static OptionItem UsePets;
|
||||
public static OptionItem PetToAssignToEveryone;
|
||||
public static OptionItem UseVoteCancelling;
|
||||
@@ -1618,6 +1622,10 @@ public static class Options
|
||||
DisableShapeshiftAnimations = BooleanOptionItem.Create(22604, "DisableShapeshiftAnimations", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
|
||||
DisableAllShapeshiftAnimations = BooleanOptionItem.Create(22605, "DisableAllShapeshiftAnimations", false, TabGroup.GameSettings, false)
|
||||
.SetParent(DisableShapeshiftAnimations)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
|
||||
DisableVanillaRoles = BooleanOptionItem.Create(22600, "DisableVanillaRoles", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
|
||||
@@ -1750,7 +1758,7 @@ public static class Options
|
||||
.SetColor(new Color32(255, 153, 153, byte.MaxValue));
|
||||
|
||||
|
||||
//Disable Short Tasks
|
||||
// Disable Short Tasks
|
||||
DisableShortTasks = BooleanOptionItem.Create(23000, "DisableShortTasks", false, TabGroup.TaskSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
@@ -1870,7 +1878,7 @@ public static class Options
|
||||
LoadingPercentage = 84;
|
||||
|
||||
|
||||
//Disable Common Tasks
|
||||
// Disable Common Tasks
|
||||
DisableCommonTasks = BooleanOptionItem.Create(23100, "DisableCommonTasks", false, TabGroup.TaskSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(239, 89, 175, byte.MaxValue));
|
||||
@@ -1913,7 +1921,7 @@ public static class Options
|
||||
|
||||
LoadingPercentage = 85;
|
||||
|
||||
//Disable Long Tasks
|
||||
// Disable Long Tasks
|
||||
DisableLongTasks = BooleanOptionItem.Create(23150, "DisableLongTasks", false, TabGroup.TaskSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(239, 89, 175, byte.MaxValue));
|
||||
@@ -2002,7 +2010,7 @@ public static class Options
|
||||
LoadingPercentage = 89;
|
||||
|
||||
|
||||
//Disable Divert Power, Weather Nodes etc. situational Tasks
|
||||
// Disable Divert Power, Weather Nodes etc. situational Tasks
|
||||
DisableOtherTasks = BooleanOptionItem.Create(23200, "DisableOtherTasks", false, TabGroup.TaskSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(239, 89, 175, byte.MaxValue));
|
||||
@@ -2074,13 +2082,28 @@ public static class Options
|
||||
MainLoadingText = "Building game settings";
|
||||
|
||||
|
||||
TextOptionItem.Create(100027, "MenuTitle.Meeting", TabGroup.GameSettings)
|
||||
TextOptionItem.Create(100027, "MenuTitle.CTA", TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(215, 227, 84, byte.MaxValue));
|
||||
|
||||
CTAPlayersCanWinWithOriginalTeam = BooleanOptionItem.Create(23550, "CTA.PlayersCanWinWithOriginalTeam", false, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(215, 227, 84, byte.MaxValue));
|
||||
CTAPlayersCanSeeEachOthersRoles = BooleanOptionItem.Create(23551, "CTA.PlayersCanSeeEachOthersRoles", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetColor(new Color32(215, 227, 84, byte.MaxValue));
|
||||
|
||||
|
||||
TextOptionItem.Create(100037, "MenuTitle.Meeting", TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(147, 241, 240, byte.MaxValue));
|
||||
|
||||
SyncButtonMode = BooleanOptionItem.Create(23300, "SyncButtonMode", false, TabGroup.GameSettings, false)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(147, 241, 240, byte.MaxValue))
|
||||
.SetHeader(true)
|
||||
.SetGameMode(CustomGameMode.Standard);
|
||||
SyncedButtonCount = IntegerOptionItem.Create(23310, "SyncedButtonCount", new(0, 100, 1), 10, TabGroup.GameSettings, false)
|
||||
.SetParent(SyncButtonMode)
|
||||
@@ -2144,9 +2167,11 @@ public static class Options
|
||||
|
||||
TextOptionItem.Create(100028, "MenuTitle.Other", TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(193, 255, 209, byte.MaxValue));
|
||||
|
||||
LadderDeath = BooleanOptionItem.Create(23800, "LadderDeath", false, TabGroup.GameSettings, false)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(193, 255, 209, byte.MaxValue));
|
||||
LadderDeathChance = StringOptionItem.Create(23810, "LadderDeathChance", Rates[1..], 0, TabGroup.GameSettings, false)
|
||||
.SetParent(LadderDeath);
|
||||
@@ -2180,6 +2205,7 @@ public static class Options
|
||||
|
||||
TextOptionItem.Create(100029, "MenuTitle.Ghost", TabGroup.GameSettings)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(217, 218, 255, byte.MaxValue));
|
||||
|
||||
LoadingPercentage = 99;
|
||||
@@ -2187,6 +2213,7 @@ public static class Options
|
||||
|
||||
GhostCanSeeOtherRoles = BooleanOptionItem.Create(24300, "GhostCanSeeOtherRoles", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
.SetHeader(true)
|
||||
.SetColor(new Color32(217, 218, 255, byte.MaxValue));
|
||||
GhostCanSeeOtherVotes = BooleanOptionItem.Create(24400, "GhostCanSeeOtherVotes", true, TabGroup.GameSettings, false)
|
||||
.SetGameMode(CustomGameMode.Standard)
|
||||
@@ -2243,6 +2270,8 @@ public static class Options
|
||||
CustomRoleCounts.Add(role, countOption);
|
||||
}
|
||||
|
||||
public static HashSet<CustomRoles> SingleRoles = [];
|
||||
|
||||
public static void SetupSingleRoleOptions(int id, TabGroup tab, CustomRoles role, int count = 1, CustomGameMode customGameMode = CustomGameMode.Standard, bool zeroOne = false, bool hideMaxSetting = true)
|
||||
{
|
||||
var spawnOption = StringOptionItem.Create(id, role.ToString(), zeroOne ? RatesZeroOne : Rates, 0, tab, false).SetColor(Utils.GetRoleColor(role))
|
||||
@@ -2256,6 +2285,7 @@ public static class Options
|
||||
|
||||
CustomRoleSpawnChances.Add(role, spawnOption);
|
||||
CustomRoleCounts.Add(role, countOption);
|
||||
SingleRoles.Add(role);
|
||||
}
|
||||
|
||||
public static OptionItem CreateCDSetting(int id, TabGroup tab, CustomRoles role, bool isKCD = false) =>
|
||||
|
||||
+31
-10
@@ -528,6 +528,7 @@ public static class Utils
|
||||
case CustomRoles.Doppelganger:
|
||||
case CustomRoles.PlagueDoctor:
|
||||
case CustomRoles.Postman:
|
||||
case CustomRoles.SchrodingersCat:
|
||||
case CustomRoles.Impartial:
|
||||
case CustomRoles.Predator:
|
||||
case CustomRoles.Reckless:
|
||||
@@ -586,7 +587,7 @@ public static class Utils
|
||||
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.Analyst when !Options.UsePets.GetBool() || !Analyst.UsePet.GetBool():
|
||||
case CustomRoles.Witness when !Options.UsePets.GetBool() || !Options.WitnessUsePet.GetBool():
|
||||
case CustomRoles.Pursuer:
|
||||
case CustomRoles.Spiritcaller:
|
||||
@@ -606,6 +607,7 @@ public static class Utils
|
||||
if (ForRecompute)
|
||||
hasTasks = false;
|
||||
break;
|
||||
case CustomRoles.Cherokious:
|
||||
case CustomRoles.Crewpostor:
|
||||
if (ForRecompute && !p.IsDead)
|
||||
hasTasks = false;
|
||||
@@ -703,7 +705,7 @@ public static class Utils
|
||||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoles.Crewpostor) && Options.AlliesKnowCrewpostor.GetBool() ||
|
||||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoleTypes.Impostor) && Options.ImpKnowAlliesRole.GetBool() ||
|
||||
__instance.Is(CustomRoleTypes.Impostor) && PlayerControl.LocalPlayer.Is(CustomRoles.Madmate) && Options.MadmateKnowWhosImp.GetBool() ||
|
||||
CustomTeamManager.AreInSameCustomTeam(__instance.PlayerId, PlayerControl.LocalPlayer.PlayerId) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(__instance.PlayerId, PlayerControl.LocalPlayer.PlayerId) && Options.CTAPlayersCanSeeEachOthersRoles.GetBool() ||
|
||||
Adventurer.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Totocalcio.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
Romantic.KnowRole(PlayerControl.LocalPlayer, __instance) ||
|
||||
@@ -805,8 +807,15 @@ public static class Utils
|
||||
NonCompleteColor = Workhorse.RoleColor;
|
||||
|
||||
var NormalColor = taskState.IsTaskFinished ? TaskCompleteColor : NonCompleteColor;
|
||||
if (Main.PlayerStates.TryGetValue(playerId, out var ps) && ps.MainRole == CustomRoles.Crewpostor)
|
||||
NormalColor = Color.red;
|
||||
if (Main.PlayerStates.TryGetValue(playerId, out var ps))
|
||||
{
|
||||
NormalColor = ps.MainRole switch
|
||||
{
|
||||
CustomRoles.Crewpostor => Color.red,
|
||||
CustomRoles.Cherokious => GetRoleColor(CustomRoles.Cherokious),
|
||||
_ => NormalColor
|
||||
};
|
||||
}
|
||||
|
||||
Color TextColor = comms ? Color.gray : NormalColor;
|
||||
string Completed = comms ? "?" : $"{taskState.CompletedTasksCount}";
|
||||
@@ -1620,6 +1629,7 @@ public static class Utils
|
||||
if (devUser.HasTag() || isMod)
|
||||
{
|
||||
string tag = devUser.GetTag();
|
||||
if (tag == "null") tag = string.Empty;
|
||||
if (player.AmOwner || player.IsModClient())
|
||||
name = tag + (isMod ? ("<size=1.4>" + GetString("ModeratorTag") + "\r\n</size>") : string.Empty) + name;
|
||||
else name = tag.Replace("\r\n", " - ") + (isMod ? ("<size=1.4>" + GetString("ModeratorTag") + " - </size>") : string.Empty) + name;
|
||||
@@ -1801,6 +1811,7 @@ public static class Utils
|
||||
SelfSuffix.Append(Deathpact.GetDeathpactPlayerArrow(seer));
|
||||
SelfSuffix.Append(Commander.GetSuffixText(seer, seer));
|
||||
SelfSuffix.Append(AntiAdminer.GetSuffixText(seer));
|
||||
SelfSuffix.Append(Roles.Impostor.Sentry.GetSuffix(seer));
|
||||
|
||||
switch (seer.GetCustomRole())
|
||||
{
|
||||
@@ -2105,10 +2116,10 @@ public static class Utils
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomRoles.Analyzer:
|
||||
if ((Main.PlayerStates[seer.PlayerId].Role as Analyzer).CurrentTarget.ID == target.PlayerId)
|
||||
case CustomRoles.Analyst:
|
||||
if ((Main.PlayerStates[seer.PlayerId].Role as Analyst).CurrentTarget.ID == target.PlayerId)
|
||||
{
|
||||
TargetMark.Append($"<color={GetRoleColorCode(CustomRoles.Analyzer)}>○</color>");
|
||||
TargetMark.Append($"<color={GetRoleColorCode(CustomRoles.Analyst)}>○</color>");
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2138,7 +2149,7 @@ public static class Utils
|
||||
(target.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && target.GetTaskState().IsTaskFinished) ||
|
||||
(seer.Is(CustomRoleTypes.Crewmate) && target.Is(CustomRoles.Marshall) && target.GetTaskState().IsTaskFinished) ||
|
||||
(Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(seer.PlayerId, target.PlayerId) && Options.CTAPlayersCanSeeEachOthersRoles.GetBool() ||
|
||||
Adventurer.KnowRole(seer, target) ||
|
||||
Totocalcio.KnowRole(seer, target) ||
|
||||
Romantic.KnowRole(seer, target) ||
|
||||
@@ -2391,6 +2402,7 @@ public static class Utils
|
||||
CustomRoles.Tornado => Tornado.TornadoCooldown.GetInt(),
|
||||
CustomRoles.Sentinel => Sentinel.PatrolCooldown.GetInt(),
|
||||
CustomRoles.Druid => Druid.VentCooldown.GetInt(),
|
||||
CustomRoles.Sentry => Roles.Impostor.Sentry.ShowInfoCooldown.GetInt(),
|
||||
CustomRoles.Sniper => Options.DefaultShapeshiftCooldown.GetInt(),
|
||||
CustomRoles.Assassin => Assassin.AssassinateCooldownOpt.GetInt(),
|
||||
CustomRoles.Undertaker => Undertaker.UndertakerAssassinateCooldown.GetInt(),
|
||||
@@ -2405,6 +2417,7 @@ public static class Utils
|
||||
CustomRoles.Warlock => Warlock.IsCursed ? -1 : (int)Options.DefaultKillCooldown,
|
||||
CustomRoles.Swiftclaw => Swiftclaw.DashCD.GetInt() + (includeDuration ? Swiftclaw.DashDuration.GetInt() : 0),
|
||||
CustomRoles.Tiger => Tiger.EnrageCooldown.GetInt() + (includeDuration ? Tiger.EnrageDuration.GetInt() : 0),
|
||||
CustomRoles.Cherokious => Cherokious.KillCooldown.GetInt(),
|
||||
_ => -1,
|
||||
};
|
||||
if (CD == -1) return;
|
||||
@@ -2563,6 +2576,7 @@ public static class Utils
|
||||
Vulture.OnPlayerDead(target);
|
||||
Tracker.OnPlayerDeath(target);
|
||||
Adventurer.OnAnyoneDead(target);
|
||||
Roles.Impostor.Sentry.OnAnyoneMurder(target);
|
||||
|
||||
FixedUpdatePatch.LoversSuicide(target.PlayerId, onMeeting);
|
||||
}
|
||||
@@ -2690,8 +2704,15 @@ public static class Utils
|
||||
NonCompleteColor = Workhorse.RoleColor;
|
||||
|
||||
var NormalColor = taskState.IsTaskFinished ? TaskCompleteColor : NonCompleteColor;
|
||||
if (Main.PlayerStates.TryGetValue(id, out var ps) && ps.MainRole == CustomRoles.Crewpostor)
|
||||
NormalColor = Color.red;
|
||||
if (Main.PlayerStates.TryGetValue(id, out var ps))
|
||||
{
|
||||
NormalColor = ps.MainRole switch
|
||||
{
|
||||
CustomRoles.Crewpostor => Color.red,
|
||||
CustomRoles.Cherokious => GetRoleColor(CustomRoles.Cherokious),
|
||||
_ => NormalColor
|
||||
};
|
||||
}
|
||||
|
||||
Color TextColor = NormalColor;
|
||||
string Completed = $"{taskState.CompletedTasksCount}";
|
||||
|
||||
@@ -297,7 +297,7 @@ internal class ChatCommands
|
||||
case "ban":
|
||||
if (GetRoleByName(args[2], out CustomRoles mainRole) && GetRoleByName(args[3], out CustomRoles addOn))
|
||||
{
|
||||
if (mainRole.IsAdditionRole() || !addOn.IsAdditionRole()) break;
|
||||
if (mainRole.IsAdditionRole() || !addOn.IsAdditionRole() || addOn == CustomRoles.Lovers) break;
|
||||
if (args[1] == "add") Main.AlwaysSpawnTogetherCombos[mainRole] = addOn;
|
||||
else Main.NeverSpawnTogetherCombos[mainRole] = addOn;
|
||||
Utils.SendMessage(string.Format(args[1] == "add" ? GetString("ComboAdd") : GetString("ComboBan"), GetString(mainRole.ToString()), GetString(addOn.ToString())), localPlayerId);
|
||||
|
||||
@@ -183,6 +183,10 @@ class GameEndChecker
|
||||
WinnerIds.Add(pc.PlayerId);
|
||||
AdditionalWinnerTeams.Add(AdditionalWinners.SoulHunter);
|
||||
break;
|
||||
case CustomRoles.SchrodingersCat when SchrodingersCat.WinsWithCrewIfNotAttacked.GetBool():
|
||||
WinnerIds.Add(pc.PlayerId);
|
||||
AdditionalWinnerTeams.Add(AdditionalWinners.SchrodingersCat);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +222,7 @@ class GameEndChecker
|
||||
.Do(p => WinnerIds.Add(p.PlayerId));
|
||||
}
|
||||
|
||||
if (WinnerTeam != CustomWinner.CustomTeam)
|
||||
if (WinnerTeam != CustomWinner.CustomTeam && !Options.CTAPlayersCanWinWithOriginalTeam.GetBool())
|
||||
{
|
||||
WinnerIds.RemoveWhere(x => CustomTeamManager.GetCustomTeam(x) != null);
|
||||
}
|
||||
@@ -282,7 +286,7 @@ class GameEndChecker
|
||||
continue;
|
||||
}
|
||||
|
||||
bool canWin = WinnerIds.Contains(pc.PlayerId) || WinnerRoles.Contains(pc.GetCustomRole());
|
||||
bool canWin = WinnerIds.Contains(pc.PlayerId) || WinnerRoles.Contains(pc.GetCustomRole()) || (winner == CustomWinner.Bloodlust && pc.Is(CustomRoles.Bloodlust));
|
||||
bool isCrewmateWin = reason.Equals(GameOverReason.HumansByVote) || reason.Equals(GameOverReason.HumansByTask);
|
||||
SetGhostRole(ToGhostImpostor: canWin ^ isCrewmateWin); // XOR
|
||||
|
||||
@@ -524,25 +528,21 @@ class GameEndChecker
|
||||
|
||||
if (FFAManager.FFATeamMode.GetBool())
|
||||
{
|
||||
var firstTeam = FFAManager.PlayerTeams.GroupBy(x => x.Value, x => x.Key).Select(x => x.Where(p =>
|
||||
var teams = FFAManager.PlayerTeams.GroupBy(x => x.Value, x => x.Key).Select(x => x.Where(p =>
|
||||
{
|
||||
var pc = GetPlayerById(p);
|
||||
return pc != null && !pc.Data.Disconnected;
|
||||
}).ToHashSet()).FirstOrDefault(x => x.Count > 0);
|
||||
}).ToHashSet()).Where(x => x.Count > 0);
|
||||
|
||||
if (firstTeam == null)
|
||||
foreach (var team in teams)
|
||||
{
|
||||
FFAManager.RoundTime = 0;
|
||||
Logger.Warn("No players alive. Force ending the game", "FFA");
|
||||
return false;
|
||||
}
|
||||
if (Main.AllAlivePlayerControls.All(x => team.Contains(x.PlayerId)))
|
||||
{
|
||||
WinnerIds = team;
|
||||
|
||||
if (Main.AllAlivePlayerControls.All(x => firstTeam.Contains(x.PlayerId)))
|
||||
{
|
||||
WinnerIds = firstTeam;
|
||||
|
||||
Main.DoBlockNameChange = true;
|
||||
return true;
|
||||
Main.DoBlockNameChange = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -203,7 +203,7 @@ class HudManagerPatch
|
||||
case CustomRoles.Pelican:
|
||||
__instance.KillButton?.OverrideText(GetString("PelicanButtonText"));
|
||||
break;
|
||||
case CustomRoles.Analyzer:
|
||||
case CustomRoles.Analyst:
|
||||
usedButton?.OverrideText(GetString("AnalyzerKillButtonText"));
|
||||
break;
|
||||
case CustomRoles.Pursuer:
|
||||
@@ -569,8 +569,6 @@ class SetHudActivePatch
|
||||
case CustomRoles.SwordsMan:
|
||||
case CustomRoles.Deputy:
|
||||
case CustomRoles.Monarch:
|
||||
//case CustomRoles.NWitch:
|
||||
//case CustomRoles.Reverie:
|
||||
case CustomRoles.Pelican:
|
||||
case CustomRoles.FFF:
|
||||
case CustomRoles.Medic:
|
||||
|
||||
@@ -238,7 +238,7 @@ public static class HudSpritePatch
|
||||
else
|
||||
newPetButton = CustomButton.Get("Mine");
|
||||
break;
|
||||
case CustomRoles.Analyzer:
|
||||
case CustomRoles.Analyst:
|
||||
case CustomRoles.Witness:
|
||||
newKillButton = CustomButton.Get("Examine");
|
||||
break;
|
||||
|
||||
@@ -796,7 +796,7 @@ class MeetingHudStartPatch
|
||||
(pc.Is(CustomRoles.Mayor) && Mayor.MayorRevealWhenDoneTasks.GetBool() && pc.GetTaskState().IsTaskFinished) ||
|
||||
(pc.Is(CustomRoles.Marshall) && PlayerControl.LocalPlayer.Is(CustomRoleTypes.Crewmate) && pc.GetTaskState().IsTaskFinished) ||
|
||||
(Main.PlayerStates[pc.PlayerId].deathReason == PlayerState.DeathReason.Vote && Options.SeeEjectedRolesInMeeting.GetBool()) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId) ||
|
||||
CustomTeamManager.AreInSameCustomTeam(pc.PlayerId, PlayerControl.LocalPlayer.PlayerId) && Options.CTAPlayersCanSeeEachOthersRoles.GetBool() ||
|
||||
Adventurer.KnowRole(PlayerControl.LocalPlayer, pc) ||
|
||||
Totocalcio.KnowRole(PlayerControl.LocalPlayer, pc) ||
|
||||
Romantic.KnowRole(PlayerControl.LocalPlayer, pc) ||
|
||||
|
||||
@@ -506,11 +506,11 @@ class MurderPlayerPatch
|
||||
|
||||
if (Main.PlayerStates[target.PlayerId].deathReason == PlayerState.DeathReason.etc)
|
||||
{
|
||||
//If the cause of death is not specified, it is determined as a normal kill.
|
||||
// If the cause of death is not specified, it is determined as a normal kill.
|
||||
Main.PlayerStates[target.PlayerId].deathReason = PlayerState.DeathReason.Kill;
|
||||
}
|
||||
|
||||
//Let’s see if Youtuber was stabbed first
|
||||
// Let’s see if Youtuber was stabbed first
|
||||
if (Main.FirstDied == byte.MaxValue && target.Is(CustomRoles.Youtuber))
|
||||
{
|
||||
CustomSoundsManager.RPCPlayCustomSoundAll("Congrats");
|
||||
@@ -518,7 +518,7 @@ class MurderPlayerPatch
|
||||
CustomWinnerHolder.WinnerIds.Add(target.PlayerId);
|
||||
}
|
||||
|
||||
//Record the first blow
|
||||
// Record the first blow
|
||||
if (Main.FirstDied == byte.MaxValue)
|
||||
Main.FirstDied = target.PlayerId;
|
||||
|
||||
@@ -530,9 +530,6 @@ class MurderPlayerPatch
|
||||
if (target.Is(CustomRoles.Stained))
|
||||
Stained.OnDeath(target, killer);
|
||||
|
||||
//if ((Romantic.BetPlayer.TryGetValue(target.PlayerId, out var RomanticPartner) && target.PlayerId == RomanticPartner) && target.PlayerId != killer.PlayerId)
|
||||
// VengefulRomantic.PartnerKiller.Add(killer.PlayerId, 1);
|
||||
|
||||
Witness.AllKillers.Remove(killer.PlayerId);
|
||||
Witness.AllKillers.Add(killer.PlayerId, TimeStamp);
|
||||
|
||||
@@ -685,8 +682,20 @@ class ShapeshiftPatch
|
||||
isSSneeded = false;
|
||||
}
|
||||
|
||||
bool forceCancel = shapeshifter.GetCustomRole().ForceCancelShapeshift();
|
||||
|
||||
if (shapeshifter.Is(CustomRoles.Camouflager) && !shapeshifting) Camouflager.Reset();
|
||||
if (Changeling.ChangedRole.TryGetValue(shapeshifter.PlayerId, out var changed) && changed && shapeshifter.GetRoleTypes() != RoleTypes.Shapeshifter) isSSneeded = false;
|
||||
if (Changeling.ChangedRole.TryGetValue(shapeshifter.PlayerId, out var changed) && changed && shapeshifter.GetRoleTypes() != RoleTypes.Shapeshifter)
|
||||
{
|
||||
forceCancel = true;
|
||||
isSSneeded = false;
|
||||
}
|
||||
|
||||
bool shouldCancel = Options.DisableShapeshiftAnimations.GetBool();
|
||||
bool shouldAlwaysCancel = shouldCancel && Options.DisableAllShapeshiftAnimations.GetBool();
|
||||
|
||||
isSSneeded &= !shouldAlwaysCancel;
|
||||
forceCancel |= shouldAlwaysCancel;
|
||||
|
||||
// Forced rewriting in case the name cannot be corrected due to the timing of canceling the transformation being off.
|
||||
if (!shapeshifting && !shapeshifter.Is(CustomRoles.Glitch) && isSSneeded)
|
||||
@@ -706,7 +715,7 @@ class ShapeshiftPatch
|
||||
NotifyRoles(SpecifySeer: shapeshifter, SpecifyTarget: shapeshifter);
|
||||
}
|
||||
|
||||
return isSSneeded || !Options.DisableShapeshiftAnimations.GetBool() || !shapeshifting;
|
||||
return isSSneeded || (!shouldCancel && !forceCancel) || (!shapeshifting && !shouldAlwaysCancel);
|
||||
}
|
||||
|
||||
// Tasks that should run when someone performs a shapeshift (with the egg animation) should be here.
|
||||
@@ -723,14 +732,28 @@ class ShapeshiftPatch
|
||||
pc.Notify(shapeshifting ? GetString("ShiftguardNotifySS") : "ShiftguardNotifyUnshift");
|
||||
}
|
||||
|
||||
if (Main.PlayerStates[pc.PlayerId].Role is Adventurer { IsEnable: true } av)
|
||||
switch (Main.PlayerStates[pc.PlayerId].Role)
|
||||
{
|
||||
Adventurer.OnAnyoneShapeshiftLoop(av, __instance);
|
||||
case Adventurer av:
|
||||
Adventurer.OnAnyoneShapeshiftLoop(av, __instance);
|
||||
break;
|
||||
case Roles.Impostor.Sentry st:
|
||||
st.OnAnyoneShapeshiftLoop(__instance);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.RpcShapeshift))]
|
||||
class RpcShapeshiftPatch
|
||||
{
|
||||
public static void Postfix(PlayerControl __instance, [HarmonyArgument(0)] PlayerControl target)
|
||||
{
|
||||
Main.CheckShapeshift[__instance.PlayerId] = __instance.PlayerId != target.PlayerId;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.ReportDeadBody))]
|
||||
class ReportDeadBodyPatch
|
||||
{
|
||||
@@ -1377,10 +1400,10 @@ class FixedUpdatePatch
|
||||
}
|
||||
|
||||
break;
|
||||
case CustomRoles.Analyzer:
|
||||
if ((Main.PlayerStates[seer.PlayerId].Role as Analyzer).CurrentTarget.ID == target.PlayerId)
|
||||
case CustomRoles.Analyst:
|
||||
if ((Main.PlayerStates[seer.PlayerId].Role as Analyst).CurrentTarget.ID == target.PlayerId)
|
||||
{
|
||||
Mark.Append($"<color={GetRoleColorCode(CustomRoles.Analyzer)}>○</color>");
|
||||
Mark.Append($"<color={GetRoleColorCode(CustomRoles.Analyst)}>○</color>");
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -1493,9 +1516,12 @@ class FixedUpdatePatch
|
||||
Suffix.Append(Deathpact.GetDeathpactPlayerArrow(seer, target));
|
||||
Suffix.Append(Deathpact.GetDeathpactMark(seer, target));
|
||||
|
||||
if (self) Suffix.Append(AntiAdminer.GetSuffixText(seer));
|
||||
|
||||
if (seer.Is(CustomRoles.Asthmatic) && self) Suffix.Append(Asthmatic.GetSuffixText(seer.PlayerId));
|
||||
if (self)
|
||||
{
|
||||
Suffix.Append(AntiAdminer.GetSuffixText(seer));
|
||||
Suffix.Append(Roles.Impostor.Sentry.GetSuffix(seer));
|
||||
if (seer.Is(CustomRoles.Asthmatic)) Suffix.Append(Asthmatic.GetSuffixText(seer.PlayerId));
|
||||
}
|
||||
|
||||
if (target.Is(CustomRoles.Librarian)) Suffix.Append(Librarian.GetNameTextForSuffix(target.PlayerId));
|
||||
|
||||
@@ -1690,7 +1716,8 @@ class EnterVentPatch
|
||||
}
|
||||
|
||||
Drainer.OnAnyoneEnterVent(pc, __instance);
|
||||
Analyzer.OnAnyoneEnterVent(pc);
|
||||
Analyst.OnAnyoneEnterVent(pc);
|
||||
Roles.Impostor.Sentry.OnAnyoneEnterVent(pc);
|
||||
|
||||
switch (pc.GetCustomRole())
|
||||
{
|
||||
|
||||
@@ -261,7 +261,7 @@ public static class SabotageSystemTypeRepairDamagePatch
|
||||
}
|
||||
|
||||
if (player.Is(CustomRoleTypes.Impostor) && !player.IsAlive() && Options.DeadImpCantSabotage.GetBool()) return false;
|
||||
if (player.Is(CustomRoleTypes.Impostor) && (player.IsAlive() || !Options.DeadImpCantSabotage.GetBool()) && !player.Is(CustomRoles.Minimalism) && !player.Is(CustomRoles.Mafioso)) return true;
|
||||
if (player.Is(CustomRoleTypes.Impostor) && (player.IsAlive() || !Options.DeadImpCantSabotage.GetBool()) && player.GetCustomRole() is not CustomRoles.Minimalism and not CustomRoles.Mafioso and not CustomRoles.Generator) return true;
|
||||
return player.GetCustomRole() switch
|
||||
{
|
||||
CustomRoles.Jackal when Jackal.CanSabotage.GetBool() => true,
|
||||
|
||||
@@ -596,7 +596,7 @@ internal class SelectRolesPatch
|
||||
GameOptionsSender.AllSenders.Add(new PlayerGameOptionsSender(pc));
|
||||
}
|
||||
|
||||
// Added players with unclassified roles to the list of players who require ResetCam.
|
||||
// Add players with unclassified roles to the list of players who require ResetCam.
|
||||
Main.ResetCamPlayerList.AddRange(Main.AllPlayerControls.Where(p => p.GetCustomRole() is CustomRoles.Arsonist or CustomRoles.Revolutionist or CustomRoles.Sidekick or CustomRoles.KB_Normal or CustomRoles.Killer or CustomRoles.Tasker or CustomRoles.Potato or CustomRoles.Seeker or CustomRoles.Hider or CustomRoles.Fox or CustomRoles.Troll or CustomRoles.Innocent || (p.Is(CustomRoles.Witness) && (!Options.UsePets.GetBool() || Options.WitnessUsePet.GetBool()))).Select(p => p.PlayerId));
|
||||
Utils.CountAlivePlayers(true);
|
||||
Utils.SyncAllSettings();
|
||||
|
||||
@@ -134,7 +134,7 @@
|
||||
- Tunneler (Crewmate)
|
||||
- Detour (Crewmate)
|
||||
- Gaulois (Crewmate)
|
||||
- Analyzer (Crewmate)
|
||||
- Analyst (Crewmate)
|
||||
- Electric (Crewmate)
|
||||
- Mole (Crewmate)
|
||||
- Tornado (Crewmate)
|
||||
|
||||
@@ -1091,6 +1091,9 @@
|
||||
"DisableZiplineForImps": "Disable Zipline for <color=#ff1919>Impostors</color>",
|
||||
"DisableZiplineForNeutrals": "Disable Zipline for <color=#ffab1b>Neutrals</color>",
|
||||
"DisableShapeshiftAnimations": "Disable Shapeshift Animations",
|
||||
"DisableAllShapeshiftAnimations": "Disable All Shapeshift Animations",
|
||||
"CTA.PlayersCanWinWithOriginalTeam": "Custom Teamed Players Can Win With Their Original Team",
|
||||
"CTA.PlayersCanSeeEachOthersRoles": "Custom Teamed Players Can See Each Other's Roles",
|
||||
"AirshipVariableElectrical": "Variable Electrical (Airship)",
|
||||
"ApplyDenyNameList": "Apply DenyName List",
|
||||
"KickPlayerFriendCodeNotExist": "Kick players who are not logged in",
|
||||
@@ -1128,6 +1131,7 @@
|
||||
"MenuTitle.TaskSettings": "★ Task Management ★",
|
||||
"MenuTitle.Guessers": "★ Guesser Mode ★",
|
||||
"MenuTitle.GuesserModeRoles": "★ Roles and Add-ons for Guesser Mode ★",
|
||||
"MenuTitle.CTA": "★ Custom Team Assignment ★",
|
||||
"ShieldPersonDiedFirst": "Shield the person who got killed first in the last game",
|
||||
"JackalWinWithSidekick": "<color=#00b4eb>Jackal</color> can win with <color=#00b4eb>Sidekick</color>'s team",
|
||||
"SidekickKnowOtherSidekick": "<color=#00b4eb>Sidekicks</color> know each other",
|
||||
@@ -2615,6 +2619,24 @@
|
||||
"Transmitter": "Transmitter",
|
||||
"TransmitterInfo": "TP to nearest player by doing a task",
|
||||
"TransmitterInfoLong": "(Crewmates):\\nAs the Transmitter, when you complete a task, you teleport to the nearest player.",
|
||||
"Sentry": "Sentry",
|
||||
"SentryInfo": "Monitor a Room",
|
||||
"SentryInfoLong": "(Crewmates):\\nAs the Sentry, you can monitor a room by petting your pet. When you pet your pet in the future, you get information from that room, including:<size=80%>\\n- The players currently in that room\\n- Who is dead in that room (if any)\\n- The players that used a vent in that room\\n- Whether someone shapeshifted in that room</size>\\n\\nDepending on the settings, players may know if a room is monitored, and you may not be able to view this info during Comms Sabotages.",
|
||||
"Sentry.ShowInfoDuration": "Info is Visible for",
|
||||
"Sentry.PlayersKnowAboutCamera": "Players Know if the Room is Monitored",
|
||||
"Sentry.Suffix.MonitoredRoom": "<size=80%>This room is monitored by the {0}</size>",
|
||||
"Sentry.Suffix.Self": "<size=70%>Monitoring: <#00ffa5>{0}</color></size>",
|
||||
"Sentry.Notify.Info": "<u>Info about your monitored room:</u>\\nPlayers: {0}\\nDead players: {1}\\nPlayers that used a vent: {2}\\nShapeshifters: {3}",
|
||||
"Sentry.Notify.Info.NoData": "<#ff0000>none</color>",
|
||||
"SchrodingersCat": "Schrödinger's Cat",
|
||||
"SchrodingersCatInfo": "Get Attacked to Get a Role",
|
||||
"SchrodingersCatInfoLong": "(Neutrals):\\nAs Schrödinger's Cat, if you get attacked, you turn into the same role as your killer.\\nIf you don't get attacked, you lose, or you can win with crewmates, depending on the settings.",
|
||||
"SchrodingersCat.WinsWithCrewIfNotAttacked": "Wins with crewmates if not attacked",
|
||||
"SchrodingersCat.Notify.KillerRecruited": "You have recruited the {1}! {0} now has the same role as you.",
|
||||
"SchrodingersCat.Notify.RecruitedByKiller": "You have been recruited by the {1}! You now have the same role as {0}.",
|
||||
"Cherokious": "Cherokious",
|
||||
"CherokiousInfo": "Do tasks to get Bullets to Kill",
|
||||
"CherokiousInfoLong": "(Neutrals):\\nAs the Cherokious, you can get bullets by completing tasks. You can kill by petting your pet near someone. You can only kill if you have bullets.",
|
||||
"Autocrat": "Autocrat",
|
||||
"AutocratInfo": "TP nearest player to you by doing a task",
|
||||
"AutocratInfoLong": "(Crewmates):\\nAs the Autocrat, when you complete a task, you teleport the nearest player to you.",
|
||||
@@ -2829,9 +2851,9 @@
|
||||
"StealthDarkened": "Darkened: {0}",
|
||||
"StealthExcludeImpostors": "Ignore Impostors when Blinding",
|
||||
"StealthDarkenDuration": "Blinding Duration",
|
||||
"Analyzer": "Analyzer",
|
||||
"AnalyzerInfo": "Analyze Players to Get Information",
|
||||
"AnalyzerInfoLong": "(Crewmates):\\nAs the Analyzer, you may use your kill button on someone to analyze them. You will have to stand next to your target for a few seconds to complete the analysis. When the analysis is complete, you will see how many players they've killed so far, how many times they've vented so far, and their role basis.\\n\\nNote: If the host's settings don't allow you to see an information, the result will show 0 or nothing!\\nNote: None of these factors determine whether someone is evil or not! Think twice before judging too fast!",
|
||||
"Analyst": "Analyst",
|
||||
"AnalystInfo": "Analyze Players to Get Information",
|
||||
"AnalystInfoLong": "(Crewmates):\\nAs the Analyst, you may use your kill button on someone to analyze them. You will have to stand next to your target for a few seconds to complete the analysis. When the analysis is complete, you will see how many players they've killed so far, how many times they've vented so far, and their role basis.\\n\\nNote: If the host's settings don't allow you to see an information, the result will show 0 or nothing!\\nNote: None of these factors determine whether someone is evil or not! Think twice before judging too fast!",
|
||||
"AnalyzerCD": "Analyze Cooldown",
|
||||
"AnalyzerDur": "Analyze Time",
|
||||
"AnalyzerResult": "\\n\\nShowing analyzation result for <color=#00ffa5>{0}</color>:\\nKills: <color=#ff1919>{1}</color>, Vents: <color=#ffa500>{2}</color>, Role Basis: <color=#00ffff>{3}</color>",
|
||||
@@ -3319,6 +3341,19 @@
|
||||
"TrollInfoLong": "GET KILLED TO WIN",
|
||||
"TrollVision": "Troll Vision",
|
||||
"TrollSpeed": "Troll Speed",
|
||||
"Generator": "Generator",
|
||||
"GeneratorInfo": "Power up the ship",
|
||||
"GeneratorInfoLong": "(Impostors):\\nAs the Generator, you generate charges every second. You can only kill/vent/shapeshift/sabotage if you have enough charges to do so. You also lose charges while shapeshifted.",
|
||||
"Generator.ChargesGainedEverySecond": "Charges Gained Every Second",
|
||||
"Generator.StartingCharges": "Starting Charges",
|
||||
"Generator.ChargesLostWhileShiftedPerSecond": "Charges Lost While Shifted Per Second",
|
||||
"Generator.MaxChargesStored": "Maximum Charges Stored",
|
||||
"Generator.Kill.Cost": "Charges Needed to Kill",
|
||||
"Generator.Vent.Cost": "Charges Needed to Vent",
|
||||
"Generator.Sabotage.Cost": "Charges Needed to Sabotage",
|
||||
"Generator.Shapeshift.Cost": "Charges Needed to Shapeshift",
|
||||
"Generator.Notify.RevertShapeshift": "You ran out of charges, so shapeshifting was reverted",
|
||||
"Generator.Notify.NotEnoughCharges": "You don't have enough charges ({0}) to do that",
|
||||
"GNoCommandInfo": "<b>This Command can only be used when in lobby or after you die.</b>\\n\\ntype <b>/gno X</b> to play guess a number. X can be a number between 0 and 99 (both included). \\n\\nYou get maximum of <color=#ff0000>7 tries</color> to guess the number.\\n\\n Example:- <b>/gno 10</b>",
|
||||
"GNoLost": "Oh, you were so close! Just one more guess, and you might have deciphered the Da Vinci code! By the way, <color=#ff0000>the secret number was... {0}!</color> But hey, you were only off by a few billion possibilities. Better luck next time, Sherlock! ",
|
||||
"GNoLow": "Oh, you're really nailing this! It's so low, I almost need a shovel to dig it up!\\nYou have <color=#ff0000>{0} guesses</color> left!",
|
||||
|
||||
@@ -2820,9 +2820,9 @@
|
||||
"StealthDarkened": "Cegado: {0}",
|
||||
"StealthExcludeImpostors": "Ignorar Impostores ao Cegar",
|
||||
"StealthDarkenDuration": "Duração da Visão Zero",
|
||||
"Analyzer": "Analisador",
|
||||
"AnalyzerInfo": "Analize jogadores para obter Informações",
|
||||
"AnalyzerInfoLong": "(Tripulantes):\\nComo Analisador, você pode usar seu botão matar para analizar um jogador. Você deverá ficar ao lado do alvo por alguns segundos para concluir a analise. Quando a analise estiver completa, Você verá quantos jogadores ele matou, quantoas vezes ele entrou no duto e a sua função base.\\n\\nNota: Se as configurações do Anfitrião não permitirem você ver uma informação, o resultado será 0 ou nada!\\nNota: Nenhum destes fatores determinam se o jogador e maligno ou não! Pense duas vezes antes de acusar!",
|
||||
"Analyst": "Analisador",
|
||||
"AnalystInfo": "Analize jogadores para obter Informações",
|
||||
"AnalystInfoLong": "(Tripulantes):\\nComo Analisador, você pode usar seu botão matar para analizar um jogador. Você deverá ficar ao lado do alvo por alguns segundos para concluir a analise. Quando a analise estiver completa, Você verá quantos jogadores ele matou, quantoas vezes ele entrou no duto e a sua função base.\\n\\nNota: Se as configurações do Anfitrião não permitirem você ver uma informação, o resultado será 0 ou nada!\\nNota: Nenhum destes fatores determinam se o jogador e maligno ou não! Pense duas vezes antes de acusar!",
|
||||
"AnalyzerCD": "Recarga para analisar",
|
||||
"AnalyzerDur": "Duração da analise",
|
||||
"AnalyzerResult": "n\\nMostrando resultados da analise de <color=#00ffa5>{0}</color>:\\nAbates: <color=#ff1919>{1}</color>, Usou dutos: <color=#ffa500>{2}</color>, Função Base: <color=#00ffff>{3}</color>",
|
||||
|
||||
@@ -7,7 +7,7 @@ using static EHR.Translator;
|
||||
|
||||
namespace EHR.Roles.Crewmate
|
||||
{
|
||||
internal class Analyzer : RoleBase
|
||||
internal class Analyst : RoleBase
|
||||
{
|
||||
private const int Id = 643100;
|
||||
private static byte playerId = byte.MaxValue;
|
||||
@@ -20,32 +20,32 @@ namespace EHR.Roles.Crewmate
|
||||
private static OptionItem SeeRoleBasis;
|
||||
public static OptionItem UsePet;
|
||||
|
||||
private static readonly Dictionary<string, string> ReplacementDict = new() { { "Analyze", Utils.ColorString(Utils.GetRoleColor(CustomRoles.Analyzer), "Analyze") } };
|
||||
private static readonly Dictionary<string, string> ReplacementDict = new() { { "Analyze", Utils.ColorString(Utils.GetRoleColor(CustomRoles.Analyst), "Analyze") } };
|
||||
|
||||
public static Dictionary<byte, int> VentCount = [];
|
||||
public (byte ID, long TIME) CurrentTarget = (byte.MaxValue, Utils.TimeStamp);
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Analyzer);
|
||||
SetupRoleOptions(Id, TabGroup.CrewmateRoles, CustomRoles.Analyst);
|
||||
UseLimitOpt = IntegerOptionItem.Create(Id + 10, "AbilityUseLimit", new(0, 30, 1), 3, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer])
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyst])
|
||||
.SetValueFormat(OptionFormat.Times);
|
||||
CD = FloatOptionItem.Create(Id + 11, "AnalyzeCD", new(0f, 60f, 2.5f), 15f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer])
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyst])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
CD.ReplacementDictionary = ReplacementDict;
|
||||
Duration = IntegerOptionItem.Create(Id + 12, "AnalyzeDur", new(1, 30, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer])
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyst])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
Duration.ReplacementDictionary = ReplacementDict;
|
||||
SeeKillCount = BooleanOptionItem.Create(Id + 13, "AnalyzerSeeKillCount", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyst]);
|
||||
SeeVentCount = BooleanOptionItem.Create(Id + 14, "AnalyzerSeeVentCount", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyst]);
|
||||
SeeRoleBasis = BooleanOptionItem.Create(Id + 15, "AnalyzerSeeRoleBasis", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyzer]);
|
||||
UsePet = CreatePetUseSetting(Id + 16, CustomRoles.Analyzer);
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Analyst]);
|
||||
UsePet = CreatePetUseSetting(Id + 16, CustomRoles.Analyst);
|
||||
}
|
||||
|
||||
public override bool CanUseKillButton(PlayerControl pc) => CurrentTarget.ID == byte.MaxValue && pc.GetAbilityUseLimit() > 0;
|
||||
@@ -0,0 +1,156 @@
|
||||
using HarmonyLib;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace EHR.Roles.Impostor
|
||||
{
|
||||
internal class Sentry : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
public override bool IsEnable => On;
|
||||
|
||||
public static OptionItem ShowInfoCooldown;
|
||||
private static OptionItem ShowInfoDuration;
|
||||
private static OptionItem PlayersKnowAboutCamera;
|
||||
private static OptionItem AbilityUseLimit;
|
||||
public static OptionItem AbilityUseGainWithEachTaskCompleted;
|
||||
public static OptionItem AbilityChargesWhenFinishedTasks;
|
||||
|
||||
private PlainShipRoom MonitoredRoom;
|
||||
|
||||
private HashSet<byte> DeadBodiesInRoom;
|
||||
private HashSet<byte> PlayersVentedInRoom;
|
||||
private HashSet<byte> PlayersShiftedInRoom;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
const int id = 11370;
|
||||
Options.SetupRoleOptions(id, TabGroup.CrewmateRoles, CustomRoles.Sentry);
|
||||
ShowInfoCooldown = IntegerOptionItem.Create(id + 2, "AbilityCooldown", new(1, 60, 1), 15, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sentry])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
ShowInfoDuration = IntegerOptionItem.Create(id + 3, "Sentry.ShowInfoDuration", new(1, 60, 1), 5, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sentry])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
PlayersKnowAboutCamera = BooleanOptionItem.Create(id + 4, "Sentry.PlayersKnowAboutCamera", true, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sentry]);
|
||||
AbilityUseLimit = IntegerOptionItem.Create(id + 5, "AbilityUseLimit", new(0, 20, 1), 0, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sentry]);
|
||||
AbilityUseGainWithEachTaskCompleted = FloatOptionItem.Create(id + 6, "AbilityUseGainWithEachTaskCompleted", new(0.1f, 5f, 0.1f), 1f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sentry]);
|
||||
AbilityChargesWhenFinishedTasks = FloatOptionItem.Create(id + 7, "AbilityChargesWhenFinishedTasks", new(0.1f, 5f, 0.1f), 0.2f, TabGroup.CrewmateRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Sentry]);
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
MonitoredRoom = null;
|
||||
DeadBodiesInRoom = [];
|
||||
PlayersVentedInRoom = [];
|
||||
PlayersShiftedInRoom = [];
|
||||
playerId.SetAbilityUseLimit(AbilityUseLimit.GetInt());
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
if (MonitoredRoom == null || MonitoredRoom == default || MonitoredRoom == default(PlainShipRoom)) MonitoredRoom = pc.GetPlainShipRoom();
|
||||
else DisplayRoomInfo(pc);
|
||||
}
|
||||
|
||||
void DisplayRoomInfo(PlayerControl pc)
|
||||
{
|
||||
if (pc.GetAbilityUseLimit() < 1) return;
|
||||
pc.RpcRemoveAbilityUse();
|
||||
|
||||
var players = Main.AllAlivePlayerControls.Where(IsInMonitoredRoom).Select(x => Utils.ColorString(Main.PlayerColors[x.PlayerId], x.GetRealName())).Join();
|
||||
var bodies = GetColoredNames(DeadBodiesInRoom);
|
||||
var vented = GetColoredNames(PlayersVentedInRoom);
|
||||
var shifted = GetColoredNames(PlayersShiftedInRoom);
|
||||
|
||||
var noDataString = Translator.GetString("Sentry.Notify.Info.NoData");
|
||||
if (players.Length == 0) players = noDataString;
|
||||
if (bodies.Length == 0) bodies = noDataString;
|
||||
if (vented.Length == 0) vented = noDataString;
|
||||
if (shifted.Length == 0) shifted = noDataString;
|
||||
|
||||
pc.Notify(string.Format(Translator.GetString("Sentry.Notify.Info"), players, bodies, vented, shifted), ShowInfoDuration.GetInt());
|
||||
return;
|
||||
|
||||
static string GetColoredNames(IEnumerable<byte> ids) => ids.Where(x => Utils.GetPlayerById(x) != null).Select(x => Utils.ColorString(Main.PlayerColors[x], Utils.GetPlayerById(x).GetRealName())).Join();
|
||||
}
|
||||
|
||||
public bool IsInMonitoredRoom(PlayerControl pc) => MonitoredRoom != null && pc.GetPlainShipRoom() == MonitoredRoom;
|
||||
|
||||
public void OnAnyoneShapeshiftLoop(PlayerControl shapeshifter)
|
||||
{
|
||||
if (IsInMonitoredRoom(shapeshifter)) PlayersShiftedInRoom.Add(shapeshifter.PlayerId);
|
||||
}
|
||||
|
||||
public static void OnAnyoneMurder(PlayerControl target)
|
||||
{
|
||||
foreach (var state in Main.PlayerStates.Values)
|
||||
{
|
||||
if (state.Role is Sentry st && st.IsInMonitoredRoom(target))
|
||||
{
|
||||
st.DeadBodiesInRoom.Add(target.PlayerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnAnyoneEnterVent(PlayerControl pc)
|
||||
{
|
||||
foreach (var state in Main.PlayerStates.Values)
|
||||
{
|
||||
if (state.Role is Sentry st && st.IsInMonitoredRoom(pc))
|
||||
{
|
||||
st.PlayersVentedInRoom.Add(pc.PlayerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetSuffix(PlayerControl seer)
|
||||
{
|
||||
if (!PlayersKnowAboutCamera.GetBool()) return string.Empty;
|
||||
|
||||
if (Main.PlayerStates[seer.PlayerId].Role is Sentry s && s.MonitoredRoom != null) return string.Format(Translator.GetString("Sentry.Suffix.Self"), Translator.GetString($"{s.MonitoredRoom.RoomId}"));
|
||||
|
||||
foreach (var state in Main.PlayerStates.Values)
|
||||
{
|
||||
if (state.Role is Sentry st && st.IsInMonitoredRoom(seer))
|
||||
{
|
||||
return string.Format(Translator.GetString("Sentry.Suffix.MonitoredRoom"), CustomRoles.Sentry.ToColoredString());
|
||||
}
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private readonly HashSet<byte> LastNotified = [];
|
||||
|
||||
public override void OnGlobalFixedUpdate(PlayerControl pc, bool lowLoad)
|
||||
{
|
||||
if (!GameStates.IsInTask || lowLoad) return;
|
||||
|
||||
bool nowInMonitoredRoom = IsInMonitoredRoom(pc);
|
||||
bool wasInMonitoredRoom = LastNotified.Contains(pc.PlayerId);
|
||||
|
||||
switch (nowInMonitoredRoom)
|
||||
{
|
||||
case true when !wasInMonitoredRoom:
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
LastNotified.Add(pc.PlayerId);
|
||||
break;
|
||||
case false when wasInMonitoredRoom:
|
||||
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
|
||||
LastNotified.Remove(pc.PlayerId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
using AmongUs.GameOptions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace EHR.Roles.Impostor
|
||||
{
|
||||
internal static class GeneratorStatic
|
||||
{
|
||||
enum Action
|
||||
{
|
||||
Kill,
|
||||
Shapeshift,
|
||||
Vent,
|
||||
Sabotage
|
||||
}
|
||||
|
||||
private static int GetDefaultCost(this Action action) => action switch
|
||||
{
|
||||
Action.Kill => 5,
|
||||
Action.Shapeshift => 10,
|
||||
Action.Vent => 20,
|
||||
Action.Sabotage => 15,
|
||||
|
||||
_ => 15
|
||||
};
|
||||
|
||||
internal class Generator : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
public override bool IsEnable => On;
|
||||
|
||||
private static OptionItem ChargesGainedPerSecond;
|
||||
private static OptionItem StartingCharges;
|
||||
private static OptionItem ChargesLostWhileShiftedPerSecond;
|
||||
private static OptionItem MaxChargesStored;
|
||||
private static readonly Dictionary<Action, OptionItem> ActionCostSettings = [];
|
||||
|
||||
private static int Gain;
|
||||
private static int ChargesLostWhileShifted;
|
||||
private static Dictionary<Action, int> ActionCosts = [];
|
||||
|
||||
private int Charges;
|
||||
private long LastUpdate;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
const int id = 11380;
|
||||
Options.SetupRoleOptions(id, TabGroup.ImpostorRoles, CustomRoles.Generator);
|
||||
ChargesGainedPerSecond = IntegerOptionItem.Create(id + 2, "Generator.ChargesGainedEverySecond", new(1, 30, 1), 1, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Generator]);
|
||||
StartingCharges = IntegerOptionItem.Create(id + 3, "Generator.StartingCharges", new(0, 100, 1), 0, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Generator]);
|
||||
ChargesLostWhileShiftedPerSecond = IntegerOptionItem.Create(id + 4, "Generator.ChargesLostWhileShiftedPerSecond", new(1, 30, 1), 1, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Generator]);
|
||||
MaxChargesStored = IntegerOptionItem.Create(id + 5, "Generator.MaxChargesStored", new(0, 200, 1), 100, TabGroup.ImpostorRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Generator]);
|
||||
|
||||
foreach (var action in EnumHelper.GetAllValues<Action>())
|
||||
{
|
||||
var option = IntegerOptionItem.Create(id + 6 + (int)action, $"Generator.{action}.Cost", new(0, 100, 1), action.GetDefaultCost(), TabGroup.ImpostorRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Generator]);
|
||||
ActionCostSettings.Add(action, option);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
Charges = StartingCharges.GetInt();
|
||||
playerId.SetAbilityUseLimit(Charges);
|
||||
LastUpdate = Utils.TimeStamp + 8;
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
Gain = ChargesGainedPerSecond.GetInt();
|
||||
ChargesLostWhileShifted = ChargesLostWhileShiftedPerSecond.GetInt();
|
||||
ActionCosts = ActionCostSettings.ToDictionary(x => x.Key, x => x.Value.GetInt());
|
||||
}
|
||||
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte playerId)
|
||||
{
|
||||
AURoleOptions.ShapeshifterCooldown = 1f;
|
||||
AURoleOptions.ShapeshifterDuration = 300f;
|
||||
}
|
||||
|
||||
public override void OnFixedUpdate(PlayerControl pc)
|
||||
{
|
||||
if (!GameStates.IsInTask || pc == null || !pc.IsAlive()) return;
|
||||
|
||||
long now = Utils.TimeStamp;
|
||||
if (now <= LastUpdate) return;
|
||||
LastUpdate = now;
|
||||
|
||||
int beforeCharges = Charges;
|
||||
bool shifted = pc.IsShifted();
|
||||
|
||||
if (shifted) Charges -= ChargesLostWhileShifted;
|
||||
else Charges += Gain;
|
||||
|
||||
Charges = Math.Clamp(Charges, 0, MaxChargesStored.GetInt());
|
||||
|
||||
if (Charges <= 0 && shifted)
|
||||
{
|
||||
pc.Notify(Translator.GetString("Generator.Notify.RevertShapeshift"));
|
||||
pc.RpcShapeshift(pc, !Options.DisableShapeshiftAnimations.GetBool());
|
||||
pc.RpcResetAbilityCooldown();
|
||||
}
|
||||
|
||||
if (beforeCharges != Charges) pc.SetAbilityUseLimit(Charges, log: false);
|
||||
}
|
||||
|
||||
public override void OnCoEnterVent(PlayerPhysics physics, int ventId)
|
||||
{
|
||||
int cost = ActionCosts[Action.Vent];
|
||||
|
||||
if (Charges < cost)
|
||||
{
|
||||
_ = new LateTask(() =>
|
||||
{
|
||||
physics.RpcBootFromVent(ventId);
|
||||
physics.myPlayer.Notify(string.Format(Translator.GetString("Generator.Notify.NotEnoughCharges"), cost));
|
||||
}, 0.5f, "Generator not enough charges to vent");
|
||||
return;
|
||||
}
|
||||
|
||||
Charges -= cost;
|
||||
}
|
||||
|
||||
public override bool OnCheckMurder(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
if (!base.OnCheckMurder(killer, target)) return false;
|
||||
|
||||
int cost = ActionCosts[Action.Kill];
|
||||
if (Charges < cost)
|
||||
{
|
||||
killer.Notify(string.Format(Translator.GetString("Generator.Notify.NotEnoughCharges"), cost));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void OnMurder(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
Charges -= ActionCosts[Action.Kill];
|
||||
}
|
||||
|
||||
public override bool OnSabotage(PlayerControl pc)
|
||||
{
|
||||
if (!pc.IsAlive()) return true;
|
||||
|
||||
int cost = ActionCosts[Action.Sabotage];
|
||||
|
||||
if (Charges < cost)
|
||||
{
|
||||
pc.Notify(string.Format(Translator.GetString("Generator.Notify.NotEnoughCharges"), cost));
|
||||
return false;
|
||||
}
|
||||
|
||||
Charges -= cost;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool OnShapeshift(PlayerControl shapeshifter, PlayerControl target, bool shapeshifting)
|
||||
{
|
||||
if (!shapeshifting) return true;
|
||||
|
||||
int cost = ActionCosts[Action.Shapeshift];
|
||||
|
||||
if (Charges < cost)
|
||||
{
|
||||
shapeshifter.Notify(string.Format(Translator.GetString("Generator.Notify.NotEnoughCharges"), cost));
|
||||
return false;
|
||||
}
|
||||
|
||||
Charges -= cost;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,18 @@ public class Amnesiac : RoleBase
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.Amnesiac);
|
||||
RememberMode = StringOptionItem.Create(Id + 9, "RememberMode", RememberModes, 0, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
RememberCooldown = FloatOptionItem.Create(Id + 10, "RememberCooldown", new(0f, 180f, 2.5f), 5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac])
|
||||
RememberMode = StringOptionItem.Create(Id + 9, "RememberMode", RememberModes, 0, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
RememberCooldown = FloatOptionItem.Create(Id + 10, "RememberCooldown", new(0f, 180f, 2.5f), 5f, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
RefugeeKillCD = FloatOptionItem.Create(Id + 11, "RefugeeKillCD", new(0f, 180f, 2.5f), 25f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac])
|
||||
RefugeeKillCD = FloatOptionItem.Create(Id + 11, "RefugeeKillCD", new(0f, 180f, 2.5f), 25f, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
IncompatibleNeutralMode = StringOptionItem.Create(Id + 12, "IncompatibleNeutralMode", AmnesiacIncompatibleNeutralMode, 0, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
CanVent = BooleanOptionItem.Create(Id + 13, "CanVent", false, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
IncompatibleNeutralMode = StringOptionItem.Create(Id + 12, "IncompatibleNeutralMode", AmnesiacIncompatibleNeutralMode, 0, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
CanVent = BooleanOptionItem.Create(Id + 13, "CanVent", false, TabGroup.NeutralRoles, false)
|
||||
.SetParent(CustomRoleSpawnChances[CustomRoles.Amnesiac]);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
using EHR.Patches;
|
||||
|
||||
namespace EHR.Roles.Impostor
|
||||
{
|
||||
internal class Cherokious : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
public override bool IsEnable => On;
|
||||
|
||||
public static OptionItem KillCooldown;
|
||||
public static Options.OverrideTasksData Tasks;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
const int id = 13860;
|
||||
Options.SetupRoleOptions(id, TabGroup.NeutralRoles, CustomRoles.Cherokious);
|
||||
KillCooldown = IntegerOptionItem.Create(id + 2, "KillCooldown", new(0, 60, 1), 15, TabGroup.NeutralRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.Cherokious])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
Tasks = Options.OverrideTasksData.Create(id + 3, TabGroup.NeutralRoles, CustomRoles.Cherokious);
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
playerId.SetAbilityUseLimit(0);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override void OnTaskComplete(PlayerControl pc, int completedTaskCount, int totalTaskCount)
|
||||
{
|
||||
pc.RpcIncreaseAbilityUseLimitBy(1);
|
||||
}
|
||||
|
||||
public override void OnPet(PlayerControl pc)
|
||||
{
|
||||
if (pc.GetAbilityUseLimit() < 1) return;
|
||||
var target = ExternalRpcPetPatch.SelectKillButtonTarget(pc);
|
||||
if (target != null && pc.RpcCheckAndMurder(target)) pc.RpcRemoveAbilityUse();
|
||||
}
|
||||
|
||||
public override bool CanUseKillButton(PlayerControl pc) => false;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,41 @@
|
||||
using AmongUs.GameOptions;
|
||||
using System.Collections.Generic;
|
||||
using static EHR.Options;
|
||||
|
||||
namespace EHR.Roles.Neutral;
|
||||
|
||||
public class NSerialKiller : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
private const int Id = 12800;
|
||||
public static List<byte> playerIdList = [];
|
||||
|
||||
private static OptionItem KillCooldown;
|
||||
public static OptionItem CanVent;
|
||||
private static OptionItem CanVent;
|
||||
private static OptionItem HasImpostorVision;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
SetupRoleOptions(Id, TabGroup.NeutralRoles, CustomRoles.NSerialKiller);
|
||||
KillCooldown = FloatOptionItem.Create(Id + 10, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.NSerialKiller])
|
||||
KillCooldown = FloatOptionItem.Create(Id + 2, "KillCooldown", new(0f, 180f, 2.5f), 22.5f, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.NSerialKiller])
|
||||
.SetValueFormat(OptionFormat.Seconds);
|
||||
CanVent = BooleanOptionItem.Create(Id + 11, "CanVent", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.NSerialKiller]);
|
||||
HasImpostorVision = BooleanOptionItem.Create(Id + 13, "ImpostorVision", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.NSerialKiller]);
|
||||
CanVent = BooleanOptionItem.Create(Id + 3, "CanVent", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.NSerialKiller]);
|
||||
HasImpostorVision = BooleanOptionItem.Create(Id + 4, "ImpostorVision", true, TabGroup.NeutralRoles, false).SetParent(CustomRoleSpawnChances[CustomRoles.NSerialKiller]);
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
playerIdList = [];
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
playerIdList.Add(playerId);
|
||||
On = true;
|
||||
|
||||
if (!AmongUsClient.Instance.AmHost) return;
|
||||
if (!Main.ResetCamPlayerList.Contains(playerId))
|
||||
Main.ResetCamPlayerList.Add(playerId);
|
||||
}
|
||||
|
||||
public override bool IsEnable => playerIdList.Count > 0;
|
||||
public override bool IsEnable => On;
|
||||
public override void SetKillCooldown(byte id) => Main.AllPlayerKillCooldown[id] = KillCooldown.GetFloat();
|
||||
public override void ApplyGameOptions(IGameOptions opt, byte id) => opt.SetVision(HasImpostorVision.GetBool());
|
||||
public override bool CanUseImpostorVentButton(PlayerControl pc) => CanVent.GetBool();
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
namespace EHR.Roles.Impostor
|
||||
{
|
||||
internal class SchrodingersCat : RoleBase
|
||||
{
|
||||
public static bool On;
|
||||
public override bool IsEnable => On;
|
||||
|
||||
public static OptionItem WinsWithCrewIfNotAttacked;
|
||||
|
||||
public static void SetupCustomOption()
|
||||
{
|
||||
const int id = 13840;
|
||||
Options.SetupRoleOptions(id, TabGroup.NeutralRoles, CustomRoles.SchrodingersCat);
|
||||
WinsWithCrewIfNotAttacked = BooleanOptionItem.Create(id + 2, "SchrodingersCat.WinsWithCrewIfNotAttacked", true, TabGroup.NeutralRoles, false)
|
||||
.SetParent(Options.CustomRoleSpawnChances[CustomRoles.SchrodingersCat]);
|
||||
}
|
||||
|
||||
public override void Add(byte playerId)
|
||||
{
|
||||
On = true;
|
||||
}
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
On = false;
|
||||
}
|
||||
|
||||
public override bool OnCheckMurderAsTarget(PlayerControl killer, PlayerControl target)
|
||||
{
|
||||
var killerRole = killer.GetCustomRole();
|
||||
if (Options.SingleRoles.Contains(killerRole)) killerRole = CustomRoles.Amnesiac;
|
||||
|
||||
target.RpcSetCustomRole(killerRole);
|
||||
|
||||
killer.SetKillCooldown(5f);
|
||||
|
||||
killer.Notify(string.Format(Translator.GetString("SchrodingersCat.Notify.KillerRecruited"), target.GetRealName(), CustomRoles.SchrodingersCat.ToColoredString()));
|
||||
target.Notify(string.Format(Translator.GetString("SchrodingersCat.Notify.RecruitedByKiller"), killer.GetRealName(), killerRole.ToColoredString()));
|
||||
|
||||
Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: target);
|
||||
Utils.NotifyRoles(SpecifySeer: target, SpecifyTarget: killer);
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -51,7 +51,7 @@ namespace EHR
|
||||
|
||||
public virtual bool CanUseSabotage(PlayerControl pc)
|
||||
{
|
||||
return pc.Is(Team.Impostor) || (pc.Is(CustomRoles.Mischievous) || (pc.Is(CustomRoles.Bloodlust) && Bloodlust.HasImpVision.GetBool()) && pc.IsAlive());
|
||||
return pc.Is(Team.Impostor) || pc.Is(CustomRoles.Mischievous) || (pc.Is(CustomRoles.Bloodlust) && Bloodlust.HasImpVision.GetBool()) && pc.IsAlive();
|
||||
}
|
||||
|
||||
public virtual void ApplyGameOptions(IGameOptions opt, byte playerId)
|
||||
|
||||
@@ -322,6 +322,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Gaulois, "#42d1f5" },
|
||||
{ CustomRoles.Druid, "#ffb694" },
|
||||
{ CustomRoles.Autocrat, "#e2ed64" },
|
||||
{ CustomRoles.Sentry, "#db55f2" },
|
||||
{ CustomRoles.Perceiver, "#ebeb34" },
|
||||
{ CustomRoles.Convener, "#34eb7a" },
|
||||
{ CustomRoles.Mathematician, "#eb3474" },
|
||||
@@ -335,7 +336,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.NiceHacker, "#75fa4c" },
|
||||
{ CustomRoles.Aid, "#D7BDE2" },
|
||||
{ CustomRoles.DonutDelivery, "#a46efa" },
|
||||
{ CustomRoles.Analyzer, "#33ddff" },
|
||||
{ CustomRoles.Analyst, "#33ddff" },
|
||||
{ CustomRoles.Escort, "#ff94e6" },
|
||||
{ CustomRoles.Spy, "#34495E" },
|
||||
{ CustomRoles.Doormaster, "#7FB3D5" },
|
||||
@@ -432,6 +433,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Sprayer, "#ffc038" },
|
||||
{ CustomRoles.PlagueDoctor, "#ff6633" },
|
||||
{ CustomRoles.Postman, "#00b893" },
|
||||
{ CustomRoles.SchrodingersCat, "#616161" },
|
||||
{ CustomRoles.Impartial, "#4287f5" },
|
||||
{ CustomRoles.Predator, "#c73906" },
|
||||
{ CustomRoles.Reckless, "#6e000d" },
|
||||
@@ -446,6 +448,7 @@ public class Main : BasePlugin
|
||||
{ CustomRoles.Agitater, "#F4A460" },
|
||||
{ CustomRoles.BloodKnight, "#630000" },
|
||||
{ CustomRoles.Juggernaut, "#A41342" },
|
||||
{ CustomRoles.Cherokious, "#de4b9e" },
|
||||
{ CustomRoles.Parasite, "#ff1919" },
|
||||
{ CustomRoles.Crewpostor, "#ff1919" },
|
||||
{ CustomRoles.Refugee, "#ff1919" },
|
||||
@@ -611,8 +614,8 @@ public class Main : BasePlugin
|
||||
{
|
||||
AllRoleClasses.AddRange(Assembly.GetAssembly(typeof(RoleBase))!
|
||||
.GetTypes()
|
||||
.Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(RoleBase)))
|
||||
.Select(type => (RoleBase)Activator.CreateInstance(type, null)));
|
||||
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(RoleBase)))
|
||||
.Select(t => (RoleBase)Activator.CreateInstance(t, null)));
|
||||
AllRoleClasses.Sort();
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -712,7 +715,10 @@ public enum CustomWinner
|
||||
Doomsayer = CustomRoles.Doomsayer,
|
||||
RuthlessRomantic = CustomRoles.RuthlessRomantic,
|
||||
Doppelganger = CustomRoles.Doppelganger,
|
||||
Imitator = CustomRoles.Imitator
|
||||
Imitator = CustomRoles.Imitator,
|
||||
Cherokious = CustomRoles.Cherokious,
|
||||
|
||||
Bloodlust = CustomRoles.Bloodlust
|
||||
}
|
||||
|
||||
public enum AdditionalWinners
|
||||
@@ -741,7 +747,8 @@ public enum AdditionalWinners
|
||||
Postman = CustomRoles.Postman,
|
||||
Impartial = CustomRoles.Impartial,
|
||||
Predator = CustomRoles.Predator,
|
||||
SoulHunter = CustomRoles.SoulHunter
|
||||
SoulHunter = CustomRoles.SoulHunter,
|
||||
SchrodingersCat = CustomRoles.SchrodingersCat
|
||||
}
|
||||
|
||||
public enum SuffixModes
|
||||
|
||||
Reference in new issue
Block a user