Skip to content

Commit 8387e54

Browse files
committed
Fix
1 parent 12e60b9 commit 8387e54

12 files changed

Lines changed: 230 additions & 546 deletions

File tree

Modules/AntiBlackout.cs

Lines changed: 98 additions & 344 deletions
Large diffs are not rendered by default.

Modules/CustomRpcSender.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,4 +428,10 @@ public static bool TP(this CustomRpcSender sender, PlayerControl pc, Vector2 loc
428428
// if (sender.sendOption == SendOption.Reliable) Utils.NumSnapToCallsThisRound++;
429429
return true;
430430
}
431+
432+
public static bool RpcExileV2(this CustomRpcSender sender, PlayerControl player)
433+
{
434+
sender.RpcSetRole(player, player.GetGhostRoleBasis());
435+
return true;
436+
}
431437
}

Modules/ExtendedPlayerControl.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using TOHE.Roles.AddOns.Common;
1515
using TOHE.Roles.AddOns.Impostor;
1616
using TOHE.Roles.Core;
17+
using TOHE.Roles.Core.AssignManager;
1718
using TOHE.Roles.Coven;
1819
using TOHE.Roles.Crewmate;
1920
using TOHE.Roles.Impostor;
@@ -1041,6 +1042,47 @@ public static CountTypes GetCountTypes(this PlayerControl player)
10411042
return Main.PlayerStates.TryGetValue(player.PlayerId, out var State) ? State.countTypes : CountTypes.None;
10421043
}
10431044

1045+
// If you use vanilla RpcSetRole, it will block further SetRole calls until the next game starts.
1046+
public static void RpcSetRoleGlobal(this PlayerControl player, RoleTypes roleTypes, bool setRoleMap = false)
1047+
{
1048+
if (!AmongUsClient.Instance.AmHost) return;
1049+
if (AmongUsClient.Instance.AmClient) try { player.StartCoroutine(player.CoSetRole(roleTypes, true)); } catch { }
1050+
MessageWriter writer = AmongUsClient.Instance.StartRpcImmediately(player.NetId, (byte)RpcCalls.SetRole, SendOption.Reliable);
1051+
writer.Write((ushort)roleTypes);
1052+
writer.Write(true);
1053+
AmongUsClient.Instance.FinishRpcImmediately(writer);
1054+
Logger.Info($" {player.GetNameWithRole()} => {roleTypes}", "RpcSetRoleGlobal");
1055+
1056+
// if (setRoleMap)
1057+
// {
1058+
// foreach ((byte seerID, byte targetID) in StartGameHostPatch.RpcSetRoleReplacer.RoleMap.Keys.ToArray())
1059+
// {
1060+
// if (targetID == player.PlayerId)
1061+
// {
1062+
// var value = StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(seerID, targetID)];
1063+
// value.RoleType = roleTypes;
1064+
// StartGameHostPatch.RpcSetRoleReplacer.RoleMap[(seerID, targetID)] = value;
1065+
// }
1066+
// }
1067+
// }
1068+
}
1069+
1070+
public static RoleTypes GetGhostRoleBasis(this PlayerControl __instance)
1071+
{
1072+
RoleTypes roleType;
1073+
1074+
if (GhostRoleAssign.AssignedGhostRole.TryGetValue(__instance.PlayerId, out var ghostRole))
1075+
roleType = ghostRole.GetRoleTypes();
1076+
// else if (GhostRolesManager.ShouldHaveGhostRole(__instance))
1077+
// roleType = RoleTypes.GuardianAngel;
1078+
else if (!(__instance.Is(RoleTypes.Impostor) && Options.DeadImpCantSabotage.GetBool()) && __instance.GetRoleClass().CanUseSabotage(__instance))
1079+
roleType = RoleTypes.ImpostorGhost;
1080+
else
1081+
roleType = RoleTypes.CrewmateGhost;
1082+
1083+
return roleType;
1084+
}
1085+
10441086
public static DeadBody GetDeadBody(this NetworkedPlayerInfo playerData)
10451087
{
10461088
return UnityEngine.Object.FindObjectsOfType<DeadBody>().FirstOrDefault(bead => bead.ParentId == playerData.PlayerId);

Modules/Utils.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3325,8 +3325,6 @@ public static void AfterMeetingTasks()
33253325
if (Diseased.IsEnable) Diseased.AfterMeetingTasks();
33263326
if (Antidote.IsEnable) Antidote.AfterMeetingTasks();
33273327

3328-
AntiBlackout.AfterMeetingTasks();
3329-
33303328
try
33313329
{
33323330
CovenManager.CheckNecroVotes();

Patches/ExilePatch.cs

Lines changed: 68 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
using AmongUs.Data;
22
using AmongUs.GameOptions;
3+
using Hazel;
34
using System;
5+
using System.Diagnostics;
46
using TOHE.Roles.Core;
57
using TOHE.Roles.Neutral;
68

79
namespace TOHE;
810

911
class ExileControllerWrapUpPatch
1012
{
13+
public static Stopwatch Stopwatch;
1114
public static NetworkedPlayerInfo AntiBlackout_LastExiled;
1215
[HarmonyPatch(typeof(ExileController), nameof(ExileController.Begin))]
1316
class ExileControllerBeginPatch
@@ -89,8 +92,6 @@ private static void CheckAndDoRandomSpawn()
8992
}
9093
private static void WrapUpPostfix(NetworkedPlayerInfo exiled)
9194
{
92-
if (AntiBlackout.BlackOutIsActive) exiled = AntiBlackout_LastExiled;
93-
9495
// Still not springing up in Airship
9596
if (!GameStates.AirshipIsActive)
9697
{
@@ -102,7 +103,6 @@ private static void WrapUpPostfix(NetworkedPlayerInfo exiled)
102103

103104
bool DecidedWinner = false;
104105
if (!AmongUsClient.Instance.AmHost) return;
105-
AntiBlackout.RestoreIsDead(doSend: false);
106106

107107
List<Collector> collectorCL = Utils.GetRoleBasesByType<Collector>()?.ToList();
108108

@@ -152,100 +152,95 @@ private static void WrapUpFinalizer(NetworkedPlayerInfo exiled)
152152
// Even if an exception occurs in WrapUpPostfix, this is the only part that will be executed reliably
153153
if (AmongUsClient.Instance.AmHost)
154154
{
155-
_ = new LateTask(() =>
155+
Stopwatch = Stopwatch.StartNew();
156+
157+
LateTask.New(() =>
156158
{
157159
if (GameStates.IsEnded) return;
160+
AntiBlackout.RevertToActualRoleTypes();
161+
}, 2f, "Revert AntiBlackout Measures");
162+
}
158163

159-
exiled = AntiBlackout_LastExiled;
160-
AntiBlackout.SendGameData();
161-
AntiBlackout.SetRealPlayerRoles();
164+
//This should happen shortly after the Exile Controller wrap up finished for clients
165+
//For Certain Laggy clients 0.8f delay is still not enough. The finish time can differ
166+
//If the delay is too long, it will influence other normal players' view
162167

163-
if (AntiBlackout.BlackOutIsActive && // State in which the expulsion target is overwritten (need not be executed if the expulsion target is not overwritten)
164-
exiled && // Exiled is not null
165-
exiled.Object) //exiled.Object is not null
166-
{
167-
exiled.Object.RpcExileV2();
168-
}
169-
}, Options.CurrentGameMode is CustomGameMode.Standard ? 0.5f : 1.4f, "Restore IsDead Task");
168+
GameStates.AlreadyDied |= !Utils.IsAllAlive;
169+
RemoveDisableDevicesPatch.UpdateDisableDevices();
170+
SoundManager.Instance.ChangeAmbienceVolume(DataManager.Settings.Audio.AmbienceVolume);
170171

171-
_ = new LateTask(AntiBlackout.ResetAfterMeeting, 0.6f, "ResetAfterMeeting");
172+
_ = new LateTask(() =>
173+
{
174+
if (!AmongUsClient.Instance.IsGameOver)
175+
DestroyableSingleton<HudManager>.Instance.SetHudActive(true);
176+
}, 0.8f, "Set Hud Active");
172177

173-
_ = new LateTask(() =>
174-
{
175-
if (GameStates.IsEnded) return;
176178

177-
Main.AfterMeetingDeathPlayers.Do(x =>
178-
{
179-
var player = x.Key.GetPlayer();
180-
var state = Main.PlayerStates[x.Key];
181179

182-
Logger.Info($"{player?.GetNameWithRole().RemoveHtmlTags()} died with {x.Value}", "AfterMeetingDeath");
180+
Logger.Info("Start of Task Phase", "Phase");
181+
}
183182

184-
if (x.Value == PlayerState.DeathReason.Suicide)
185-
player?.SetRealKiller(player, true);
183+
public static void AfterMeetingTasks()
184+
{
185+
if (CustomWinnerHolder.WinnerTeam != CustomWinner.Default || GameStates.IsEnded){
186+
Stopwatch.Reset();
187+
return;
188+
}
186189

187-
state.deathReason = x.Value;
188-
state.SetDead();
189-
player?.RpcExileV2();
190+
bool hasValue = false;
191+
CustomRpcSender sender = CustomRpcSender.Create("Exile AfterMeetingDeathPlayers", SendOption.Reliable);
192+
Main.AfterMeetingDeathPlayers.Keys.ToValidPlayers().Do(x => hasValue |= sender.RpcExileV2(x));
193+
sender.SendMessage(dispose: !hasValue);
190194

191-
// Just to be sure
192-
_ = new LateTask(() => player?.RpcExile(), 0.5f, "Extra Exile to be Sure");
195+
foreach ((byte id, PlayerState.DeathReason deathReason) in Main.AfterMeetingDeathPlayers)
196+
{
197+
var player = id.GetPlayer();
198+
var state = Main.PlayerStates[id];
193199

194-
MurderPlayerPatch.AfterPlayerDeathTasks(player, player, true);
195-
});
200+
Logger.Info($"{player?.GetNameWithRole().RemoveHtmlTags()} died with {deathReason}", "AfterMeetingDeath");
196201

197-
Main.AfterMeetingDeathPlayers.Clear();
202+
if (deathReason == PlayerState.DeathReason.Suicide)
203+
player?.SetRealKiller(player, true);
198204

199-
Utils.AfterMeetingTasks();
200-
Utils.SyncAllSettings();
201-
Utils.CheckAndSetVentInteractions();
205+
state.deathReason = deathReason;
206+
state.SetDead();
202207

203-
if (Main.CurrentServerIsVanilla && Options.BypassRateLimitAC.GetBool())
204-
{
205-
Main.Instance.StartCoroutine(Utils.NotifyEveryoneAsync(speed: 5));
206-
}
207-
else
208-
{
209-
Utils.NotifyRoles();
210-
}
208+
if (!player) continue;
211209

212-
_ = new LateTask(() =>
213-
{
214-
foreach (var player in Main.EnumerateAlivePlayerControls())
215-
{
216-
if (player.GetRoleClass() is not DefaultSetup)
217-
{
218-
if (player.GetRoleClass().ThisRoleBase.GetRoleTypesDirect() is RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper)
219-
{
220-
player.ResetKillCooldown();
221-
if (Main.AllPlayerKillCooldown.TryGetValue(player.PlayerId, out var killTimer) && (killTimer - 2f) > 0f)
222-
{
223-
player.SetKillCooldown(killTimer - 2f);
224-
}
225-
}
226-
}
227-
}
228-
}, 1f, $"Fix Kill Cooldown Task after meeting");
210+
if (deathReason == PlayerState.DeathReason.Suicide)
211+
player.SetRealKiller(player, true);
229212

230-
Main.LastMeetingEnded = Utils.TimeStamp;
231-
}, 1f, "AfterMeetingDeathPlayers Task");
213+
MurderPlayerPatch.AfterPlayerDeathTasks(player, player, true);
232214
}
233215

234-
//This should happen shortly after the Exile Controller wrap up finished for clients
235-
//For Certain Laggy clients 0.8f delay is still not enough. The finish time can differ
236-
//If the delay is too long, it will influence other normal players' view
216+
Main.AfterMeetingDeathPlayers.Clear();
237217

238-
GameStates.AlreadyDied |= !Utils.IsAllAlive;
239-
RemoveDisableDevicesPatch.UpdateDisableDevices();
240-
SoundManager.Instance.ChangeAmbienceVolume(DataManager.Settings.Audio.AmbienceVolume);
218+
Utils.AfterMeetingTasks();
219+
Utils.SyncAllSettings();
220+
Utils.CheckAndSetVentInteractions();
221+
222+
Main.Instance.StartCoroutine(Utils.NotifyEveryoneAsync());
241223

242224
_ = new LateTask(() =>
243225
{
244-
if (!AmongUsClient.Instance.IsGameOver)
245-
DestroyableSingleton<HudManager>.Instance.SetHudActive(true);
246-
}, 0.8f, "Set Hud Active");
226+
foreach (var player in Main.EnumerateAlivePlayerControls())
227+
{
228+
if (player.GetRoleClass() is not DefaultSetup)
229+
{
230+
if (player.GetRoleClass().ThisRoleBase.GetRoleTypesDirect() is RoleTypes.Impostor or RoleTypes.Phantom or RoleTypes.Shapeshifter or RoleTypes.Viper)
231+
{
232+
player.ResetKillCooldown();
233+
if (Main.AllPlayerKillCooldown.TryGetValue(player.PlayerId, out var killTimer) && (killTimer - 2f) > 0f)
234+
{
235+
player.SetKillCooldown(killTimer - 2f);
236+
}
237+
}
238+
}
239+
}
240+
}, 1f, $"Fix Kill Cooldown Task after meeting");
247241

248-
Logger.Info("Start of Task Phase", "Phase");
242+
Main.LastMeetingEnded = Utils.TimeStamp;
243+
Stopwatch.Reset();
249244
}
250245

251246
[HarmonyPatch(typeof(PbExileController), nameof(PbExileController.PlayerSpin))]

Patches/IntroPatch.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ public static void Postfix()
10251025

10261026
foreach (var player in Main.EnumeratePlayerControls())
10271027
{
1028-
if (player.Is(CustomRoles.GM) && !AntiBlackout.IsCached)
1028+
if (player.Is(CustomRoles.GM))
10291029
{
10301030
player.RpcExile();
10311031
Main.PlayerStates[player.PlayerId].SetDead();

0 commit comments

Comments
 (0)