mirror of
https://github.com/GoodStartLabs/AI_Diplomacy.git
synced 2026-04-27 17:23:21 +00:00
WIP: Mostly working version that uses the eventqueue
We've mostly got this working. Events get executed in the array of events. We don't use setTimeout anymore thankfully. I'm not in love with this system, it still isn't straight forward about what events happen where, but I do at least now have an ability to better control the flow.
This commit is contained in:
parent
a929bf5ee6
commit
ef3e3a79fe
11 changed files with 336 additions and 393 deletions
|
|
@ -49,26 +49,15 @@ export function _setPhase(phaseIndex: number) {
|
|||
// Clear any existing animations to prevent overlap
|
||||
// (playbackTimer is replaced by event queue system)
|
||||
|
||||
// Ensure any open two-power conversations are closed immediately before resetting event queue
|
||||
if (gameState.isDisplayingMoment) {
|
||||
closeTwoPowerConversation(true); // immediate = true
|
||||
}
|
||||
|
||||
// Reset event queue for new phase with cleanup callback
|
||||
gameState.eventQueue.reset(() => {
|
||||
// Ensure proper state cleanup when events are canceled
|
||||
gameState.messagesPlaying = false;
|
||||
gameState.isAnimating = false;
|
||||
});
|
||||
|
||||
|
||||
if (gameState.isPlaying) {
|
||||
gameState.eventQueue.start();
|
||||
}
|
||||
|
||||
// Reset animation state (redundant but kept for clarity)
|
||||
gameState.isAnimating = false;
|
||||
gameState.messagesPlaying = false;
|
||||
|
||||
// Advance the phase index
|
||||
gameState.phaseIndex++;
|
||||
if (config.isDebugMode && gameState.gameData) {
|
||||
|
|
@ -126,7 +115,6 @@ export function togglePlayback(explicitSet: boolean | undefined = undefined) {
|
|||
if (gameState.currentPhase.messages && gameState.currentPhase.messages.length) {
|
||||
// Show messages with stepwise animation
|
||||
logger.log(`Playing ${gameState.currentPhase.messages.length} messages from phase ${gameState.phaseIndex + 1}/${gameState.gameData.phases.length}`);
|
||||
gameState.nextPhaseScheduled = true
|
||||
displayPhase()
|
||||
} else {
|
||||
// No messages, go straight to unit animations
|
||||
|
|
@ -136,15 +124,13 @@ export function togglePlayback(explicitSet: boolean | undefined = undefined) {
|
|||
if (gameState.cameraPanAnim) gameState.cameraPanAnim.getAll()[0].pause();
|
||||
playBtn.textContent = "▶ Play";
|
||||
// (playbackTimer is replaced by event queue system)
|
||||
|
||||
|
||||
// Stop background audio when pausing
|
||||
stopBackgroundAudio();
|
||||
|
||||
|
||||
// Ensure any open two-power conversations are closed when pausing
|
||||
if (gameState.isDisplayingMoment) {
|
||||
closeTwoPowerConversation(true); // immediate = true
|
||||
}
|
||||
|
||||
closeTwoPowerConversation(true); // immediate = true
|
||||
|
||||
// Stop and reset event queue when pausing with cleanup
|
||||
gameState.eventQueue.stop();
|
||||
gameState.eventQueue.reset(() => {
|
||||
|
|
@ -152,7 +138,7 @@ export function togglePlayback(explicitSet: boolean | undefined = undefined) {
|
|||
gameState.messagesPlaying = false;
|
||||
gameState.isAnimating = false;
|
||||
});
|
||||
|
||||
|
||||
gameState.messagesPlaying = false;
|
||||
prevBtn.disabled = false;
|
||||
nextBtn.disabled = false;
|
||||
|
|
@ -160,32 +146,42 @@ export function togglePlayback(explicitSet: boolean | undefined = undefined) {
|
|||
}
|
||||
|
||||
|
||||
export function scheduleNextPhase() {
|
||||
gameState.eventQueue.scheduleDelay(0, nextPhase)
|
||||
}
|
||||
|
||||
export function scheduleSummarySpeech() {
|
||||
// Delay speech in streaming mode
|
||||
gameState.eventQueue.scheduleDelay(config.speechDelay, () => {
|
||||
// Speak the summary and advance after
|
||||
speakSummary()
|
||||
}, `speech-delay-${Date.now()}`);
|
||||
}
|
||||
|
||||
/** Handels all the end-of-phase items before calling _setPhase().
|
||||
*
|
||||
*/
|
||||
export function nextPhase() {
|
||||
if (!gameState.isDisplayingMoment && gameState.gameData && gameState.momentsData) {
|
||||
let moment = gameState.checkPhaseHasMoment(gameState.gameData.phases[gameState.phaseIndex].name)
|
||||
if (moment !== null && moment.interest_score >= MOMENT_THRESHOLD && moment.powers_involved.length >= 2) {
|
||||
moment.hasBeenDisplayed = true
|
||||
let moment = gameState.checkPhaseHasMoment(gameState.gameData.phases[gameState.phaseIndex].name)
|
||||
if (moment !== null && moment.interest_score >= MOMENT_THRESHOLD && moment.powers_involved.length >= 2) {
|
||||
|
||||
const power1 = moment.powers_involved[0];
|
||||
const power2 = moment.powers_involved[1];
|
||||
const power1 = moment.powers_involved[0];
|
||||
const power2 = moment.powers_involved[1];
|
||||
|
||||
showTwoPowerConversation({
|
||||
power1: power1,
|
||||
power2: power2,
|
||||
moment: moment
|
||||
})
|
||||
if (gameState.isPlaying) {
|
||||
// The conversation will close itself and then advance the phase
|
||||
// We don't need to schedule a timeout here anymore since the conversation manages its own timing
|
||||
console.log("Two-power conversation will handle its own timing and phase advancement");
|
||||
} else {
|
||||
_setPhase(gameState.phaseIndex + 1)
|
||||
showTwoPowerConversation({
|
||||
power1: power1,
|
||||
power2: power2,
|
||||
moment: moment,
|
||||
onClose: () => {
|
||||
// Schedule the speaking of the summary after the conversation closes
|
||||
scheduleSummarySpeech();
|
||||
if (gameState.isPlaying) _setPhase(gameState.phaseIndex + 1)
|
||||
}
|
||||
} else {
|
||||
_setPhase(gameState.phaseIndex + 1)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.log("not moving")
|
||||
// No conversation to show, proceed with normal flow
|
||||
scheduleSummarySpeech();
|
||||
_setPhase(gameState.phaseIndex + 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -220,8 +216,6 @@ export function displayPhase(skipMessages = false) {
|
|||
// Only get previous phase if not the first phase
|
||||
const prevIndex = isFirstPhase ? null : (index > 0 ? index - 1 : null);
|
||||
const previousPhase = prevIndex !== null ? gameState.gameData.phases[prevIndex] : null;
|
||||
updatePhaseDisplay()
|
||||
|
||||
|
||||
|
||||
// Update supply centers
|
||||
|
|
@ -271,7 +265,6 @@ export function displayPhase(skipMessages = false) {
|
|||
} else {
|
||||
logger.log("No animations for this phase transition");
|
||||
}
|
||||
gameState.nextPhaseScheduled = false;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -293,68 +286,6 @@ export function displayPhaseWithAnimation() {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Advances to the next phase in the game sequence
|
||||
* Handles speaking summaries and transitioning to the next phase
|
||||
*/
|
||||
export function advanceToNextPhase() {
|
||||
// If we're not "playing" through the game, just skipping phases, move everything along
|
||||
if (!gameState.isPlaying) {
|
||||
nextPhase()
|
||||
}
|
||||
|
||||
if (!gameState.gameData || !gameState.gameData.phases || gameState.phaseIndex < 0) {
|
||||
logger.log("Cannot advance phase: invalid game state");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current phase
|
||||
const currentPhase = gameState.gameData.phases[gameState.phaseIndex];
|
||||
|
||||
console.log(`Current phase: ${currentPhase.name}, Has summary: ${Boolean(currentPhase.summary)}`);
|
||||
if (currentPhase.summary) {
|
||||
console.log(`Summary preview: "${currentPhase.summary.substring(0, 50)}..."`);
|
||||
}
|
||||
|
||||
if (config.isDebugMode) {
|
||||
console.log(`Processing phase transition for ${currentPhase.name}`);
|
||||
}
|
||||
|
||||
const speechDelay = config.speechDelay
|
||||
|
||||
// First show summary if available
|
||||
if (currentPhase.summary && currentPhase.summary.trim() !== '') {
|
||||
// Delay speech in streaming mode
|
||||
gameState.eventQueue.scheduleDelay(speechDelay, () => {
|
||||
// Speak the summary and advance after
|
||||
if (!gameState.isSpeaking) {
|
||||
speakSummary(currentPhase.summary)
|
||||
.then(() => {
|
||||
console.log("Speech completed successfully");
|
||||
if (gameState.isPlaying) {
|
||||
nextPhase();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Speech failed with error:", error);
|
||||
if (gameState.isPlaying) {
|
||||
nextPhase();
|
||||
}
|
||||
}).finally(() => {
|
||||
// Any cleanup code here
|
||||
});
|
||||
} else {
|
||||
console.error("Attempted to start speaking when already speaking...");
|
||||
}
|
||||
}, `speech-delay-${Date.now()}`);
|
||||
} else {
|
||||
console.log("No summary available, skipping speech");
|
||||
// No summary to speak, advance immediately
|
||||
nextPhase();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function displayFinalPhase() {
|
||||
if (!gameState.gameData || !gameState.gameData.phases || gameState.gameData.phases.length === 0) {
|
||||
return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue