From a5d76aa9b024746e43a6d94cd4420e4a52ac4363 Mon Sep 17 00:00:00 2001 From: ApfelTeeSaft <91074565+ApfelTeeSaft@users.noreply.github.com> Date: Wed, 22 Apr 2026 09:05:42 +0200 Subject: [PATCH] Continue on Sequencer End --- Aeon-740/Aeon-740.vcxproj | 2 ++ Aeon-740/Aeon-740.vcxproj.filters | 6 ++++ Aeon-740/EventHandler.h | 59 +++++++++++++++++++++++++------ 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/Aeon-740/Aeon-740.vcxproj b/Aeon-740/Aeon-740.vcxproj index fa81d522..00c02371 100644 --- a/Aeon-740/Aeon-740.vcxproj +++ b/Aeon-740/Aeon-740.vcxproj @@ -176,6 +176,8 @@ + + diff --git a/Aeon-740/Aeon-740.vcxproj.filters b/Aeon-740/Aeon-740.vcxproj.filters index 2292796b..2d8331b3 100644 --- a/Aeon-740/Aeon-740.vcxproj.filters +++ b/Aeon-740/Aeon-740.vcxproj.filters @@ -32,6 +32,12 @@ MinHook + + SDK + + + SDK + diff --git a/Aeon-740/EventHandler.h b/Aeon-740/EventHandler.h index 78ef48f8..8476df16 100644 --- a/Aeon-740/EventHandler.h +++ b/Aeon-740/EventHandler.h @@ -47,7 +47,7 @@ namespace EventHandler static const string SoundPath_Finale = "/Game/Apfel/Audio/SC_EventFinale.SC_EventFinale"; // World-space event staging location - static FVector EventStagingLocation = { 0.0f, 0.0f, 5000.0f }; + static FVector EventStagingLocation = { 349.57f, 509.0f, 68.0f }; static FRotator EventStagingRotation = { 0.0f, 0.0f, 0.0f }; @@ -213,6 +213,42 @@ namespace EventHandler return OutActor; } + // Block the calling thread until the sequence finishes playing naturally. + // + // Uses UMovieSceneSequencePlayer::IsPlaying() (SDK) rather than a hardcoded + // Sleep duration, so the phase length is always exactly as long as the + // sequence asset itself – no need to keep code and content in sync. + // + // The 200 ms initial sleep gives the engine's game thread one or two ticks + // to process the Play() call before start polling; without it IsPlaying() + // can return false in the very first check before playback has actually begun. + // + static void WaitForSequence(ALevelSequenceActor* SeqActor, + float FallbackTimeoutSeconds = 300.0f) + { + if (!SeqActor || !SeqActor->SequencePlayer) + { + LogInfo("EventHandler: WaitForSequence – no valid player, skipping wait."); + return; + } + + ULevelSequencePlayer* Player = SeqActor->SequencePlayer; + float AbsTimeout = GetWorldTime() + FallbackTimeoutSeconds; + + Sleep(200); + + while (GetWorldTime() < AbsTimeout) + { + if (!Player->IsPlaying()) + break; + + Sleep(50); // poll at ~20 Hz – responsive without busy-waiting + } + + LogInfo("EventHandler: Sequence ended at {:.2f}s / {:.2f}s", + Player->GetPlaybackPosition(), Player->GetPlaybackEnd()); + } + static void StopSequence(ALevelSequenceActor*& OutActor) { if (!OutActor) return; @@ -235,13 +271,13 @@ namespace EventHandler // Phase: Countdown // BeginCountdown() writes WarmupCountdownEndTime onto the GameState. - // That field is Net-replicated; clients poll it each tick to drive the + // That field is Net-replicated; clients read it each tick for the HUD. // HUD timer without any extra server messaging. // WaitUntil() blocks this thread until the timestamp is reached. CurrentPhase = ECustomEventPhase::Countdown; LogInfo("EventHandler: [Countdown] Starting 30 s timestamp countdown..."); float EventStartTimestamp = BeginCountdown(30.0f); - WaitUntil(EventStartTimestamp); // server advances exactly when timer hits 0 + WaitUntil(EventStartTimestamp); EndCountdown(); // Phase: Event Start @@ -253,31 +289,34 @@ namespace EventHandler Sleep(2000); // brief settle time after teleport RPC propagates SetAllPlayersLocked(true); - // Phase 1 – Opening cinematic (15 s) + // Phase 1 – Opening cinematic + // Duration = length of LS_CustomEvent_Phase1 (no hardcoded value needed) CurrentPhase = ECustomEventPhase::Phase1; LogInfo("EventHandler: [Phase1] Opening cinematic."); ALevelSequenceActor* SeqActor = PlaySequence(SequencePath_Phase1); BroadcastSound(SoundPath_Intro); - Sleep(15000); + WaitForSequence(SeqActor); // returns when IsPlaying() == false StopSequence(SeqActor); - // Phase 2 – Main event sequence (30 s) + // Phase 2 – Main event sequence + // Duration = length of LS_CustomEvent_Phase2 CurrentPhase = ECustomEventPhase::Phase2; LogInfo("EventHandler: [Phase2] Main event sequence."); SeqActor = PlaySequence(SequencePath_Phase2); BroadcastSound(SoundPath_Main); - Sleep(30000); + WaitForSequence(SeqActor); StopSequence(SeqActor); - // Phase 3 – Finale (20 s) + // Phase 3 – Finale + // Duration = length of LS_CustomEvent_Phase3 CurrentPhase = ECustomEventPhase::Phase3; LogInfo("EventHandler: [Phase3] Finale."); SeqActor = PlaySequence(SequencePath_Phase3); BroadcastSound(SoundPath_Finale); - Sleep(20000); + WaitForSequence(SeqActor); StopSequence(SeqActor); // Phase: Event End – restore players, clear countdown state @@ -309,4 +348,4 @@ namespace EventHandler LogInfo("EventHandler: Scheduling live event timeline..."); CreateThread(nullptr, 0, EventTimeline, nullptr, 0, nullptr); } -} +} \ No newline at end of file