BLADERUNNER: Support wait for dialogue queues to finish
Fixes a Crazylegs bug where he can interrupt himself Could probably be used elsewhere if there are any other such cases.
This commit is contained in:
parent
e4b78f4f62
commit
f04705084c
9 changed files with 49 additions and 3 deletions
|
@ -53,7 +53,7 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
|
||||||
|
|
||||||
_walkInfo = new ActorWalk(vm);
|
_walkInfo = new ActorWalk(vm);
|
||||||
_movementTrack = new MovementTrack();
|
_movementTrack = new MovementTrack();
|
||||||
_cluesLimit = (actorId == 0 || actorId == 99) ? 4 : 2;
|
_cluesLimit = (actorId == kActorMcCoy || actorId == kActorVoiceOver) ? 4 : 2;
|
||||||
_clues = new ActorClues(vm, _cluesLimit);
|
_clues = new ActorClues(vm, _cluesLimit);
|
||||||
_combatInfo = new ActorCombat(vm);
|
_combatInfo = new ActorCombat(vm);
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ ActorDialogueQueue::~ActorDialogueQueue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) {
|
void ActorDialogueQueue::add(int actorId, int sentenceId, int animationMode) {
|
||||||
if (actorId == 0 || actorId == BladeRunnerEngine::kActorVoiceOver) {
|
if (actorId == kActorMcCoy || actorId == kActorVoiceOver) {
|
||||||
animationMode = -1;
|
animationMode = -1;
|
||||||
}
|
}
|
||||||
if (_entries.size() < kMaxEntries) {
|
if (_entries.size() < kMaxEntries) {
|
||||||
|
@ -105,6 +105,21 @@ void ActorDialogueQueue::flush(int a1, bool callScript) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true when queue is empty and object is flushed
|
||||||
|
*/
|
||||||
|
bool ActorDialogueQueue::isEmpty() {
|
||||||
|
return _entries.empty() \
|
||||||
|
&& !_isNotPause \
|
||||||
|
&& !_isPause \
|
||||||
|
&& _actorId == -1 \
|
||||||
|
&& _sentenceId == -1 \
|
||||||
|
&& _animationMode == -1 \
|
||||||
|
&& _animationModePrevious == -1 \
|
||||||
|
&& _delay == 0 \
|
||||||
|
&& _timeLast == 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ActorDialogueQueue::tick() {
|
void ActorDialogueQueue::tick() {
|
||||||
if (!_vm->_audioSpeech->isPlaying()) {
|
if (!_vm->_audioSpeech->isPlaying()) {
|
||||||
if (_isPause) {
|
if (_isPause) {
|
||||||
|
|
|
@ -64,6 +64,7 @@ public:
|
||||||
void add(int actorId, int sentenceId, int animationMode);
|
void add(int actorId, int sentenceId, int animationMode);
|
||||||
void addPause(int delay);
|
void addPause(int delay);
|
||||||
void flush(int a1, bool callScript);
|
void flush(int a1, bool callScript);
|
||||||
|
bool isEmpty();
|
||||||
void tick();
|
void tick();
|
||||||
|
|
||||||
void save(SaveFileWriteStream &f);
|
void save(SaveFileWriteStream &f);
|
||||||
|
|
|
@ -174,7 +174,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool mustReachWalkDestinat
|
||||||
int r = nextOnPath(actorId, _current, _destination, next);
|
int r = nextOnPath(actorId, _current, _destination, next);
|
||||||
obstaclesRestore();
|
obstaclesRestore();
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
stop(actorId, actorId == 0, kAnimationModeCombatIdle, kAnimationModeIdle);
|
stop(actorId, actorId == kActorMcCoy, kAnimationModeCombatIdle, kAnimationModeIdle);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (r != -1) {
|
if (r != -1) {
|
||||||
|
|
|
@ -1693,6 +1693,22 @@ void BladeRunnerEngine::loopActorSpeaking() {
|
||||||
playerGainsControl();
|
playerGainsControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be used only for when there is a chance an ongoing dialogue in a dialogue queue
|
||||||
|
* might be interrupted AND that is unwanted behavior (sometimes, it's intended that the dialogue
|
||||||
|
* can be interrupted without necessarily being finished).
|
||||||
|
*/
|
||||||
|
void BladeRunnerEngine::loopQueuedDialogueStillPlaying() {
|
||||||
|
if (_actorDialogueQueue->isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
gameTick();
|
||||||
|
} while (_gameIsRunning && !_actorDialogueQueue->isEmpty());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
|
void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
|
||||||
Common::String name = _gameInfo->getOuttake(id);
|
Common::String name = _gameInfo->getOuttake(id);
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,7 @@ public:
|
||||||
|
|
||||||
void gameWaitForActive();
|
void gameWaitForActive();
|
||||||
void loopActorSpeaking();
|
void loopActorSpeaking();
|
||||||
|
void loopQueuedDialogueStillPlaying();
|
||||||
|
|
||||||
void outtakePlay(int id, bool no_localization, int container = -1);
|
void outtakePlay(int id, bool no_localization, int container = -1);
|
||||||
|
|
||||||
|
|
|
@ -690,6 +690,13 @@ void SceneScriptHF05::talkWithCrazyLegs1() {
|
||||||
Ambient_Sounds_Play_Sound(149, 99, 99, 0, 0);
|
Ambient_Sounds_Play_Sound(149, 99, 99, 0, 0);
|
||||||
Actor_Face_Actor(kActorCrazylegs, kActorMcCoy, true);
|
Actor_Face_Actor(kActorCrazylegs, kActorMcCoy, true);
|
||||||
Actor_Face_Actor(kActorMcCoy, kActorCrazylegs, true);
|
Actor_Face_Actor(kActorMcCoy, kActorCrazylegs, true);
|
||||||
|
#if BLADERUNNER_ORIGINAL_BUGS
|
||||||
|
#else
|
||||||
|
// There is a chance here that Crazylegs will "interrupt himself"
|
||||||
|
// and thus sometimes skip the last sentence of the above queued dialogue in chapter 3.
|
||||||
|
// So we explicitly wait for the queue to be emptied before proceeding to his next line
|
||||||
|
ADQ_Wait_For_All_Queued_Dialogue();
|
||||||
|
#endif // BLADERUNNER_ORIGINAL_BUGS
|
||||||
Actor_Says(kActorCrazylegs, 170, kAnimationModeTalk);
|
Actor_Says(kActorCrazylegs, 170, kAnimationModeTalk);
|
||||||
Actor_Says(kActorCrazylegs, 180, 12);
|
Actor_Says(kActorCrazylegs, 180, 12);
|
||||||
Actor_Says(kActorCrazylegs, 190, 14);
|
Actor_Says(kActorCrazylegs, 190, 14);
|
||||||
|
|
|
@ -1551,6 +1551,11 @@ void ScriptBase::ADQ_Add_Pause(int delay) {
|
||||||
_vm->_actorDialogueQueue->addPause(delay);
|
_vm->_actorDialogueQueue->addPause(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptBase::ADQ_Wait_For_All_Queued_Dialogue() {
|
||||||
|
debugC(kDebugScript, "ADQ_Wait_For_All_Queued_Dialogue()");
|
||||||
|
_vm->loopQueuedDialogueStillPlaying();
|
||||||
|
}
|
||||||
|
|
||||||
bool ScriptBase::Game_Over() {
|
bool ScriptBase::Game_Over() {
|
||||||
debugC(kDebugScript, "Game_Over()");
|
debugC(kDebugScript, "Game_Over()");
|
||||||
_vm->_gameIsRunning = false;
|
_vm->_gameIsRunning = false;
|
||||||
|
|
|
@ -259,6 +259,7 @@ protected:
|
||||||
void ADQ_Flush();
|
void ADQ_Flush();
|
||||||
void ADQ_Add(int actorId, int sentenceId, int animationMode);
|
void ADQ_Add(int actorId, int sentenceId, int animationMode);
|
||||||
void ADQ_Add_Pause(int delay);
|
void ADQ_Add_Pause(int delay);
|
||||||
|
void ADQ_Wait_For_All_Queued_Dialogue();
|
||||||
bool Game_Over();
|
bool Game_Over();
|
||||||
void Autosave_Game(int textId);
|
void Autosave_Game(int textId);
|
||||||
void I_Sez(const char *str);
|
void I_Sez(const char *str);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue