some changes

This commit is contained in:
Gurge44 committed 2025-05-07 20:21:31 +02:00
1 parent d8a5f1ec61
commit 4e791b5fa2
17 files changed
+212 -110

No files matched your search

+19 -30
View File
@@ -147,20 +147,19 @@ internal static class FreeForAll
if (Main.GM.Value && AmongUsClient.Instance.AmHost) allPlayers = allPlayers.Without(PlayerControl.LocalPlayer).ToArray();
allPlayers = allPlayers.ExceptBy(ChatCommands.Spectators, x => x.PlayerId).ToArray();
foreach (PlayerControl pc in allPlayers) KillCount[pc.PlayerId] = 0;
foreach (PlayerControl pc in allPlayers)
{
KillCount[pc.PlayerId] = 0;
Utils.SendRPC(CustomRPC.FFASync, pc.PlayerId, 0);
}
if (FFATeamMode.GetBool())
{
int teamNum = FFATeamNumber.GetInt();
int playerNum = allPlayers.Length;
int memberNum = (teamNum > 5 && playerNum >= 15) || playerNum % teamNum == 0 ? playerNum / teamNum : (playerNum / teamNum) + 1;
List<byte[]> teamMembers = allPlayers.Select(x => x.PlayerId).Shuffle().Chunk(memberNum).ToList();
int i = 0;
for (var i = 0; i < teamMembers.Count; i++)
{
foreach (byte id in teamMembers[i])
PlayerTeams.Add(id, i);
}
foreach (IEnumerable<byte> ids in allPlayers.Select(x => x.PlayerId).Shuffle().Partition(FFATeamNumber.GetInt()))
foreach (byte id in ids)
PlayerTeams[id] = i++;
}
}
@@ -291,17 +290,14 @@ internal static class FreeForAll
// De-Buff
case 8:
{
var EffectID = (byte)IRandom.Instance.Next(0, 3);
if (Main.NormalOptions.MapId == 4) EffectID = 1;
var effectID = (byte)IRandom.Instance.Next(0, 3);
if (Main.NormalOptions.MapId == 4) effectID = 1;
switch (EffectID)
switch (effectID)
{
case 0:
if (FFADecreasedSpeedList.ContainsKey(killer.PlayerId))
{
FFADecreasedSpeedList.Remove(killer.PlayerId);
if (FFADecreasedSpeedList.Remove(killer.PlayerId))
FFADecreasedSpeedList.Add(killer.PlayerId, Utils.TimeStamp);
}
else
{
FFADecreasedSpeedList.TryAdd(killer.PlayerId, Utils.TimeStamp);
@@ -361,25 +357,18 @@ internal static class FreeForAll
ChatCommands.Spectators.ToValidPlayers().Do(x => x.KillFlash());
KillCount[killer.PlayerId]++;
Utils.SendRPC(CustomRPC.FFASync, killer.PlayerId, KillCount[killer.PlayerId]);
}
public static string GetPlayerArrow(PlayerControl seer, PlayerControl target = null)
{
if (GameStates.IsMeeting) return string.Empty;
if (GameStates.IsMeeting || target != null && seer.PlayerId != target.PlayerId || Main.AllAlivePlayerControls.Length != 2) return string.Empty;
if (target != null && seer.PlayerId != target.PlayerId) return string.Empty;
if (Main.AllAlivePlayerControls.Length != 2) return string.Empty;
var arrows = string.Empty;
PlayerControl otherPlayer = Main.AllAlivePlayerControls.FirstOrDefault(pc => pc.IsAlive() && pc.PlayerId != seer.PlayerId);
if (otherPlayer == null) return string.Empty;
string arrow = TargetArrow.GetArrows(seer, otherPlayer.PlayerId);
arrows += Utils.ColorString(Utils.GetRoleColor(CustomRoles.Killer), arrow);
return arrows;
return Utils.ColorString(Utils.GetRoleColor(CustomRoles.Killer), arrow);
}
public static void UpdateLastChatMessage(string playerName, string message)
@@ -405,10 +394,10 @@ internal static class FreeForAll
RoundTime--;
var rd = IRandom.Instance;
var FFAdoTPdecider = (byte)rd.Next(0, 100);
bool FFAdoTP = FFAdoTPdecider == 0;
var ffaDoTPdecider = (byte)rd.Next(0, 100);
bool ffaDoTP = ffaDoTPdecider == 0;
if (FFAEnableRandomTwists.GetBool() && FFAdoTP)
if (FFAEnableRandomTwists.GetBool() && ffaDoTP)
{
Logger.Info("Swap everyone with someone", "FFA");
+2
View File
@@ -102,6 +102,7 @@ internal static class SoloPVP
PlayerDF.TryAdd(pc.PlayerId, 0f);
KBScore.TryAdd(pc.PlayerId, 0);
Utils.SendRPC(CustomRPC.SoloPVPSync, pc.PlayerId, 0);
LastHurt.TryAdd(pc.PlayerId, Utils.TimeStamp);
LastCountdownTime.TryAdd(pc.PlayerId, Utils.TimeStamp);
@@ -268,6 +269,7 @@ internal static class SoloPVP
ChatCommands.Spectators.ToValidPlayers().Do(x => x.KillFlash());
KBScore[killer.PlayerId]++;
Utils.SendRPC(CustomRPC.SoloPVPSync, killer.PlayerId, KBScore[killer.PlayerId]);
if (Options.CurrentGameMode == CustomGameMode.AllInOne)
Speedrun.ResetTimer(killer);
+3
View File
@@ -65,6 +65,9 @@ public static class AFKDetector
if (Vector2.Distance(pc.Pos(), data.LastPosition) > 0.1f && !TempIgnoredPlayers.Contains(pc.PlayerId))
{
if (ExtendedPlayerControl.BlackScreenWaitingPlayers.Contains(pc.PlayerId))
ExtendedPlayerControl.CancelBlackScreenFix.Add(pc.PlayerId);
PlayerData.Remove(pc.PlayerId);
ShieldedPlayers.Remove(pc.PlayerId);
return;
+12 -4
View File
@@ -25,7 +25,8 @@ internal static class ExtendedPlayerControl
{
public const MurderResultFlags ResultFlags = MurderResultFlags.Succeeded;
private static readonly HashSet<byte> BlackScreenWaitingPlayers = [];
public static readonly HashSet<byte> BlackScreenWaitingPlayers = [];
public static readonly HashSet<byte> CancelBlackScreenFix = [];
public static void SetRole(this PlayerControl player, RoleTypes role, bool canOverride = true)
{
@@ -943,9 +944,16 @@ internal static class ExtendedPlayerControl
{
Logger.Warn($"FixBlackScreen was called for {pc.GetNameWithRole()}, but the conditions are not met to execute this code right now, waiting until it becomes possible to do so", "FixBlackScreen");
while (GameStates.InGame && !GameStates.IsEnded && (GameStates.IsMeeting || ExileController.Instance || AntiBlackout.SkipTasks || Main.AllPlayerControls.All(x => x.IsAlive())))
while (GameStates.InGame && !GameStates.IsEnded && !CancelBlackScreenFix.Contains(pc.PlayerId) && (GameStates.IsMeeting || ExileController.Instance || AntiBlackout.SkipTasks || Main.AllPlayerControls.All(x => x.IsAlive())))
yield return null;
if (CancelBlackScreenFix.Remove(pc.PlayerId))
{
Logger.Msg($"The black screen fix was canceled for {pc.GetNameWithRole()}", "FixBlackScreen");
BlackScreenWaitingPlayers.Remove(pc.PlayerId);
yield break;
}
if (!GameStates.InGame || GameStates.IsEnded)
{
Logger.Msg($"During the waiting, the game ended, so the black screen fix will not be executed for {pc.GetNameWithRole()}", "FixBlackScreen");
@@ -1001,7 +1009,7 @@ internal static class ExtendedPlayerControl
dummyGhost.NetTransform.SnapTo(murderPos, (ushort)(dummyGhost.NetTransform.lastSequenceId + 328));
dummyGhost.NetTransform.SetDirtyBit(uint.MaxValue);
sender.AutoStartRpc(dummyGhost.NetTransform.NetId, (byte)RpcCalls.SnapTo);
sender.AutoStartRpc(dummyGhost.NetTransform.NetId, 21);
sender.WriteVector2(murderPos);
sender.Write((ushort)(dummyGhost.NetTransform.lastSequenceId + 8));
sender.EndRpc();
@@ -1032,7 +1040,7 @@ internal static class ExtendedPlayerControl
dummyGhost.NetTransform.SnapTo(ghostPos, (ushort)(dummyGhost.NetTransform.lastSequenceId + 328));
dummyGhost.NetTransform.SetDirtyBit(uint.MaxValue);
sender.AutoStartRpc(dummyGhost.NetTransform.NetId, (byte)RpcCalls.SnapTo);
sender.AutoStartRpc(dummyGhost.NetTransform.NetId, 21);
sender.WriteVector2(ghostPos);
sender.Write((ushort)(dummyGhost.NetTransform.lastSequenceId + 8));
sender.EndRpc();
+7 -2
View File
@@ -139,7 +139,7 @@ public class PlayerState(byte playerId)
Logger.Info($"ID {PlayerId} ({Player.GetRealName()}) => {role}, CountTypes => {countTypes}", "SetMainRole");
if (Main.IntroDestroyed)
if (Main.IntroDestroyed && GameStates.InGame)
{
if (!previousHasTasks && Utils.HasTasks(Player.Data, false))
{
@@ -150,7 +150,7 @@ public class PlayerState(byte playerId)
if (!AmongUsClient.Instance.AmHost) return;
if (Main.IntroDestroyed)
if (Main.IntroDestroyed && GameStates.InGame)
{
Player.ResetKillCooldown();
@@ -185,6 +185,8 @@ public class PlayerState(byte playerId)
Utils.NotifyRoles(SpecifySeer: Player);
Utils.NotifyRoles(SpecifyTarget: Player);
HudSpritePatch.ResetButtonIcons = true;
}
CheckMurderPatch.TimeSinceLastKill.Remove(PlayerId);
@@ -210,6 +212,9 @@ public class PlayerState(byte playerId)
SetAddonCountTypes(role);
if (Main.IntroDestroyed && GameStates.InGame)
HudSpritePatch.ResetButtonIcons = true;
Logger.Info($" ID {PlayerId} ({Player?.GetRealName()}) => {role}, CountTypes => {countTypes}", "SetSubRole");
}
+3 -1
View File
@@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using EHR.AddOns.Common;
using EHR.AddOns.GhostRoles;
@@ -42,7 +43,8 @@ public static class NameColorManager
switch (Options.CurrentGameMode)
{
case CustomGameMode.FFA when FreeForAll.FFATeamMode.GetBool():
color = FreeForAll.TeamColors[FreeForAll.PlayerTeams[target.PlayerId]];
if (FreeForAll.PlayerTeams.TryGetValue(target.PlayerId, out int team))
color = FreeForAll.TeamColors.GetValueOrDefault(team, "#00ffff");
return true;
case CustomGameMode.RoomRush:
case CustomGameMode.NaturalDisasters:
+19 -2
View File
@@ -71,7 +71,6 @@ public enum CustomRPC
SyncRabbit,
SyncSoulHunter,
// BAU should always be 150
BAU = 150,
SyncMycologist,
@@ -143,12 +142,15 @@ public enum CustomRPC
SyncOverheat,
SyncIntrovert,
SyncAllergic,
SyncAsthmatic,
// Game Modes
RoomRushDataSync,
FFAKill,
FFASync,
QuizSync,
HotPotatoSync
HotPotatoSync,
SoloPVPSync
}
public enum Sounds
@@ -595,6 +597,11 @@ internal static class RPCHandlerPatch
Allergic.ReceiveRPC(reader);
break;
}
case CustomRPC.SyncAsthmatic:
{
Asthmatic.ReceiveRPC(reader);
break;
}
case CustomRPC.SetBountyTarget:
{
byte bountyId = reader.ReadByte();
@@ -1133,6 +1140,11 @@ internal static class RPCHandlerPatch
FreeForAll.OnPlayerAttack(killer, target);
break;
}
case CustomRPC.FFASync:
{
FreeForAll.KillCount[reader.ReadByte()] = reader.ReadPackedInt32();
break;
}
case CustomRPC.QuizSync:
{
Quiz.AllowKills = reader.ReadBoolean();
@@ -1143,6 +1155,11 @@ internal static class RPCHandlerPatch
HotPotato.ReceiveRPC(reader);
break;
}
case CustomRPC.SoloPVPSync:
{
SoloPVP.KBScore[reader.ReadByte()] = reader.ReadPackedInt32();
break;
}
}
}
catch (Exception e) { Utils.ThrowException(e); }
+6 -6
View File
@@ -62,7 +62,6 @@ public static class Utils
private static readonly Dictionary<byte, (string Text, int Duration, bool Long)> LongRoleDescriptions = [];
private static int NumSnapToRPCsThisRound;
public static long TimeStamp => (long)(DateTime.Now.ToUniversalTime() - TimeStampStartTime).TotalSeconds;
public static bool DoRPC => AmongUsClient.Instance.AmHost && Main.AllPlayerControls.Any(x => x.IsModdedClient() && !x.IsHost());
public static int TotalTaskCount => Main.RealOptionsData.GetInt(Int32OptionNames.NumCommonTasks) + Main.RealOptionsData.GetInt(Int32OptionNames.NumLongTasks) + Main.RealOptionsData.GetInt(Int32OptionNames.NumShortTasks);
@@ -154,8 +153,7 @@ public static class Utils
}
var newSid = (ushort)(nt.lastSequenceId + 8);
SendOption sendOption = NumSnapToRPCsThisRound < 100 || GameStates.CurrentServerType != GameStates.ServerType.Vanilla || DateTime.UtcNow.Month < 4 ? SendOption.Reliable : SendOption.None;
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(nt.NetId, (byte)RpcCalls.SnapTo, sendOption);
MessageWriter messageWriter = AmongUsClient.Instance.StartRpcImmediately(nt.NetId, (byte)RpcCalls.SnapTo, SendOption.Reliable);
NetHelpers.WriteVector2(location, messageWriter);
messageWriter.Write(newSid);
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
@@ -165,7 +163,6 @@ public static class Utils
CheckInvalidMovementPatch.LastPosition[pc.PlayerId] = location;
CheckInvalidMovementPatch.ExemptedPlayers.Add(pc.PlayerId);
NumSnapToRPCsThisRound++;
return true;
}
@@ -3482,8 +3479,11 @@ public static class Utils
summary = $"{ColorString(Main.PlayerColors[id], name)} - <#e8cd46>{GetString("SurvivedTimePrefix")}: <#ffffff>{(time2 == 0 ? $"{GetString("SurvivedUntilTheEnd")}</color>" : $"{time2}</color>s")}</color> ({GetVitalText(id, true)})";
break;
case CustomGameMode.RoomRush:
int time3 = RoomRush.GetSurvivalTime(id);
summary = $"{ColorString(Main.PlayerColors[id], name)} - <#e8cd46>{GetString("SurvivedTimePrefix")}: <#ffffff>{(time3 == 0 ? RoomRush.PointsSystem ? string.Empty : $"{GetString("SurvivedUntilTheEnd")}</color>" : $"{time3}</color>s")}</color> ({(RoomRush.PointsSystem ? RoomRush.GetPoints(id) : GetVitalText(id, true))})";
int rrSurvivalTime = RoomRush.GetSurvivalTime(id);
string rrSurvivalTimeText = rrSurvivalTime == 0 ? $"{GetString("SurvivedUntilTheEnd")}</color>" : $"{rrSurvivalTime}</color>s";
string rrSurvivedText = RoomRush.PointsSystem ? RoomRush.GetPoints(id) : $"{GetString("SurvivedTimePrefix")}: <#ffffff>{rrSurvivalTimeText}</color>";
string vitalText = RoomRush.PointsSystem ? string.Empty : $" ({GetVitalText(id, true)})";
summary = $"{ColorString(Main.PlayerColors[id], name)} - <#e8cd46>{rrSurvivedText}{vitalText}";
break;
case CustomGameMode.CaptureTheFlag:
summary = $"{ColorString(Main.PlayerColors[id], name)}: {CaptureTheFlag.GetStatistics(id)}";
+77 -28
View File
@@ -282,7 +282,8 @@ internal static class GameEndChecker
if ((WinnerTeam == CustomWinner.Lovers || WinnerIds.Any(x => Main.PlayerStates[x].SubRoles.Contains(CustomRoles.Lovers))) && Main.LoversPlayers.TrueForAll(x => x.IsAlive()) && reason != GameOverReason.CrewmatesByTask)
{
if (WinnerTeam != CustomWinner.Lovers) AdditionalWinnerTeams.Add(AdditionalWinners.Lovers);
if (WinnerTeam != CustomWinner.Lovers)
AdditionalWinnerTeams.Add(AdditionalWinners.Lovers);
WinnerIds.UnionWith(Main.LoversPlayers.Select(x => x.PlayerId));
}
@@ -404,6 +405,50 @@ internal static class GameEndChecker
GameManager.Instance.RpcEndGame(reason, false);
}
private static bool WouldWinIfCrewLost(PlayerState state)
{
try
{
switch (state.MainRole)
{
case CustomRoles.Phantasm when state.TaskState.RemainingTasksCount <= 0 && state.IsDead:
case CustomRoles.VengefulRomantic when VengefulRomantic.HasKilledKiller:
case CustomRoles.SchrodingersCat when !state.SubRoles.Any(x => x.IsConverted()):
case CustomRoles.Opportunist when !state.IsDead:
case CustomRoles.Sunnyboy when state.IsDead:
case CustomRoles.Maverick when !state.IsDead && state.Role is Maverick mr && mr.NumOfKills >= Maverick.MinKillsToWin.GetInt():
case CustomRoles.Provocateur when Provocateur.Provoked.TryGetValue(state.Player.PlayerId, out byte tar) && !WinnerIds.Contains(tar):
case CustomRoles.FFF when ((FFF)state.Role).IsWon:
case CustomRoles.Postman when ((Postman)state.Role).IsFinished:
case CustomRoles.Dealer when ((Dealer)state.Role).IsWon:
case CustomRoles.Impartial when ((Impartial)state.Role).IsWon:
case CustomRoles.Tank when ((Tank)state.Role).IsWon:
case CustomRoles.Technician when ((Technician)state.Role).IsWon:
case CustomRoles.Backstabber when ((Backstabber)state.Role).CheckWin():
case CustomRoles.Predator when ((Predator)state.Role).IsWon:
case CustomRoles.Gaslighter when ((Gaslighter)state.Role).AddAsAdditionalWinner():
case CustomRoles.SoulHunter when ((SoulHunter)state.Role).Souls >= SoulHunter.NumOfSoulsToWin.GetInt():
case CustomRoles.Curser:
case CustomRoles.NoteKiller when !NoteKiller.CountsAsNeutralKiller && NoteKiller.Kills >= NoteKiller.NumKillsNeededToWin:
case CustomRoles.NecroGuesser when ((NecroGuesser)state.Role).GuessedPlayers >= NecroGuesser.NumGuessesToWin.GetInt():
case CustomRoles.RoomRusher when ((RoomRusher)state.Role).Won:
case CustomRoles.Auditor:
case CustomRoles.Magistrate:
case CustomRoles.Seamstress:
case CustomRoles.Spirit:
case CustomRoles.Starspawn:
return true;
default:
return false;
}
}
catch (Exception e)
{
ThrowException(e);
return false;
}
}
public static void SetPredicateToNormal()
{
Predicate = new NormalGameEndPredicate();
@@ -495,7 +540,7 @@ internal static class GameEndChecker
return true;
}
if (aapc.All(x => Main.LoversPlayers.Exists(l => l.PlayerId == x.PlayerId)) && (!Main.LoversPlayers.TrueForAll(x => x.Is(Team.Crewmate)) || !Lovers.CrewLoversWinWithCrew.GetBool()))
if (aapc.Length > 0 && aapc.All(x => Main.LoversPlayers.Exists(l => l.PlayerId == x.PlayerId)) && (!Main.LoversPlayers.TrueForAll(x => x.Is(Team.Crewmate)) || !Lovers.CrewLoversWinWithCrew.GetBool()))
{
ResetAndSetWinner(CustomWinner.Lovers);
WinnerIds.UnionWith(Main.LoversPlayers.ConvertAll(x => x.PlayerId));
@@ -504,11 +549,16 @@ internal static class GameEndChecker
if (Main.AllAlivePlayerControls.Any(x => x.GetCountTypes() == CountTypes.CustomTeam)) return false;
var statesCoutingAsCrew = Main.PlayerStates.Values.Where(x => x.countTypes == CountTypes.Crew).ToList();
if (statesCoutingAsCrew.Count > 0 && statesCoutingAsCrew.TrueForAll(WouldWinIfCrewLost))
statesCoutingAsCrew.ForEach(x => x.countTypes = CountTypes.None);
int sheriffCount = AlivePlayersCount(CountTypes.Sheriff);
int Imp = AlivePlayersCount(CountTypes.Impostor);
int Crew = AlivePlayersCount(CountTypes.Crew) + sheriffCount;
int Coven = AlivePlayersCount(CountTypes.Coven);
int imp = AlivePlayersCount(CountTypes.Impostor);
int crew = AlivePlayersCount(CountTypes.Crew) + sheriffCount;
int coven = AlivePlayersCount(CountTypes.Coven);
Dictionary<(CustomRoles? Role, CustomWinner Winner), int> roleCounts = [];
@@ -532,9 +582,9 @@ internal static class GameEndChecker
{
if (!x.Is(CustomRoles.DualPersonality)) continue;
if (x.Is(Team.Impostor)) Imp++;
else if (x.Is(Team.Crewmate)) Crew++;
else if (x.Is(Team.Coven)) Coven++;
if (x.Is(Team.Impostor)) imp++;
else if (x.Is(Team.Crewmate)) crew++;
else if (x.Is(Team.Coven)) coven++;
if (x.Is(CustomRoles.Charmed)) roleCounts[(null, CustomWinner.Succubus)]++;
if (x.Is(CustomRoles.Undead)) roleCounts[(null, CustomWinner.Necromancer)]++;
@@ -551,19 +601,19 @@ internal static class GameEndChecker
if (totalNKAlive == 0)
{
if (Coven == 0)
if (coven == 0)
{
if (Crew == 0 && Imp == 0)
if (crew == 0 && imp == 0)
{
reason = GameOverReason.ImpostorsByKill;
winner = CustomWinner.None;
}
else if (Crew <= Imp && sheriffCount == 0)
else if (crew <= imp && sheriffCount == 0)
{
reason = GameOverReason.ImpostorsByKill;
winner = CustomWinner.Impostor;
}
else if (Imp == 0)
else if (imp == 0)
{
reason = GameOverReason.CrewmatesByVote;
winner = CustomWinner.Crewmate;
@@ -571,7 +621,7 @@ internal static class GameEndChecker
else
return false;
Logger.Info($"Crew: {Crew}, Imp: {Imp}, Coven: {Coven}", "CheckGameEndPatch.CheckGameEndByLivingPlayers");
Logger.Info($"Crew: {crew}, Imp: {imp}, Coven: {coven}", "CheckGameEndPatch.CheckGameEndByLivingPlayers");
ResetAndSetWinner((CustomWinner)winner);
if (winner == CustomWinner.Crewmate && Main.AllAlivePlayerControls.All(x => x.GetCustomRole().IsNeutral()))
@@ -582,11 +632,11 @@ internal static class GameEndChecker
}
else
{
if (Imp >= 1) return false;
if (Crew > Coven) return false;
if (imp >= 1) return false;
if (crew > coven) return false;
if (sheriffCount > 0) return false;
Logger.Info($"Crew: {Crew}, Imp: {Imp}, Coven: {Coven}", "CheckGameEndPatch.CheckGameEndByLivingPlayers");
Logger.Info($"Crew: {crew}, Imp: {imp}, Coven: {coven}", "CheckGameEndPatch.CheckGameEndByLivingPlayers");
reason = GameOverReason.ImpostorsByKill;
ResetAndSetWinner(CustomWinner.Coven);
}
@@ -594,9 +644,9 @@ internal static class GameEndChecker
return true;
}
if (Imp >= 1) return false; // both imps and NKs are alive, game must continue
if (Coven >= 1) return false; // both covens and NKs are alive, game must continue
if (Crew > totalNKAlive) return false; // Imps are dead, but crew still outnumbers NKs, game must continue
if (imp >= 1) return false; // both imps and NKs are alive, game must continue
if (coven >= 1) return false; // both covens and NKs are alive, game must continue
if (crew > totalNKAlive) return false; // Imps are dead, but crew still outnumbers NKs, game must continue
// Imps dead, Crew <= NK, Checking if all NKs alive are in 1 team
List<int> aliveCounts = roleCounts.Values.Where(x => x > 0).ToList();
@@ -631,9 +681,7 @@ internal static class GameEndChecker
}
if (winner != null) ResetAndSetWinner((CustomWinner)winner);
if (rl != null) WinnerRoles.Add((CustomRoles)rl);
return true;
}
}
@@ -773,7 +821,7 @@ internal static class GameEndChecker
case 0:
MoveAndStop.RoundTime = 0;
Logger.Warn("No players alive. Force ending the game", "MoveAndStop");
return false;
break;
}
return false;
@@ -1029,23 +1077,23 @@ internal static class GameEndChecker
}
/// <summary>Determines whether sabotage victory is possible based on the elements in ShipStatus.Systems.</summary>
public virtual bool CheckGameEndBySabotage(out GameOverReason reason)
protected virtual bool CheckGameEndBySabotage(out GameOverReason reason)
{
reason = GameOverReason.ImpostorsByKill;
if (ShipStatus.Instance.Systems == null) return false;
// TryGetValue is not available
Il2CppSystem.Collections.Generic.Dictionary<SystemTypes, ISystemType> systems = ShipStatus.Instance.Systems;
LifeSuppSystemType LifeSupp;
LifeSuppSystemType lifeSupp;
if (systems.ContainsKey(SystemTypes.LifeSupp) && // Confirmation of sabotage existence
(LifeSupp = systems[SystemTypes.LifeSupp].CastFast<LifeSuppSystemType>()) != null && // Confirmation that cast is possible
LifeSupp.Countdown <= 0f) // Time up confirmation
(lifeSupp = systems[SystemTypes.LifeSupp].CastFast<LifeSuppSystemType>()) != null && // Confirmation that cast is possible
lifeSupp.Countdown <= 0f) // Time up confirmation
{
// oxygen sabotage
ResetAndSetWinner(CustomWinner.Impostor);
reason = GameOverReason.ImpostorsBySabotage;
LifeSupp.Countdown = 10000f;
lifeSupp.Countdown = 10000f;
return true;
}
@@ -1055,7 +1103,8 @@ internal static class GameEndChecker
sys = systems[SystemTypes.Reactor];
else if (systems.ContainsKey(SystemTypes.Laboratory))
sys = systems[SystemTypes.Laboratory];
else if (systems.ContainsKey(SystemTypes.HeliSabotage)) sys = systems[SystemTypes.HeliSabotage];
else if (systems.ContainsKey(SystemTypes.HeliSabotage))
sys = systems[SystemTypes.HeliSabotage];
ICriticalSabotage critical;
+8 -8
View File
@@ -29,6 +29,8 @@ public static class HudSpritePatch
private static long LastErrorTime;
public static bool ResetButtonIcons;
public static void Postfix(HudManager __instance)
{
try
@@ -39,7 +41,7 @@ public static class HudSpritePatch
if (!Main.EnableCustomButton.Value || !Main.ProcessShapeshifts || Mastermind.ManipulatedPlayers.ContainsKey(player.PlayerId) || ExileController.Instance || GameStates.IsMeeting) return;
if ((!SetHudActivePatch.IsActive && !MeetingStates.FirstMeeting) || !player.IsAlive() || Options.CurrentGameMode is not CustomGameMode.Standard and not CustomGameMode.CaptureTheFlag) return;
if (!AmongUsClient.Instance.IsGameStarted || !Main.IntroDestroyed)
if (ResetButtonIcons || !AmongUsClient.Instance.IsGameStarted || !Main.IntroDestroyed)
{
Kill = null;
Ability = null;
@@ -47,6 +49,8 @@ public static class HudSpritePatch
Sabotage = null;
Pet = null;
Report = null;
ResetButtonIcons = false;
return;
}
@@ -466,15 +470,11 @@ public static class HudSpritePatch
}
case CustomRoles.Warlock:
{
if (Options.UsePets.GetBool())
if (Options.UsePets.GetBool() || !shapeshifting)
{
newKillButton = CustomButton.Get("Curse");
if (Warlock.IsCurseAndKill.TryGetValue(player.PlayerId, out bool curse) && curse) newAbilityButton = CustomButton.Get("CurseKill");
}
else if (!shapeshifting)
{
newKillButton = CustomButton.Get("Curse");
if (Warlock.IsCurseAndKill.TryGetValue(player.PlayerId, out bool curse) && curse) newAbilityButton = CustomButton.Get("CurseKill");
if (Warlock.IsCurseAndKill.TryGetValue(player.PlayerId, out bool curse) && curse)
newAbilityButton = CustomButton.Get("CurseKill");
}
break;
+1 -1
View File
@@ -654,7 +654,7 @@ internal static class BeginCrewmatePatch
case CustomGameMode.FFA:
{
__instance.TeamTitle.text = GetString("Killer");
Color color = FreeForAll.PlayerTeams.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out int team) && ColorUtility.TryParseHtmlString(FreeForAll.TeamColors[team], out Color teamColor) ? teamColor : new(0, 255, 255, byte.MaxValue);
Color color = FreeForAll.PlayerTeams.TryGetValue(PlayerControl.LocalPlayer.PlayerId, out int team) && FreeForAll.TeamColors.TryGetValue(team, out var teamColorHex) && ColorUtility.TryParseHtmlString(teamColorHex, out Color teamColor) ? teamColor : new(0, 255, 255, byte.MaxValue);
__instance.TeamTitle.color = __instance.BackgroundBar.material.color = color;
PlayerControl.LocalPlayer.Data.Role.IntroSound = GetIntroSound(RoleTypes.Shapeshifter);
__instance.ImpostorText.gameObject.SetActive(true);
+2 -3
View File
@@ -1089,6 +1089,8 @@ internal static class ReportDeadBodyPatch
Damocles.CountRepairSabotage = false;
Stressed.CountRepairSabotage = false;
HudSpritePatch.ResetButtonIcons = true;
if (Options.CurrentGameMode == CustomGameMode.Standard)
{
foreach (byte id in Main.DiedThisRound)
@@ -1858,9 +1860,6 @@ internal static class FixedUpdatePatch
if (!self && CustomGameMode.KingOfTheZones.IsActiveOrIntegrated() && Main.IntroDestroyed && !KingOfTheZones.GameGoing)
realName = EmptyMessage;
if (Magistrate.CallCourtNextMeeting)
realName = target.Is(CustomRoles.Magistrate) ? GetString("Magistrate.CourtName") : GetString("Magistrate.JuryName");
string deathReason = seer.Data.IsDead && seer.KnowDeathReason(target) ? $"\n<size=1.5>『{ColorString(GetRoleColor(CustomRoles.Doctor), GetVitalText(target.PlayerId))}』</size>" : string.Empty;
string currentText = target.cosmetics.nameText.text;
+7 -13
View File
@@ -1,5 +1,5 @@
using System;
using System.Linq;
using System.Collections;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AmongUs.Data;
@@ -92,8 +92,8 @@ internal static class OnGameJoinedPatch
if (Options.AutoGMPollCommandAfterJoin.GetBool())
{
Main.Instance.StartCoroutine(CoRoutine());
System.Collections.IEnumerator CoRoutine()
IEnumerator CoRoutine()
{
float timer = Options.AutoGMPollCommandCooldown.GetInt();
@@ -103,7 +103,7 @@ internal static class OnGameJoinedPatch
timer -= Time.deltaTime;
yield return null;
}
ChatCommands.GameModePollCommand(PlayerControl.LocalPlayer, "/gmpoll", ["/gmpoll"]);
}
}
@@ -112,7 +112,7 @@ internal static class OnGameJoinedPatch
{
Main.Instance.StartCoroutine(CoRoutine());
System.Collections.IEnumerator CoRoutine()
IEnumerator CoRoutine()
{
float timer = Options.AutoDraftStartCommandCooldown.GetInt();
@@ -189,7 +189,7 @@ internal static class OnPlayerJoinedPatch
}
}
catch { }
}, 4f, "green bean kick late task", false);
}, 4.5f, "green bean kick late task", false);
if (AmongUsClient.Instance.AmHost && client.FriendCode == "" && Options.KickPlayerFriendCodeNotExist.GetBool() && !GameStates.IsLocalGame && GameStates.CurrentServerType is not GameStates.ServerType.ModdedWithCNOSupport and not GameStates.ServerType.ModdedWithoutCNOSupport)
{
@@ -208,12 +208,6 @@ internal static class OnPlayerJoinedPatch
Logger.Info(msg, "Android Kick");
}
if (AmongUsClient.Instance.AmHost && (client.PlayerName.EndsWith("cm", StringComparison.OrdinalIgnoreCase) || client.PlayerName.EndsWith("sm", StringComparison.OrdinalIgnoreCase)) && (client.PlayerName.Length == 4 || client.PlayerName.Count(x => x is 'i' or 'I') >= 2))
{
AmongUsClient.Instance.KickPlayer(client.Id, false);
Logger.SendInGame("They were probably hacking tbh");
}
if (FastDestroyableSingleton<FriendsListManager>.Instance.IsPlayerBlockedUsername(client.FriendCode) && AmongUsClient.Instance.AmHost && GameStates.CurrentServerType is not GameStates.ServerType.ModdedWithCNOSupport and not GameStates.ServerType.ModdedWithoutCNOSupport)
{
AmongUsClient.Instance.KickPlayer(client.Id, true);
@@ -549,7 +543,7 @@ internal static class SetColorPatch
AmongUsClient.Instance.KickPlayer(client.Id, false);
}
}
}, 4.5f, "fortegreen bean color kick");
}, 5f, "fortegreen bean color kick");
}
if (bodyColor == 255) return;
+1
View File
@@ -3491,6 +3491,7 @@
"WWRampageDur": "Rampage Duration",
"WWCanRampage": "Vent to begin Rampaging",
"WWCanRampageUnshift": "Press Unshift (shapeshift button) to begin Rampaging",
"WWCanRampageVanish": "Press Vanish to begin Rampaging",
"WWRampageOut": "You're no longer Rampaging",
"WWRampageCountdown": "<color=#00ffa5>Rampage ends in</color> <b>{0}</b>s",
"WWRampaging": "Rampaging",
+24 -3
View File
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using EHR.Modules;
using Hazel;
using UnityEngine;
using static EHR.Options;
@@ -97,7 +99,7 @@ internal class Asthmatic : IAddon
public static void OnCheckPlayerPosition(PlayerControl pc)
{
if (!pc.Is(CustomRoles.Asthmatic) || ExileController.Instance || !RunChecks || !Timers.TryGetValue(pc.PlayerId, out Counter counter)) return;
if (!Main.IntroDestroyed || !pc.Is(CustomRoles.Asthmatic) || ExileController.Instance || !RunChecks || !Timers.TryGetValue(pc.PlayerId, out Counter counter)) return;
Vector2 currentPosition = pc.transform.position;
@@ -138,13 +140,32 @@ internal class Asthmatic : IAddon
string suffix = GetSuffixText(pc.PlayerId);
if (!pc.IsModdedClient() && (!LastSuffix.TryGetValue(pc.PlayerId, out string beforeSuffix) || beforeSuffix != suffix)) Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
if (!pc.IsModdedClient() && (!LastSuffix.TryGetValue(pc.PlayerId, out string beforeSuffix) || beforeSuffix != suffix))
{
Utils.NotifyRoles(SpecifySeer: pc, SpecifyTarget: pc);
Utils.SendRPC(CustomRPC.SyncAsthmatic, pc.PlayerId, suffix);
}
LastSuffix[pc.PlayerId] = suffix;
}
public static void ReceiveRPC(MessageReader reader)
{
LastSuffix[reader.ReadByte()] = reader.ReadString();
}
public static string GetSuffixText(byte id)
{
return id.GetPlayer().IsAlive() && Timers.TryGetValue(id, out Counter counter) ? $"{counter.ColoredArrow} {counter.ColoredTimerString}" : string.Empty;
if (Main.PlayerStates.TryGetValue(id, out var state) && !state.IsDead)
{
if (Timers.TryGetValue(id, out Counter counter))
return $"{counter.ColoredArrow} {counter.ColoredTimerString}";
else if (id.IsPlayerModClient() && !id.IsHost())
return LastSuffix[id];
else
return string.Empty;
}
else
return string.Empty;
}
}
+10 -1
View File
@@ -1,4 +1,5 @@
using AmongUs.GameOptions;
using EHR.Modules;
namespace EHR.Impostor;
@@ -60,7 +61,15 @@ internal class Minimalism : RoleBase
if (BypassShields.GetBool())
{
killer.Kill(target);
if (killer.Is(CustomRoles.Swift))
{
target.Suicide(PlayerState.DeathReason.Kill, killer);
killer.SetKillCooldown();
RPC.PlaySoundRPC(killer.PlayerId, Sounds.KillSound);
}
else
killer.Kill(target);
return false;
}
+11 -8
View File
@@ -70,7 +70,7 @@ public class Werewolf : RoleBase
LateTask.New(() =>
{
if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool())
if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool() || UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
Utils.GetPlayerById(playerId).RpcResetAbilityCooldown();
}, 12f, log: false);
}
@@ -87,7 +87,7 @@ public class Werewolf : RoleBase
public override bool CanUseImpostorVentButton(PlayerControl pc)
{
return (CanRampage && (!UseUnshiftTrigger.GetBool() || !UseUnshiftTriggerForNKs.GetBool())) || IsRampaging || pc.inVent;
return (CanRampage && (!UsePhantomBasis.GetBool() || !UsePhantomBasisForNKs.GetBool()) && (!UseUnshiftTrigger.GetBool() || !UseUnshiftTriggerForNKs.GetBool())) || IsRampaging || pc.inVent;
}
public override bool CanUseKillButton(PlayerControl pc)
@@ -98,9 +98,12 @@ public class Werewolf : RoleBase
public override void ApplyGameOptions(IGameOptions opt, byte id)
{
opt.SetVision(HasImpostorVision.GetBool());
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool()) AURoleOptions.PhantomCooldown = 1f;
if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool()) AURoleOptions.ShapeshifterCooldown = RampageDur.GetFloat() + 0.5f;
if (UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool())
AURoleOptions.PhantomCooldown = 1f;
if (UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool())
AURoleOptions.ShapeshifterCooldown = RampageDur.GetFloat() + 0.5f;
AURoleOptions.EngineerCooldown = 0f;
AURoleOptions.EngineerInVentMaxTime = 0f;
@@ -149,12 +152,12 @@ public class Werewolf : RoleBase
if (lastTime + (long)RampageCD.GetFloat() < now)
{
lastTime = -10;
bool unshift = UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool();
bool otherTrigger = UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool() || UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool();
if (!player.IsModdedClient())
{
player.Notify(GetString(unshift ? "WWCanRampageUnshift" : "WWCanRampage"));
player.RpcChangeRoleBasis(unshift ? CustomRoles.Werewolf : CustomRoles.EngineerEHR);
player.Notify(GetString(otherTrigger ? "WWCanRampageUnshift" : "WWCanRampage"));
player.RpcChangeRoleBasis(otherTrigger ? CustomRoles.Werewolf : CustomRoles.EngineerEHR);
}
SendRPC();
@@ -246,7 +249,7 @@ public class Werewolf : RoleBase
str.Append(string.Format(GetString("WWCD"), cooldown + 1));
}
else
str.Append(GetString(UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool() ? "WWCanRampageUnshift" : "WWCanRampage"));
str.Append(GetString(UseUnshiftTrigger.GetBool() && UseUnshiftTriggerForNKs.GetBool() ? "WWCanRampageUnshift" : UsePhantomBasis.GetBool() && UsePhantomBasisForNKs.GetBool() ? "WWCanRampageVanish" : "WWCanRampage"));
return str.ToString();
}