Fixes & CTF uses unshift

This commit is contained in:
Gurge44 committed 2024-08-12 14:20:16 +02:00
1 parent ed97635cef
commit 6dca1deecb
27 files changed
+205 -176

No files matched your search

+10 -1
View File
@@ -39,4 +39,13 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=UI/@EntryIndexedValue">UI</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=VN/@EntryIndexedValue">VN</s:String>
<s:Boolean
x:Key="/Default/Housekeeping/Layout/SolBuilderDuoView/ShowBuildProgressInToolWindow/@EntryValue">False</s:Boolean></wpf:ResourceDictionary>
x:Key="/Default/Housekeeping/Layout/SolBuilderDuoView/ShowBuildProgressInToolWindow/@EntryValue">False</s:Boolean>
<s:String
x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=DED7798D82D02045ABA68FC339C76DFA/Text/@EntryValue">try
{
$SELECTION$
}
catch ($EXCEPTION$ $EX_NAME$)
{
$SELSTART$Utils.ThrowException($EX_NAME$);$SELEND$
}</s:String></wpf:ResourceDictionary>
+25 -4
View File
@@ -35,6 +35,7 @@ namespace EHR
private static Dictionary<byte, CTFTeam> PlayerTeams = [];
private static Dictionary<CTFTeam, CTFTeamData> TeamData = [];
private static Dictionary<byte, CTFPlayerData> PlayerData = [];
private static Dictionary<byte, NetworkedPlayerInfo.PlayerOutfit> DefaultOutfits = [];
private static bool ValidTag;
public static bool IsDeathPossible => TaggedPlayersGet.GetValue() == 1;
@@ -131,26 +132,35 @@ namespace EHR
switch (aapc.Length)
{
case 0:
ResetSkins();
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Draw);
CustomWinnerHolder.WinnerIds = Main.PlayerStates.Keys.ToHashSet();
reason = GameOverReason.HumansDisconnect;
return true;
case 1:
ResetSkins();
TeamData[PlayerTeams[aapc[0].PlayerId]].SetAsWinner();
return true;
default:
// If WinnerData is already set, end the game
if (WinnerData.Team != "No one wins") return true;
if (WinnerData.Team != "No one wins")
{
ResetSkins();
return true;
}
// If all players are on the same team, end the game
if (aapc.All(x => PlayerTeams[x.PlayerId] == CTFTeam.Blue) || aapc.All(x => PlayerTeams[x.PlayerId] == CTFTeam.Yellow))
{
ResetSkins();
TeamData[PlayerTeams[aapc[0].PlayerId]].SetAsWinner();
return true;
}
return false;
}
void ResetSkins() => DefaultOutfits.Select(x => (pc: x.Key.GetPlayer(), outfit: x.Value)).DoIf(x => x.pc != null && x.outfit != null, x => Utils.RpcChangeSkin(x.pc, x.outfit));
}
public static void OnGameStart()
@@ -160,6 +170,7 @@ namespace EHR
TeamData = [];
WinnerData = (Color.white, "No one wins");
PlayerData = Main.PlayerStates.Keys.ToDictionary(x => x, _ => new CTFPlayerData());
DefaultOutfits = Main.AllPlayerControls.ToDictionary(x => x.PlayerId, x => x.Data.DefaultOutfit);
ValidTag = false;
// Check if the current game mode is Capture The Flag
@@ -182,6 +193,7 @@ namespace EHR
PlayerTeams[player.PlayerId] = CTFTeam.Blue;
bluePlayers.Add(player.PlayerId);
blueOutfit.PlayerName = player.GetRealName();
blueOutfit.PetId = player.Data.DefaultOutfit.PetId;
Utils.RpcChangeSkin(player, blueOutfit);
}
@@ -190,6 +202,7 @@ namespace EHR
PlayerTeams[player.PlayerId] = CTFTeam.Yellow;
yellowPlayers.Add(player.PlayerId);
yellowOutfit.PlayerName = player.GetRealName();
yellowOutfit.PetId = player.Data.DefaultOutfit.PetId;
Utils.RpcChangeSkin(player, yellowOutfit);
}
@@ -221,6 +234,9 @@ namespace EHR
break;
}
}
pc.CheckAndSetUnshiftState(force: true);
pc.RpcResetAbilityCooldown();
}
ValidTag = true;
@@ -232,7 +248,7 @@ namespace EHR
var targetTeam = PlayerTeams[target.PlayerId];
if (!ValidTag || PlayerTeams[killer.PlayerId] == targetTeam || TeamData.Values.Any(x => x.FlagCarrier == killer.PlayerId)) return;
killer.SetKillCooldown();
new[] { killer, target }.Do(x => x.SetKillCooldown());
if (TeamData.FindFirst(x => x.Value.FlagCarrier == target.PlayerId, out var kvp))
{
@@ -261,16 +277,21 @@ namespace EHR
Utils.NotifyRoles(SpecifySeer: killer, SpecifyTarget: killer);
}
public static void OnPet(PlayerControl pc)
public static void TryPickUpFlag(PlayerControl pc)
{
if (!ValidTag) return;
Logger.Info($"{pc.GetRealName()} petted their pet", "CTF.OnPet");
Logger.Info($"Received flag pickup request from {pc.GetRealName()}", "CTF");
// If the player is near the enemy's flag, pick it up
var pos = pc.Pos();
var enemy = TeamData[PlayerTeams[pc.PlayerId].GetOppositeTeam()];
if (enemy.IsNearFlag(pos)) enemy.PickUpFlag(pc.PlayerId);
}
public static void ApplyGameOptions(IGameOptions opt)
{
AURoleOptions.ShapeshifterCooldown = 1f;
}
static Color GetTeamColor(this CTFTeam team)
{
return team switch
+3 -2
View File
@@ -15,7 +15,7 @@ public static class AntiBlackout
///<summary>
///Whether to override the ejection process
///</summary>
public static bool OverrideExiledPlayer => IsRequired && (IsSingleImpostor || Diff_CrewImp == 1);
public static bool OverrideExiledPlayer => IsRequired && (IsSingleImpostor || Diff_CrewImp == 1 || Main.AliveImpostorCount == 1);
///<summary>
///Is there only one impostor?
@@ -25,7 +25,7 @@ public static class AntiBlackout
///<summary>
///Whether processing within AntiBlackout is required
///</summary>
public static bool IsRequired => Options.NoGameEnd.GetBool() || Main.AllPlayerControls.Any(x => x.GetCustomRole().GetCountTypes() is not CountTypes.Crew and not CountTypes.Impostor and not CountTypes.OutOfGame);
public static bool IsRequired => Options.NoGameEnd.GetBool() || Main.AllPlayerControls.Any(x => x.GetCountTypes() is not CountTypes.Crew and not CountTypes.Impostor and not CountTypes.OutOfGame);
//|| Pirate.IsEnable;
///<summary>
@@ -110,6 +110,7 @@ public static class AntiBlackout
AmongUsClient.Instance.SendOrDisconnect(writer);
writer.Recycle();
}
AmongUsClient.Instance.SendAllStreamedObjects();
}
+9 -10
View File
@@ -87,7 +87,7 @@ internal static class CustomRolesHelper
{
if (role.IsGhostRole()) return CustomRoles.GuardianAngel;
if (role.IsVanilla()) return role;
if (checkDesyncRole && role.GetDYRole() == RoleTypes.Impostor) return CustomRoles.Impostor;
if (checkDesyncRole && role.IsDesyncRole()) return Enum.Parse<CustomRoles>(role.GetDYRole() + "EHR");
if (Options.UsePhantomBasis.GetBool() && role.SimpleAbilityTrigger()) return CustomRoles.Phantom;
if (Options.UseUnshiftTrigger.GetBool() && role.SimpleAbilityTrigger()) return CustomRoles.Shapeshifter;
bool UsePets = Options.UsePets.GetBool();
@@ -334,8 +334,7 @@ internal static class CustomRolesHelper
public static CustomRoles GetErasedRole(this CustomRoles role)
{
if (role.IsVanilla()) return role;
var vnRole = role.GetVNRole();
if (role.GetDYRole() == RoleTypes.Impostor) vnRole = CustomRoles.Impostor;
var vnRole = role.GetVNRole(checkDesyncRole: true);
return vnRole switch
{
CustomRoles.Crewmate => CustomRoles.CrewmateEHR,
@@ -369,7 +368,7 @@ internal static class CustomRolesHelper
// Speedrun
CustomRoles.Runner => RoleTypes.Crewmate,
// Capture The Flag
CustomRoles.CTFPlayer => RoleTypes.Impostor,
CustomRoles.CTFPlayer => RoleTypes.Shapeshifter,
// Standard
CustomRoles.Executioner => Executioner.CRoleChangeRoles[Executioner.ChangeRolesAfterTargetKilled.GetValue()].GetDYRole(),
CustomRoles.Sheriff => UsePets && Sheriff.UsePet.GetBool() ? RoleTypes.GuardianAngel : RoleTypes.Impostor,
@@ -809,6 +808,7 @@ internal static class CustomRolesHelper
public static bool CheckAddonConflict(CustomRoles role, PlayerControl pc) => role.IsAdditionRole() && (!Main.NeverSpawnTogetherCombos.TryGetValue(OptionItem.CurrentPreset, out var neverList) || !neverList.TryGetValue(pc.GetCustomRole(), out var bannedAddonList) || !bannedAddonList.Contains(role)) && pc.GetCustomRole() is not CustomRoles.GuardianAngelEHR and not CustomRoles.God && !pc.Is(CustomRoles.Madmate) && !pc.Is(CustomRoles.GM) && role is not CustomRoles.Lovers && !pc.Is(CustomRoles.Needy) && (!pc.HasSubRole() || pc.GetCustomSubRoles().Count < Options.NoLimitAddonsNumMax.GetInt()) && (!Options.AddonCanBeSettings.TryGetValue(role, out var o) || ((o.Imp.GetBool() || !pc.GetCustomRole().IsImpostor()) && (o.Neutral.GetBool() || !pc.GetCustomRole().IsNeutral()) && (o.Crew.GetBool() || !pc.IsCrewmate()))) && (!role.IsImpOnlyAddon() || pc.IsImpostor()) && role switch
{
CustomRoles.Disco when pc.GetCustomRole() is CustomRoles.Chameleon or CustomRoles.Swooper or CustomRoles.Wraith or CustomRoles.Alchemist => false,
CustomRoles.Egoist when pc.Is(CustomRoles.Gangster) => false,
CustomRoles.Nimble when pc.Is(CustomRoles.Oxyman) => false,
CustomRoles.Magnet when pc.Is(Team.Impostor) => false,
@@ -820,7 +820,7 @@ internal static class CustomRolesHelper
CustomRoles.Autopsy when pc.Is(CustomRoles.Doctor) || pc.Is(CustomRoles.Tracefinder) || pc.Is(CustomRoles.Scientist) || pc.Is(CustomRoles.ScientistEHR) || pc.Is(CustomRoles.Sunnyboy) => false,
CustomRoles.Necroview when pc.Is(CustomRoles.Doctor) => false,
CustomRoles.Lazy when pc.Is(CustomRoles.Speedrunner) => false,
CustomRoles.Mischievous when pc.Is(Team.Impostor) || pc.GetCustomRole().GetDYRole() != RoleTypes.Impostor || !pc.IsNeutralKiller() || Main.PlayerStates[pc.PlayerId].Role.CanUseSabotage(pc) => false,
CustomRoles.Mischievous when pc.Is(Team.Impostor) || (!pc.GetCustomRole().IsDesyncRole() && !pc.Is(CustomRoles.Bloodlust)) || !pc.IsNeutralKiller() || Main.PlayerStates[pc.PlayerId].Role.CanUseSabotage(pc) => false,
CustomRoles.Loyal when pc.IsCrewmate() && !Options.CrewCanBeLoyal.GetBool() => false,
CustomRoles.Lazy when pc.Is(CustomRoles.Needy) || pc.Is(CustomRoles.Snitch) || pc.Is(CustomRoles.Marshall) || pc.Is(CustomRoles.Transporter) || pc.Is(CustomRoles.Guardian) => false,
CustomRoles.Brakar when pc.Is(CustomRoles.Dictator) => false,
@@ -900,9 +900,9 @@ internal static class CustomRolesHelper
CustomRoles.Busy when !pc.GetTaskState().hasTasks => false,
CustomRoles.Truant when pc.Is(CustomRoles.SoulHunter) => false,
CustomRoles.Nimble when !pc.IsCrewmate() => false,
CustomRoles.Physicist when !pc.IsCrewmate() || pc.GetCustomRole().GetDYRole() == RoleTypes.Impostor => false,
CustomRoles.Finder when !pc.IsCrewmate() || pc.GetCustomRole().GetDYRole() == RoleTypes.Impostor => false,
CustomRoles.Noisy when !pc.IsCrewmate() || pc.GetCustomRole().GetDYRole() == RoleTypes.Impostor => false,
CustomRoles.Physicist when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() => false,
CustomRoles.Finder when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() => false,
CustomRoles.Noisy when !pc.IsCrewmate() || pc.GetCustomRole().IsDesyncRole() => false,
CustomRoles.Unreportable when pc.Is(CustomRoles.Bait) => false,
CustomRoles.Oblivious when pc.Is(CustomRoles.Bloodhound) => false,
CustomRoles.Oblivious when pc.Is(CustomRoles.Vulture) => false,
@@ -939,8 +939,7 @@ internal static class CustomRolesHelper
public static RoleTypes GetRoleTypes(this CustomRoles role)
{
if (role.GetDYRole() == RoleTypes.Impostor) return RoleTypes.Impostor;
if (Enum.TryParse<RoleTypes>(role.GetVNRole().ToString(), ignoreCase: true, out var type)) return type;
if (Enum.TryParse<RoleTypes>(role.GetVNRole(checkDesyncRole: true).ToString(), ignoreCase: true, out var type)) return type;
return role.IsImpostor() ? RoleTypes.Impostor : RoleTypes.Crewmate;
}
+22 -6
View File
@@ -186,11 +186,11 @@ static class ExtendedPlayerControl
var callerMethod = caller.GetMethod();
string callerMethodName = callerMethod?.Name;
string callerClassName = callerMethod?.DeclaringType?.FullName;
Logger.Warn(callerClassName + "." + callerMethodName + " tried to get a CountType, but the player was null", "GetCountTypes");
Logger.Warn($"{callerClassName}.{callerMethodName} tried to get a CountType, but the player was null", "GetCountTypes");
return CountTypes.None;
}
return Main.PlayerStates.TryGetValue(player.PlayerId, out var State) ? State.countTypes : CountTypes.None;
return Main.PlayerStates.TryGetValue(player.PlayerId, out var State) ? State.SubRoles.Contains(CustomRoles.Bloodlust) ? CountTypes.Bloodlust : State.countTypes : CountTypes.None;
}
public static void RpcSetNameEx(this PlayerControl player, string name)
@@ -200,7 +200,7 @@ static class ExtendedPlayerControl
Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] = name;
}
Logger.Info($"Set:{player?.Data?.PlayerName}:{name} for All", "RpcSetNameEx");
Logger.Info($"Set: {player?.Data?.PlayerName} => {name} for Everyone", "RpcSetNameEx");
player?.RpcSetName(name);
}
@@ -211,7 +211,7 @@ static class ExtendedPlayerControl
if (!force && Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] == name) return;
Main.LastNotifyNames[(player.PlayerId, seer.PlayerId)] = name;
Logger.Info($"Set:{player.Data?.PlayerName}:{name} for {seer.GetNameWithRole().RemoveHtmlTags()}", "RpcSetNamePrivate");
Logger.Info($"Set: {player.Data?.PlayerName} => {name} for {seer.GetNameWithRole().RemoveHtmlTags()}", "RpcSetNamePrivate");
if (seer == null || player == null) return;
@@ -649,7 +649,7 @@ static class ExtendedPlayerControl
{
CustomRoles role = pc.GetCustomRole();
if (!pc.IsAlive() || pc.Data.Role.Role == RoleTypes.GuardianAngel || Pelican.IsEaten(pc.PlayerId)) return false;
if (role.GetDYRole() == RoleTypes.Impostor || role.GetVNRole() is CustomRoles.Impostor or CustomRoles.Shapeshifter) return true;
if (role.GetVNRole(checkDesyncRole: true) is CustomRoles.Impostor or CustomRoles.Shapeshifter) return true;
return pc.Is(CustomRoleTypes.Impostor) || pc.IsNeutralKiller() || role.IsTasklessCrewmate();
}
@@ -930,10 +930,13 @@ static class ExtendedPlayerControl
target.SetRealKiller(killer, NotOverRide: true);
if (target.Is(CustomRoles.Jackal))
Jackal.Instances.Do(x => x.PromoteSidekick());
switch (killer.PlayerId == target.PlayerId)
{
case true when killer.shapeshifting:
LateTask.New(() => { killer.RpcMurderPlayer(target, true); }, 1.5f, "Shapeshifting Suicide Delay");
LateTask.New(() => killer.RpcMurderPlayer(target, true), 1.5f, "Shapeshifting Suicide Delay");
return;
case false when !killer.Is(CustomRoles.Pestilence) && Main.PlayerStates[target.PlayerId].Role is SchrodingersCat cat:
cat.OnCheckMurderAsTarget(killer, target);
@@ -955,6 +958,19 @@ static class ExtendedPlayerControl
reporter.RpcStartMeeting(target);
}
public static void CheckAndSetUnshiftState(this PlayerControl pc, bool notify = true, bool force = false)
{
if (force || (pc.GetCustomRole().SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool())))
{
var target = Main.AllAlivePlayerControls.Without(pc).RandomElement();
var outfit = pc.Data.DefaultOutfit;
pc.RpcShapeshift(target, false);
Main.CheckShapeshift[pc.PlayerId] = false;
RpcChangeSkin(pc, outfit);
if (notify) NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc, NoCache: true);
}
}
public static bool IsModClient(this PlayerControl player) => Main.PlayerVersion.ContainsKey(player.PlayerId);
public static List<PlayerControl> GetPlayersInAbilityRangeSorted(this PlayerControl player, bool ignoreColliders = false) => GetPlayersInAbilityRangeSorted(player, _ => true, ignoreColliders);
@@ -161,19 +161,18 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
}
else
{
opt.SetVision(true);
opt.SetFloat(FloatOptionNames.CrewLightMod, 1.25f);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.25f);
SetMaxVision();
}
break;
case CustomGameMode.CaptureTheFlag:
CTFManager.ApplyGameOptions(opt);
SetMaxVision();
break;
case CustomGameMode.Speedrun:
case CustomGameMode.HotPotato:
case CustomGameMode.MoveAndStop:
opt.SetVision(true);
opt.SetFloat(FloatOptionNames.CrewLightMod, 1.25f);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.25f);
SetMaxVision();
break;
case CustomGameMode.HideAndSeek:
HnSManager.ApplyGameOptions(opt, player);
@@ -231,6 +230,9 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
Main.PlayerStates[player.PlayerId].Role.ApplyGameOptions(opt, player.PlayerId);
if (player.Is(CustomRoles.Bloodlust) && Bloodlust.HasImpVision.GetBool())
opt.SetVision(true);
if (Main.AllPlayerControls.Any(x => x.Is(CustomRoles.Bewilder) && !x.IsAlive() && x.GetRealKiller()?.PlayerId == player.PlayerId && !x.Is(CustomRoles.Hangman)))
{
opt.SetVision(false);
@@ -272,9 +274,7 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
if (Minion.BlindPlayers.Contains(player.PlayerId))
{
opt.SetVision(false);
opt.SetFloat(FloatOptionNames.CrewLightMod, 0);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0);
SetBlind();
}
if (Sentinel.IsPatrolling(player.PlayerId))
@@ -297,15 +297,11 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
if (Randomizer.HasSuperVision(player))
{
opt.SetVision(true);
opt.SetFloat(FloatOptionNames.CrewLightMod, 1.5f);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.5f);
SetMaxVision();
}
else if (Randomizer.IsBlind(player))
{
opt.SetVision(false);
opt.SetFloat(FloatOptionNames.CrewLightMod, 0);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0);
SetBlind();
}
var array = Main.PlayerStates[player.PlayerId].SubRoles;
@@ -332,9 +328,7 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
Main.AllPlayerSpeed[player.PlayerId] = Options.MareSpeedDuringLightsOut.GetFloat();
break;
case CustomRoles.Sleep when Utils.IsActive(SystemTypes.Electrical):
opt.SetVision(false);
opt.SetFloat(FloatOptionNames.CrewLightMod, 0);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0);
SetBlind();
Main.AllPlayerSpeed[player.PlayerId] = Main.MinSpeed;
break;
case CustomRoles.Torch:
@@ -390,23 +384,17 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
if (Magician.BlindPPL.ContainsKey(player.PlayerId))
{
opt.SetVision(false);
opt.SetFloat(FloatOptionNames.CrewLightMod, 0);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0);
SetBlind();
}
if (player.IsCrewmate() && Main.PlayerStates.Values.Any(s => s.Role is Adventurer { IsEnable: true } av && av.ActiveWeapons.Contains(Adventurer.Weapon.Lantern)))
{
opt.SetVision(true);
opt.SetFloat(FloatOptionNames.CrewLightMod, 1.5f);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.5f);
SetMaxVision();
}
if (Chemist.Instances.Any(x => x.IsBlinding && player.PlayerId != x.ChemistPC.PlayerId))
{
opt.SetVision(false);
opt.SetFloat(FloatOptionNames.CrewLightMod, 0);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0);
SetBlind();
}
if (Changeling.ChangedRole.TryGetValue(player.PlayerId, out var changed) && changed && player.GetRoleTypes() != RoleTypes.Shapeshifter)
@@ -458,6 +446,20 @@ public sealed class PlayerGameOptionsSender(PlayerControl player) : GameOptionsS
AURoleOptions.ImpostorsCanSeeProtect = false;
return opt;
void SetMaxVision()
{
opt.SetVision(true);
opt.SetFloat(FloatOptionNames.CrewLightMod, 1.5f);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 1.5f);
}
void SetBlind()
{
opt.SetVision(false);
opt.SetFloat(FloatOptionNames.CrewLightMod, 0f);
opt.SetFloat(FloatOptionNames.ImpostorLightMod, 0f);
}
}
catch (Exception e)
{
+1 -1
View File
@@ -1224,7 +1224,7 @@ public static class Options
FormatNameMode = new StringOptionItem(19403, "FormatNameMode", FormatNameModes, 0, TabGroup.SystemSettings);
DisableEmojiName = new BooleanOptionItem(19404, "DisableEmojiName", true, TabGroup.SystemSettings);
ChangeNameToRoleInfo = new BooleanOptionItem(19405, "ChangeNameToRoleInfo", true, TabGroup.SystemSettings);
ShowLongInfo = new BooleanOptionItem(19410, "ShowLongInfo", false, TabGroup.SystemSettings)
ShowLongInfo = new BooleanOptionItem(19420, "ShowLongInfo", false, TabGroup.SystemSettings)
.SetParent(ChangeNameToRoleInfo);
SendRoleDescriptionFirstMeeting = new BooleanOptionItem(19406, "SendRoleDescriptionFirstMeeting", true, TabGroup.SystemSettings);
NoGameEnd = new BooleanOptionItem(19407, "NoGameEnd", false, TabGroup.SystemSettings)
+4 -9
View File
@@ -2149,6 +2149,8 @@ public static class Utils
BeforeEnd2:
bool shouldSeeTargetAddons = new[] { seer, target }.All(x => x.Is(Team.Impostor));
string TargetRoleText =
(seer.Data.IsDead && Options.GhostCanSeeOtherRoles.GetBool()) ||
(seer.Is(CustomRoles.Mimic) && target.Data.IsDead && Options.MimicCanSeeDeadRoles.GetBool()) ||
@@ -2174,7 +2176,7 @@ public static class Utils
(seer.IsRevealedPlayer(target) && !target.Is(CustomRoles.Trickster)) ||
seer.Is(CustomRoles.God) ||
target.Is(CustomRoles.GM)
? $"<size={fontSize}>{target.GetDisplayRoleName(seer.PlayerId != target.PlayerId && !seer.Data.IsDead)}{GetProgressText(target)}</size>\r\n"
? $"<size={fontSize}>{target.GetDisplayRoleName(shouldSeeTargetAddons)}{GetProgressText(target)}</size>\r\n"
: string.Empty;
if (Options.CurrentGameMode == CustomGameMode.CaptureTheFlag) TargetRoleText = string.Empty;
@@ -2524,14 +2526,7 @@ public static class Utils
if (Options.UsePets.GetBool()) pc.AddAbilityCD(includeDuration: false);
if (pc.GetCustomRole().SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool()))
{
var target = Main.AllAlivePlayerControls.Without(pc).RandomElement();
var outfit = pc.Data.DefaultOutfit;
pc.RpcShapeshift(target, false);
Main.CheckShapeshift[pc.PlayerId] = false;
RpcChangeSkin(pc, outfit);
}
pc.CheckAndSetUnshiftState(notify: false);
AFKDetector.RecordPosition(pc);
+1 -1
View File
@@ -326,7 +326,7 @@ internal static class ChatCommands
private static void HMCommand(ChatController __instance, PlayerControl player, string text, string[] args)
{
if (args.Length < 2 || !int.TryParse(args[1], out int id) || id is > 3 or < 1) return;
if (Messenger.Sent.Contains(player.PlayerId) || args.Length < 2 || !int.TryParse(args[1], out int id) || id is > 3 or < 1) return;
Main.Instance.StartCoroutine(SendOnMeeting());
return;
+5 -5
View File
@@ -199,10 +199,10 @@ internal class TitleLogoPatch
if (!(BottomButtonBounds = GameObject.Find("BottomButtonBounds"))) return;
BottomButtonBounds.transform.localPosition -= new Vector3(0f, 0.1f, 0f);
__instance.settingsButton.buttonText.text = GetString("MainMenu.SettingsButton");
__instance.inventoryButton.buttonText.text = GetString("MainMenu.InventoryButton");
__instance.creditsButton.buttonText.text = GetString("MainMenu.CreditsButton");
__instance.quitButton.buttonText.text = GetString("MainMenu.QuitButton");
__instance.settingsButton?.ChangeButtonText(GetString("MainMenu.SettingsButton"));
__instance.inventoryButton?.ChangeButtonText(GetString("MainMenu.InventoryButton"));
__instance.creditsButton?.ChangeButtonText(GetString("MainMenu.CreditsButton"));
__instance.quitButton?.ChangeButtonText(GetString("MainMenu.QuitButton"));
return;
@@ -295,4 +295,4 @@ class OptionsMenuBehaviourOpenPatch
if (GameStates.InGame && GameStates.IsMeeting)
GuessManager.DestroyIDLabels();
}
}
}
+6 -10
View File
@@ -11,21 +11,16 @@ using HarmonyLib;
namespace EHR.Patches;
class ExileControllerWrapUpPatch
static class ExileControllerWrapUpPatch
{
private static NetworkedPlayerInfo antiBlackout_LastExiled;
public static NetworkedPlayerInfo AntiBlackout_LastExiled
{
get => antiBlackout_LastExiled;
set => antiBlackout_LastExiled = value;
}
public static NetworkedPlayerInfo AntiBlackout_LastExiled { get; set; }
static void WrapUpPostfix(NetworkedPlayerInfo exiled)
{
if (AntiBlackout.OverrideExiledPlayer)
{
exiled = AntiBlackout_LastExiled;
Logger.SendInGame(Translator.GetString("AntiBlackout.OverrideExiledPlayer"));
}
bool DecidedWinner = false;
@@ -44,12 +39,13 @@ class ExileControllerWrapUpPatch
{
if (!Options.InnocentCanWinByImp.GetBool() && role.IsImpostor())
{
Logger.Info("冤罪的目标是内鬼,非常可惜啊", "Exeiled Winner Check");
Logger.Info("The exiled player is an impostor, but the Innocent cannot win due to the settings", "Exeiled Winner Check");
}
else
{
CustomWinnerHolder.ResetAndSetWinner(CustomWinner.Innocent);
Main.AllPlayerControls.Where(x => x.Is(CustomRoles.Innocent) && !x.IsAlive() && x.GetRealKiller()?.PlayerId == exiled.PlayerId)
Main.AllPlayerControls
.Where(x => x.Is(CustomRoles.Innocent) && !x.IsAlive() && x.GetRealKiller()?.PlayerId == exiled.PlayerId)
.Do(x => CustomWinnerHolder.WinnerIds.Add(x.PlayerId));
DecidedWinner = true;
}
+2 -16
View File
@@ -651,7 +651,7 @@ class BeginImpostorPatch
return true;
}
if (PlayerControl.LocalPlayer.IsCrewmate() && role.GetDYRole() == RoleTypes.Impostor)
if (PlayerControl.LocalPlayer.IsCrewmate() && role.IsDesyncRole())
{
yourTeam = new();
yourTeam.Add(PlayerControl.LocalPlayer);
@@ -784,21 +784,7 @@ class IntroCutsceneDestroyPatch
if (Options.UseUnshiftTrigger.GetBool())
{
LateTask.New(() =>
{
foreach (var pc in Main.AllAlivePlayerControls)
{
if (pc.GetCustomRole().SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool()))
{
var target = Main.AllAlivePlayerControls.Without(pc).RandomElement();
var outfit = pc.Data.DefaultOutfit;
pc.RpcShapeshift(target, false);
Main.CheckShapeshift[pc.PlayerId] = false;
Utils.RpcChangeSkin(pc, outfit);
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc, NoCache: true);
}
}
}, 2f, "UnshiftTrigger SS");
LateTask.New(() => Main.AllAlivePlayerControls.Do(x => x.CheckAndSetUnshiftState()), 2f, "UnshiftTrigger SS");
}
if (PlayerControl.LocalPlayer.Is(CustomRoles.GM))
+10 -10
View File
@@ -92,7 +92,7 @@ public static class MainMenuManagerPatch
var bak = GameObject.Find("BackgroundTexture");
if (bak == null || !bak.active) return;
var pos2 = bak.transform.position;
Vector3 lerp2 = Vector3.Lerp(pos2, new Vector3(pos2.x, 7.1f, pos2.z), Time.deltaTime * 1.4f);
Vector3 lerp2 = Vector3.Lerp(pos2, new(pos2.x, 7.1f, pos2.z), Time.deltaTime * 1.4f);
bak.transform.position = lerp2;
if (pos2.y > 7f) ShowedBak = true;
}
@@ -115,9 +115,9 @@ public static class MainMenuManagerPatch
{
GitHubButton = CreateButton(
"GitHubButton",
new Vector3(-2.3f, -1.3f, 1f),
new Color32(153, 153, 153, byte.MaxValue),
new Color32(209, 209, 209, byte.MaxValue),
new(-2.3f, -1.3f, 1f),
new(153, 153, 153, byte.MaxValue),
new(209, 209, 209, byte.MaxValue),
() => Application.OpenURL("https://github.com/Gurge44/EndlessHostRoles"),
Translator.GetString("GitHub")); //"GitHub"
}
@@ -129,9 +129,9 @@ public static class MainMenuManagerPatch
{
DiscordButton = CreateButton(
"DiscordButton",
new Vector3(-0.5f, -1.3f, 1f),
new Color32(88, 101, 242, byte.MaxValue),
new Color32(148, 161, byte.MaxValue, byte.MaxValue),
new(-0.5f, -1.3f, 1f),
new(88, 101, 242, byte.MaxValue),
new(148, 161, byte.MaxValue, byte.MaxValue),
() => Application.OpenURL("https://discord.com/invite/m3ayxfumC8"),
Translator.GetString("Discord")); //"Discord"
}
@@ -143,9 +143,9 @@ public static class MainMenuManagerPatch
{
WebsiteButton = CreateButton(
"WebsiteButton",
new Vector3(1.3f, -1.3f, 1f),
new Color32(251, 81, 44, byte.MaxValue),
new Color32(211, 77, 48, byte.MaxValue),
new(1.3f, -1.3f, 1f),
new(251, 81, 44, byte.MaxValue),
new(211, 77, 48, byte.MaxValue),
() => Application.OpenURL("https://sites.google.com/view/ehr-au"),
Translator.GetString("Website")); //"Website"
}
+3 -2
View File
@@ -746,7 +746,8 @@ class MeetingHudStartPatch
{
var pc = Utils.GetPlayerById(pva.TargetPlayerId);
if (pc == null) continue;
var RoleTextData = Utils.GetRoleText(PlayerControl.LocalPlayer.PlayerId, pc.PlayerId);
bool shouldSeeTargetAddons = new[] { PlayerControl.LocalPlayer, pc }.All(x => x.Is(Team.Impostor));
var RoleTextData = Utils.GetRoleText(PlayerControl.LocalPlayer.PlayerId, pc.PlayerId, shouldSeeTargetAddons);
var roleTextMeeting = Object.Instantiate(pva.NameText, pva.NameText.transform, true);
roleTextMeeting.transform.localPosition = new(0f, -0.18f, 0f);
roleTextMeeting.fontSize = 1.4f;
@@ -807,7 +808,7 @@ class MeetingHudStartPatch
Logger.Info("The ship has " + (Options.SyncedButtonCount.GetFloat() - Options.UsedButtonCount) + " buttons left", "SyncButtonMode");
}
if (AntiBlackout.OverrideExiledPlayer && MeetingStates.FirstMeeting)
if (AntiBlackout.OverrideExiledPlayer && (MeetingStates.FirstMeeting || Main.RealOptionsData.GetInt(Int32OptionNames.NumImpostors) > 1))
{
LateTask.New(() => { Utils.SendMessage(GetString("Warning.OverrideExiledPlayer"), 255, Utils.ColorString(Color.red, GetString("DefaultSystemMessageTitle"))); }, 5f, "Warning OverrideExiledPlayer");
}
+1 -1
View File
@@ -742,7 +742,7 @@ internal class SelectRolesPatch
addonList.ForEach(x => state.SetSubRole(x));
}
if (state.MainRole.IsImpostor()) state.SubRoles.RemoveAll(x => x.IsImpOnlyAddon());
if (!state.MainRole.IsImpostor()) state.SubRoles.RemoveAll(x => x.IsImpOnlyAddon());
}
foreach (var pair in Main.PlayerStates)
+3 -14
View File
@@ -19,25 +19,20 @@ class LocalPetPatch
public static bool Prefix(PlayerControl __instance)
{
if (!Options.UsePets.GetBool() && Options.CurrentGameMode != CustomGameMode.CaptureTheFlag) return true;
if (!Options.UsePets.GetBool()) return true;
if (!(AmongUsClient.Instance.AmHost && AmongUsClient.Instance.AmClient)) return true;
if (GameStates.IsLobby || !__instance.IsAlive()) return true;
if (__instance.petting) return true;
__instance.petting = true;
bool ctf = Options.CurrentGameMode == CustomGameMode.CaptureTheFlag;
if (ctf) goto Skip;
if (!LastProcess.ContainsKey(__instance.PlayerId)) LastProcess.TryAdd(__instance.PlayerId, Utils.TimeStamp - 2);
if (LastProcess[__instance.PlayerId] + 1 >= Utils.TimeStamp) return true;
Skip:
ExternalRpcPetPatch.Prefix(__instance.MyPhysics, (byte)RpcCalls.Pet);
LastProcess[__instance.PlayerId] = Utils.TimeStamp;
return ctf || !__instance.GetCustomRole().PetActivatedAbility();
return !__instance.GetCustomRole().PetActivatedAbility();
}
public static void Postfix(PlayerControl __instance)
@@ -55,7 +50,7 @@ class ExternalRpcPetPatch
public static void Prefix(PlayerPhysics __instance, [HarmonyArgument(0)] byte callID)
{
if (GameStates.IsLobby || (!Options.UsePets.GetBool() && Options.CurrentGameMode != CustomGameMode.CaptureTheFlag) || !AmongUsClient.Instance.AmHost || (RpcCalls)callID != RpcCalls.Pet) return;
if (GameStates.IsLobby || !Options.UsePets.GetBool() || !AmongUsClient.Instance.AmHost || (RpcCalls)callID != RpcCalls.Pet) return;
var pc = __instance.myPlayer;
var physics = __instance;
@@ -74,12 +69,6 @@ class ExternalRpcPetPatch
&& pc.GetCustomRole().PetActivatedAbility())
physics.CancelPet();
if (Options.CurrentGameMode == CustomGameMode.CaptureTheFlag)
{
CTFManager.OnPet(pc);
return;
}
if (!LastProcess.ContainsKey(pc.PlayerId)) LastProcess.TryAdd(pc.PlayerId, Utils.TimeStamp - 2);
if (LastProcess[pc.PlayerId] + 1 >= Utils.TimeStamp) return;
LastProcess[pc.PlayerId] = Utils.TimeStamp;
+11 -10
View File
@@ -759,6 +759,9 @@ class ShapeshiftPatch
isSSneeded = false;
}
if (Options.CurrentGameMode == CustomGameMode.CaptureTheFlag)
CTFManager.TryPickUpFlag(shapeshifter);
var role = shapeshifter.GetCustomRole();
bool forceCancel = role.ForceCancelShapeshift();
bool unshiftTrigger = role.SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!role.IsNeutral() || Options.UseUnshiftTriggerForNKs.GetBool());
@@ -806,12 +809,7 @@ class ShapeshiftPatch
if (unshiftTrigger)
{
var rndTarget = Main.AllAlivePlayerControls.Without(shapeshifter).RandomElement();
var outfit = shapeshifter.Data.DefaultOutfit;
shapeshifter.RpcShapeshift(rndTarget, false);
Main.CheckShapeshift[shapeshifter.PlayerId] = false;
RpcChangeSkin(shapeshifter, outfit);
NotifyRoles(SpecifySeer: shapeshifter, SpecifyTarget: shapeshifter, NoCache: true);
shapeshifter.CheckAndSetUnshiftState(force: true);
shapeshifter.AddAbilityCD();
}
@@ -1224,7 +1222,8 @@ class FixedUpdatePatch
{
var player = __instance;
var playerId = player.PlayerId;
var localPlayer = player.PlayerId == PlayerControl.LocalPlayer.PlayerId; // Updates that are independent of the player are only executed for the local player.
var lpId = PlayerControl.LocalPlayer.PlayerId;
var localPlayer = player.PlayerId == lpId; // Updates that are independent of the player are only executed for the local player.
bool lowLoad = false;
if (Options.LowLoadMode.GetBool())
@@ -1437,7 +1436,9 @@ class FixedUpdatePatch
if (GameStates.IsInGame)
{
var RoleTextData = GetRoleText(PlayerControl.LocalPlayer.PlayerId, playerId);
bool shouldSeeTargetAddons = new[] { PlayerControl.LocalPlayer, player }.All(x => x.Is(Team.Impostor));
var RoleTextData = GetRoleText(lpId, playerId, shouldSeeTargetAddons);
RoleText.text = RoleTextData.Item1;
RoleText.color = RoleTextData.Item2;
@@ -1448,7 +1449,7 @@ class FixedUpdatePatch
if (!PlayerControl.LocalPlayer.Data.IsDead && PlayerControl.LocalPlayer.IsRevealedPlayer(__instance) && __instance.Is(CustomRoles.Trickster))
{
RoleText.text = Farseer.RandomRole[PlayerControl.LocalPlayer.PlayerId];
RoleText.text = Farseer.RandomRole[lpId];
RoleText.text += Farseer.GetTaskState();
}
@@ -1997,7 +1998,7 @@ class CoEnterVentPatch
Circumvent.OnCoEnterVent(__instance, id);
}
if (__instance.myPlayer.GetCustomRole().GetDYRole() == RoleTypes.Impostor && !Main.PlayerStates[__instance.myPlayer.PlayerId].Role.CanUseImpostorVentButton(__instance.myPlayer) && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek && !__instance.myPlayer.Is(CustomRoles.Nimble) && !__instance.myPlayer.Is(CustomRoles.Bloodlust))
if (__instance.myPlayer.GetCustomRole().IsDesyncRole() && !Main.PlayerStates[__instance.myPlayer.PlayerId].Role.CanUseImpostorVentButton(__instance.myPlayer) && Options.CurrentGameMode is CustomGameMode.Standard or CustomGameMode.HideAndSeek && !__instance.myPlayer.Is(CustomRoles.Nimble) && !__instance.myPlayer.Is(CustomRoles.Bloodlust))
{
LateTask.New(() => __instance.RpcBootFromVent(id), 0.5f, "CannotUseVentBootFromVent");
}
+2 -9
View File
@@ -168,18 +168,11 @@ public static class MushroomMixupSabotageSystemPatch
// After MushroomMixup sabotage, shapeshift cooldown sets to 0
foreach (var pc in Main.AllAlivePlayerControls)
{
// Reset Ability Cooldown To Default For Alive Players
// Reset Ability Cooldown To Default For Living Players
pc.RpcResetAbilityCooldown();
// Redo Unshift Trigger due to mushroom mixup breaking it
if (pc.GetCustomRole().SimpleAbilityTrigger() && Options.UseUnshiftTrigger.GetBool() && (!pc.IsNeutralKiller() || Options.UseUnshiftTriggerForNKs.GetBool()))
{
var target = Main.AllAlivePlayerControls.Without(pc).RandomElement();
var outfit = pc.Data.DefaultOutfit;
pc.RpcShapeshift(target, false);
Main.CheckShapeshift[pc.PlayerId] = false;
Utils.RpcChangeSkin(pc, outfit);
}
pc.CheckAndSetUnshiftState();
}
}, 1.2f, "Reset Ability Cooldown Arter Mushroom Mixup");
+1
View File
@@ -2651,6 +2651,7 @@
"AntiBlackOutLoggerSendInGame": "Because of an unknown error, the game will end to prevent black screen.",
"AntiBlackOutRequestHostToForceEnd": "You were the reason of the black screen, you are asking the host to stop the game...",
"AntiBlackOutHostRejectForceEnd": "You were the reason of the black screen, and the host is not going to end the game, we will disconnect you soon.",
"AntiBlackout.OverrideExiledPlayer": "To prevent black screens, the ejection screen shows a tied vote. (Players still get ejected, this is just visual.)",
"GitHub": "GitHub",
"Discord": "Discord",
"Website": "Website",
+1 -2
View File
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using AmongUs.GameOptions;
using UnityEngine;
using static EHR.Options;
@@ -61,7 +60,7 @@ public class Workhorse : IAddon
{
if (!pc.IsAlive() || IsThisRole(pc.PlayerId)) return false;
if (pc.Is(CustomRoles.Needy) || pc.Is(CustomRoles.Lazy) || pc.Is(CustomRoles.Bloodlust)) return false;
if (pc.GetCustomRole().GetDYRole() == RoleTypes.Impostor || pc.GetCustomRole().GetVNRole() is CustomRoles.Impostor or CustomRoles.Shapeshifter) return false;
if (pc.GetCustomRole().GetVNRole(checkDesyncRole: true) is CustomRoles.Impostor or CustomRoles.Shapeshifter) return false;
var taskState = pc.GetTaskState();
if (taskState.CompletedTasksCount + 1 < taskState.AllTasksCount) return false;
+9 -11
View File
@@ -55,17 +55,15 @@ namespace EHR.Crewmate
private static string GetRoleBasis(CustomRoles role) =>
SeeRoleBasis.GetBool()
? role.GetDYRole() == RoleTypes.Impostor
? Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("Impostor"))
: role.GetVNRole() switch
{
CustomRoles.Impostor => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("Impostor")),
CustomRoles.Shapeshifter => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Speedrunner), GetString("Shapeshifter")),
CustomRoles.Crewmate => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Crewmate), GetString("Crewmate")),
CustomRoles.Engineer => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Autocrat), GetString("Engineer")),
CustomRoles.Scientist => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Doctor), GetString("Scientist")),
_ => string.Empty
}
? role.GetVNRole(checkDesyncRole: true) switch
{
CustomRoles.Impostor => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Impostor), GetString("Impostor")),
CustomRoles.Shapeshifter => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Speedrunner), GetString("Shapeshifter")),
CustomRoles.Crewmate => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Crewmate), GetString("Crewmate")),
CustomRoles.Engineer => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Autocrat), GetString("Engineer")),
CustomRoles.Scientist => Utils.ColorString(Utils.GetRoleColor(CustomRoles.Doctor), GetString("Scientist")),
_ => string.Empty
}
: string.Empty;
private static int GetKillCount(byte id) => SeeKillCount.GetBool() ? Main.PlayerStates.Count(x => x.Value.GetRealKiller() == id) : 0;
+1 -1
View File
@@ -209,7 +209,7 @@ namespace EHR.Crewmate
if (!target.Is(CustomRoleTypes.Crewmate) || target.IsConverted()) return true;
CustomRoles role = GovernmentRecruitRoles[DecreeSettings[Decree.GovernmentRecruiting][1].GetValue()];
if (role.GetDYRole() == RoleTypes.Impostor && target.GetRoleTypes() != RoleTypes.Impostor) role = CustomRoles.NiceGuesser;
if (role.IsDesyncRole() && target.GetRoleTypes() != role.GetDYRole()) role = CustomRoles.NiceGuesser;
target.RpcSetCustomRole(role);
Utils.SendMessage("\n", target.PlayerId, Translator.GetString("President.Recruit.TargetNotifyMessage"));
Main.DontCancelVoteList.Add(voter.PlayerId);
+1 -2
View File
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
using EHR.Impostor;
using EHR.Modules;
using Hazel;
@@ -78,7 +77,7 @@ public class Psychic : RoleBase
{
if (target == null || seer == null) return false;
if (Main.PlayerStates[seer.PlayerId].Role is not Psychic ph) return false;
if (seer.Is(CustomRoles.Madmate)) return target.GetCustomRole().IsNeutral() || target.GetCustomRole().GetDYRole() == RoleTypes.Impostor;
if (seer.Is(CustomRoles.Madmate)) return target.GetCustomRole().IsNeutral() || target.GetCustomRole().GetCrewmateRoleCategory() == RoleOptionType.Crewmate_Killing;
return ph.RedPlayer != null && ph.RedPlayer.Contains(target.PlayerId);
}
+4 -4
View File
@@ -49,11 +49,11 @@ namespace EHR.Impostor
IEnumerable<CustomRoles> result = AvailableRoles.GetValue() switch
{
0 => allRoles,
1 => allRoles.Where(x => x.GetVNRole() is CustomRoles.Impostor or CustomRoles.ImpostorEHR),
2 => allRoles.Where(x => x.GetVNRole() is CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR),
1 => allRoles.Where(x => x.GetVNRole(checkDesyncRole: true) is CustomRoles.Impostor or CustomRoles.ImpostorEHR),
2 => allRoles.Where(x => x.GetVNRole(checkDesyncRole: true) is CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR),
3 => allRoles.Where(x => x.GetMode() != 0),
4 => allRoles.Where(x => x.GetVNRole() is CustomRoles.Impostor or CustomRoles.ImpostorEHR && x.GetMode() != 0),
5 => allRoles.Where(x => x.GetVNRole() is CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR && x.GetMode() != 0),
4 => allRoles.Where(x => x.GetVNRole(checkDesyncRole: true) is CustomRoles.Impostor or CustomRoles.ImpostorEHR && x.GetMode() != 0),
5 => allRoles.Where(x => x.GetVNRole(checkDesyncRole: true) is CustomRoles.Shapeshifter or CustomRoles.ShapeshifterEHR && x.GetMode() != 0),
_ => allRoles
};
+1 -1
View File
@@ -24,8 +24,8 @@ public class Councillor : RoleBase
private static OptionItem KillCooldown;
public static OptionItem CouncillorAbilityUseGainWithEachKill;
private static Dictionary<byte, int> MeetingKillLimit = [];
private byte CouncillorId;
private byte CouncillorId;
public override bool IsEnable => playerIdList.Count > 0;
public override void SetupCustomOption()
+17 -8
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using EHR.Impostor;
using EHR.Modules;
@@ -201,17 +202,25 @@ public class Doppelganger : RoleBase
public override void OnReportDeadBody()
{
if (ResetMode.GetValue() == 1 && TotalSteals[DGId] > 0)
try
{
var pc = Utils.GetPlayerById(DGId);
var currentTarget = Main.AllPlayerControls.FirstOrDefault(x => x.GetRealName() == DoppelVictim[pc.PlayerId]);
if (currentTarget != null)
if (ResetMode.GetValue() == 1 && TotalSteals[DGId] > 0)
{
RpcChangeSkin(currentTarget, DoppelPresentSkin[currentTarget.PlayerId]);
RpcChangeSkin(pc, DoppelDefaultSkin[pc.PlayerId]);
DoppelVictim[pc.PlayerId] = string.Empty;
var pc = Utils.GetPlayerById(DGId);
if (pc == null) return;
var currentTarget = Main.AllPlayerControls.FirstOrDefault(x => x?.GetRealName() == DoppelVictim[pc.PlayerId]);
if (currentTarget != null)
{
RpcChangeSkin(currentTarget, DoppelPresentSkin[currentTarget.PlayerId]);
RpcChangeSkin(pc, DoppelDefaultSkin[pc.PlayerId]);
DoppelVictim[pc.PlayerId] = string.Empty;
}
}
}
catch (Exception e)
{
Utils.ThrowException(e);
}
}
public override void OnFixedUpdate(PlayerControl pc)
+23 -9
View File
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AmongUs.GameOptions;
@@ -9,7 +10,7 @@ namespace EHR.Neutral;
public class Jackal : RoleBase
{
private const int Id = 12100;
private static List<byte> PlayerIdList = [];
public static List<Jackal> Instances = [];
private static OptionItem KillCooldown;
private static OptionItem CanVent;
@@ -30,7 +31,7 @@ public class Jackal : RoleBase
public static bool On;
private byte SidekickId;
public override bool IsEnable => PlayerIdList.Count > 0;
public override bool IsEnable => Instances.Count > 0;
public override void SetupCustomOption()
{
@@ -80,14 +81,14 @@ public class Jackal : RoleBase
public override void Init()
{
PlayerIdList = [];
Instances = [];
On = false;
}
public override void Add(byte playerId)
{
On = true;
PlayerIdList.Add(playerId);
Instances.Add(this);
playerId.SetAbilityUseLimit(1);
SidekickId = byte.MaxValue;
}
@@ -148,11 +149,24 @@ public class Jackal : RoleBase
public override void OnFixedUpdate(PlayerControl pc)
{
if (!SKPromotesToJackal.GetBool() || pc.IsAlive()) return;
var sk = SidekickId.GetPlayer();
if (sk == null || !sk.Is(CustomRoles.Sidekick)) return;
sk.RpcSetCustomRole(CustomRoles.Jackal);
if (!PromotedSKCanRecruit.GetBool()) sk.SetAbilityUseLimit(0);
if (pc.IsAlive()) return;
PromoteSidekick();
}
public void PromoteSidekick()
{
try
{
if (!SKPromotesToJackal.GetBool()) return;
var sk = SidekickId.GetPlayer();
if (sk == null || !sk.Is(CustomRoles.Sidekick)) return;
sk.RpcSetCustomRole(CustomRoles.Jackal);
if (!PromotedSKCanRecruit.GetBool()) sk.SetAbilityUseLimit(0);
}
catch (Exception e)
{
Utils.ThrowException(e);
}
}
}