diff options
-rw-r--r-- | scumm/intern.h | 3 | ||||
-rw-r--r-- | scumm/script_v2.cpp | 86 |
2 files changed, 88 insertions, 1 deletions
diff --git a/scumm/intern.h b/scumm/intern.h index be7382d01e..1133e84b74 100644 --- a/scumm/intern.h +++ b/scumm/intern.h @@ -217,6 +217,9 @@ protected: void resetSentence(); void setUserState(byte state); + void runObjectScript(int object, int entry, bool freezeResistant, bool recursive, int *vars); + void stopObjectScript(int script, bool recursive); + /* Version 2 script opcodes */ void o2_actorFromPos(); void o2_actorSet(); diff --git a/scumm/script_v2.cpp b/scumm/script_v2.cpp index 92c309c247..32ff3b64b6 100644 --- a/scumm/script_v2.cpp +++ b/scumm/script_v2.cpp @@ -906,7 +906,7 @@ void Scumm_v2::o2_doSentence() { _sentenceNum--; if (st->verb == 254) { - stopObjectScript(st->objectA); + stopObjectScript(st->objectA, true); } else if (st->verb != 253 && st->verb != 250) { VAR(VAR_ACTIVE_VERB) = st->verb; VAR(VAR_ACTIVE_OBJECT1) = st->objectA; @@ -1477,3 +1477,87 @@ void Scumm_v2::resetSentence() { VAR(VAR_SENTENCE_OBJECT2) = 0; VAR(VAR_SENTENCE_PREPOSITION) = 0; } + +enum { + ssDead = 0, + ssPaused = 1, + ssRunning = 2 +}; + +void Scumm_v2::runObjectScript(int object, int entry, bool freezeResistant, bool recursive, int *vars) { + ScriptSlot *s; + uint32 obcd; + int slot, where, offs; + + if (!object) + return; + + stopObjectScript(object, recursive); + + where = whereIsObject(object); + + if (where == WIO_NOT_FOUND) { + warning("Code for object %d not in room %d", object, _roomResource); + return; + } + + obcd = getOBCDOffs(object); + slot = getScriptSlot(); + + offs = getVerbEntrypoint(object, entry); + if (offs == 0) + return; + + s = &vm.slot[slot]; + s->number = object; + s->offs = obcd + offs; + s->status = ssRunning; + s->where = where; + s->freezeResistant = freezeResistant; + s->recursive = recursive; + s->freezeCount = 0; + s->delayFrameCount = 0; + + initializeLocals(slot, vars); + + runScriptNested(slot); +} + +/* Stop an object script 'script'*/ +void Scumm_v2::stopObjectScript(int script, bool recursive) { + ScriptSlot *ss; + NestedScript *nest; + int i, num; + + if (script == 0) + return; + + nest = vm.nest; + num = _numNestedScripts; + + while (num > 0) { + if (nest->number == script && + vm.slot[nest->slot].recursive == recursive && + (nest->where == WIO_ROOM || nest->where == WIO_INVENTORY || nest->where == WIO_FLOBJECT)) { + nest->number = 0xFF; + nest->slot = 0xFF; + nest->where = 0xFF; + } + nest++; + num--; + } + + ss = vm.slot; + for (i = 0; i < NUM_SCRIPT_SLOT; i++, ss++) { + if (script == ss->number && ss->status != ssDead && + ss->recursive == recursive && + (ss->where == WIO_ROOM || ss->where == WIO_INVENTORY || ss->where == WIO_FLOBJECT)) { + if (ss->cutsceneOverride) + error("Object %d stopped with active cutscene/override", script); + ss->number = 0; + ss->status = ssDead; + if (_currentScript == i) + _currentScript = 0xFF; + } + } +} |