11using AmongUs . Data ;
22using AmongUs . GameOptions ;
3- using Hazel ;
43using System ;
5- using System . Diagnostics ;
64using TOHE . Roles . Core ;
75using TOHE . Roles . Neutral ;
86
97namespace TOHE ;
108
119class ExileControllerWrapUpPatch
1210{
13- public static Stopwatch Stopwatch ;
1411 public static NetworkedPlayerInfo AntiBlackout_LastExiled ;
1512 [ HarmonyPatch ( typeof ( ExileController ) , nameof ( ExileController . Begin ) ) ]
1613 class ExileControllerBeginPatch
@@ -92,6 +89,8 @@ private static void CheckAndDoRandomSpawn()
9289 }
9390 private static void WrapUpPostfix ( NetworkedPlayerInfo exiled )
9491 {
92+ if ( AntiBlackout . BlackOutIsActive ) exiled = AntiBlackout_LastExiled ;
93+
9594 // Still not springing up in Airship
9695 if ( ! GameStates . AirshipIsActive )
9796 {
@@ -103,6 +102,7 @@ private static void WrapUpPostfix(NetworkedPlayerInfo exiled)
103102
104103 bool DecidedWinner = false ;
105104 if ( ! AmongUsClient . Instance . AmHost ) return ;
105+ AntiBlackout . RestoreIsDead ( doSend : false ) ;
106106
107107 List < Collector > collectorCL = Utils . GetRoleBasesByType < Collector > ( ) ? . ToList ( ) ;
108108
@@ -152,95 +152,100 @@ 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- Stopwatch = Stopwatch . StartNew ( ) ;
156-
157- LateTask . New ( ( ) =>
155+ _ = new LateTask ( ( ) =>
158156 {
159157 if ( GameStates . IsEnded ) return ;
160- AntiBlackout . RevertToActualRoleTypes ( ) ;
161- } , 2f , "Revert AntiBlackout Measures" ) ;
162- }
163158
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
159+ exiled = AntiBlackout_LastExiled ;
160+ AntiBlackout . SendGameData ( ) ;
161+ AntiBlackout . SetRealPlayerRoles ( ) ;
167162
168- GameStates . AlreadyDied |= ! Utils . IsAllAlive ;
169- RemoveDisableDevicesPatch . UpdateDisableDevices ( ) ;
170- SoundManager . Instance . ChangeAmbienceVolume ( DataManager . Settings . Audio . AmbienceVolume ) ;
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" ) ;
171170
172- _ = new LateTask ( ( ) =>
173- {
174- if ( ! AmongUsClient . Instance . IsGameOver )
175- DestroyableSingleton < HudManager > . Instance . SetHudActive ( true ) ;
176- } , 0.8f , "Set Hud Active" ) ;
171+ _ = new LateTask ( AntiBlackout . ResetAfterMeeting , 0.6f , "ResetAfterMeeting" ) ;
177172
173+ _ = new LateTask ( ( ) =>
174+ {
175+ if ( GameStates . IsEnded ) return ;
178176
177+ Main . AfterMeetingDeathPlayers . Do ( x =>
178+ {
179+ var player = x . Key . GetPlayer ( ) ;
180+ var state = Main . PlayerStates [ x . Key ] ;
179181
180- Logger . Info ( "Start of Task Phase" , "Phase" ) ;
181- }
182+ Logger . Info ( $ "{ player ? . GetNameWithRole ( ) . RemoveHtmlTags ( ) } died with { x . Value } ", "AfterMeetingDeath" ) ;
182183
183- public static void AfterMeetingTasks ( )
184- {
185- if ( CustomWinnerHolder . WinnerTeam != CustomWinner . Default || GameStates . IsEnded ) {
186- Stopwatch . Reset ( ) ;
187- return ;
188- }
184+ if ( x . Value == PlayerState . DeathReason . Suicide )
185+ player ? . SetRealKiller ( player , true ) ;
189186
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 ) ;
187+ state . deathReason = x . Value ;
188+ state . SetDead ( ) ;
189+ player ? . RpcExileV2 ( ) ;
194190
195- foreach ( ( byte id , PlayerState . DeathReason deathReason ) in Main . AfterMeetingDeathPlayers )
196- {
197- var player = id . GetPlayer ( ) ;
198- var state = Main . PlayerStates [ id ] ;
191+ // Just to be sure
192+ _ = new LateTask ( ( ) => player ? . RpcExile ( ) , 0.5f , "Extra Exile to be Sure" ) ;
199193
200- Logger . Info ( $ "{ player ? . GetNameWithRole ( ) . RemoveHtmlTags ( ) } died with { deathReason } ", "AfterMeetingDeath" ) ;
194+ MurderPlayerPatch . AfterPlayerDeathTasks ( player , player , true ) ;
195+ } ) ;
201196
202- if ( deathReason == PlayerState . DeathReason . Suicide )
203- player ? . SetRealKiller ( player , true ) ;
197+ Main . AfterMeetingDeathPlayers . Clear ( ) ;
204198
205- state . deathReason = deathReason ;
206- state . SetDead ( ) ;
199+ Utils . AfterMeetingTasks ( ) ;
200+ Utils . SyncAllSettings ( ) ;
201+ Utils . CheckAndSetVentInteractions ( ) ;
207202
208- if ( ! player ) continue ;
203+ if ( Main . CurrentServerIsVanilla && Options . BypassRateLimitAC . GetBool ( ) )
204+ {
205+ Main . Instance . StartCoroutine ( Utils . NotifyEveryoneAsync ( speed : 5 ) ) ;
206+ }
207+ else
208+ {
209+ Utils . NotifyRoles ( ) ;
210+ }
209211
210- if ( deathReason == PlayerState . DeathReason . Suicide )
211- player . SetRealKiller ( player , true ) ;
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") ;
212229
213- MurderPlayerPatch . AfterPlayerDeathTasks ( player , player , true ) ;
230+ Main . LastMeetingEnded = Utils . TimeStamp ;
231+ } , 1f , "AfterMeetingDeathPlayers Task" ) ;
214232 }
215233
216- Main . AfterMeetingDeathPlayers . Clear ( ) ;
217-
218- Utils . AfterMeetingTasks ( ) ;
219- Utils . SyncAllSettings ( ) ;
220- Utils . CheckAndSetVentInteractions ( ) ;
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
221237
222- Main . Instance . StartCoroutine ( Utils . NotifyEveryoneAsync ( ) ) ;
238+ GameStates . AlreadyDied |= ! Utils . IsAllAlive ;
239+ RemoveDisableDevicesPatch . UpdateDisableDevices ( ) ;
240+ SoundManager . Instance . ChangeAmbienceVolume ( DataManager . Settings . Audio . AmbienceVolume ) ;
223241
224242 _ = new LateTask ( ( ) =>
225243 {
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") ;
244+ if ( ! AmongUsClient . Instance . IsGameOver )
245+ DestroyableSingleton < HudManager > . Instance . SetHudActive ( true ) ;
246+ } , 0.8f , "Set Hud Active" ) ;
241247
242- Main . LastMeetingEnded = Utils . TimeStamp ;
243- Stopwatch . Reset ( ) ;
248+ Logger . Info ( "Start of Task Phase" , "Phase" ) ;
244249 }
245250
246251 [ HarmonyPatch ( typeof ( PbExileController ) , nameof ( PbExileController . PlayerSpin ) ) ]
0 commit comments