mirror of
https://github.com/Gurge44/EndlessHostRoles.git
synced 2026-10-19 15:51:58 +00:00
Fixes & CTF uses unshift
This commit is contained in:
1 parent
ed97635cef
commit
6dca1deecb
27 files changed
+205
-176
No files matched your search
+10
-1
@@ -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
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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))
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user