11using AmongUs . Data ;
22using AmongUs . GameOptions ;
3+ using Hazel ;
34using System ;
5+ using System . Diagnostics ;
46using TOHE . Roles . Core ;
57using TOHE . Roles . Neutral ;
68
79namespace TOHE ;
810
911class 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 ) ) ]
0 commit comments