diff options
Diffstat (limited to 'engines/scumm/script_v0.cpp')
-rw-r--r-- | engines/scumm/script_v0.cpp | 540 |
1 files changed, 257 insertions, 283 deletions
diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp index e2d3f40e8e..45901186cd 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -27,6 +27,7 @@ #include "scumm/resource.h" #include "scumm/scumm_v0.h" #include "scumm/verbs.h" +#include "scumm/util.h" namespace Scumm { @@ -50,7 +51,7 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0x0b, o_setActorBitVar); /* 0C */ OPCODE(0x0c, o_loadSound); - OPCODE(0x0d, o_printEgo_c64); + OPCODE(0x0d, o_printEgo); OPCODE(0x0e, o_putActorAtObject); OPCODE(0x0f, o2_clearState02); /* 10 */ @@ -59,7 +60,7 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0x12, o2_panCameraTo); OPCODE(0x13, o_lockCostume); /* 14 */ - OPCODE(0x14, o_print_c64); + OPCODE(0x14, o_print); OPCODE(0x15, o5_walkActorToActor); OPCODE(0x16, o5_getRandomNr); OPCODE(0x17, o2_clearState08); @@ -79,9 +80,9 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0x22, o4_saveLoadGame); OPCODE(0x23, o_stopCurrentScript); /* 24 */ - OPCODE(0x24, o_unknown2); + OPCODE(0x24, o_ifNotEqualActiveObject2); OPCODE(0x25, o5_loadRoom); - OPCODE(0x26, o_getClosestObjActor); + OPCODE(0x26, o_getClosestActor); OPCODE(0x27, o2_getActorY); /* 28 */ OPCODE(0x28, o5_equalZero); @@ -91,7 +92,7 @@ void ScummEngine_v0::setupOpcodes() { /* 2C */ OPCODE(0x2c, o_stopCurrentScript); OPCODE(0x2d, o2_putActorInRoom); - OPCODE(0x2e, o_print_c64); + OPCODE(0x2e, o_print); OPCODE(0x2f, o2_ifState08); /* 30 */ OPCODE(0x30, o_loadCostume); @@ -101,7 +102,7 @@ void ScummEngine_v0::setupOpcodes() { /* 34 */ OPCODE(0x34, o5_getDist); OPCODE(0x35, o_stopCurrentScript); - OPCODE(0x36, o2_walkActorToObject); + OPCODE(0x36, o_walkActorToObject); OPCODE(0x37, o2_clearState04); /* 38 */ OPCODE(0x38, o2_isLessEqual); @@ -144,7 +145,7 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0x56, o_getActorMoving); OPCODE(0x57, o2_clearState08); /* 58 */ - OPCODE(0x58, o_beginOverride); + OPCODE(0x58, o2_beginOverride); OPCODE(0x59, o_stopCurrentScript); OPCODE(0x5a, o2_add); OPCODE(0x5b, o_getActorBitVar); @@ -154,14 +155,14 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0x5e, o2_walkActorTo); OPCODE(0x5f, o2_ifState04); /* 60 */ - OPCODE(0x60, o_cursorCommand); + OPCODE(0x60, o_setMode); OPCODE(0x61, o2_putActor); OPCODE(0x62, o2_stopScript); OPCODE(0x63, o_stopCurrentScript); /* 64 */ - OPCODE(0x64, o_ifActiveObject); + OPCODE(0x64, o_ifEqualActiveObject2); OPCODE(0x65, o_stopCurrentScript); - OPCODE(0x66, o_getClosestObjActor); + OPCODE(0x66, o_getClosestActor); OPCODE(0x67, o5_getActorFacing); /* 68 */ OPCODE(0x68, o5_isScriptRunning); @@ -177,11 +178,11 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0x70, o_lights); OPCODE(0x71, o_getBitVar); OPCODE(0x72, o_nop); - OPCODE(0x73, o5_getObjectOwner); + OPCODE(0x73, o_getObjectOwner); /* 74 */ OPCODE(0x74, o5_getDist); - OPCODE(0x75, o_printEgo_c64); - OPCODE(0x76, o2_walkActorToObject); + OPCODE(0x75, o_printEgo); + OPCODE(0x76, o_walkActorToObject); OPCODE(0x77, o2_clearState04); /* 78 */ OPCODE(0x78, o2_isGreater); @@ -239,7 +240,7 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0xa2, o4_saveLoadGame); OPCODE(0xa3, o_stopCurrentScript); /* A4 */ - OPCODE(0xa4, o_unknown2); + OPCODE(0xa4, o_ifNotEqualActiveObject2); OPCODE(0xa5, o5_loadRoom); OPCODE(0xa6, o_stopCurrentScript); OPCODE(0xa7, o2_getActorY); @@ -251,7 +252,7 @@ void ScummEngine_v0::setupOpcodes() { /* AC */ OPCODE(0xac, o_stopCurrentScript); OPCODE(0xad, o2_putActorInRoom); - OPCODE(0xae, o_print_c64); + OPCODE(0xae, o_print); OPCODE(0xaf, o2_ifNotState08); /* B0 */ OPCODE(0xb0, o_loadCostume); @@ -261,7 +262,7 @@ void ScummEngine_v0::setupOpcodes() { /* B4 */ OPCODE(0xb4, o5_getDist); OPCODE(0xb5, o_stopCurrentScript); - OPCODE(0xb6, o2_walkActorToObject); + OPCODE(0xb6, o_walkActorToObject); OPCODE(0xb7, o2_setState04); /* B8 */ OPCODE(0xb8, o2_isLessEqual); @@ -314,12 +315,12 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0xde, o2_walkActorTo); OPCODE(0xdf, o2_ifNotState04); /* E0 */ - OPCODE(0xe0, o_cursorCommand); + OPCODE(0xe0, o_setMode); OPCODE(0xe1, o2_putActor); OPCODE(0xe2, o2_stopScript); OPCODE(0xe3, o_stopCurrentScript); /* E4 */ - OPCODE(0xe4, o_ifActiveObject); + OPCODE(0xe4, o_ifEqualActiveObject2); OPCODE(0xe5, o_loadRoomWithEgo); OPCODE(0xe6, o_stopCurrentScript); OPCODE(0xe7, o5_getActorFacing); @@ -337,11 +338,11 @@ void ScummEngine_v0::setupOpcodes() { OPCODE(0xf0, o_lights); OPCODE(0xf1, o_getBitVar); OPCODE(0xf2, o_nop); - OPCODE(0xf3, o5_getObjectOwner); + OPCODE(0xf3, o_getObjectOwner); /* F4 */ OPCODE(0xf4, o5_getDist); OPCODE(0xf5, o_stopCurrentScript); - OPCODE(0xf6, o2_walkActorToObject); + OPCODE(0xf6, o_walkActorToObject); OPCODE(0xf7, o2_setState04); /* F8 */ OPCODE(0xf8, o2_isGreater); @@ -365,7 +366,7 @@ uint ScummEngine_v0::fetchScriptWord() { int ScummEngine_v0::getActiveObject() { if (_opcode & PARAM_2) - return _activeObject; + return OBJECT_V0_ID(_cmdObject); return fetchScriptByte(); } @@ -406,172 +407,121 @@ void ScummEngine_v0::decodeParseString() { actorTalk(buffer); } -void ScummEngine_v0::drawSentenceWord(int object, bool usePrep, bool objInInventory) { - const byte *temp; - int sentencePrep = 0; - - // If object not in inventory, we except an index - if (!objInInventory) - _v0ObjectIndex = true; - else - _v0ObjectInInventory = true; - - temp = getObjOrActorName(object); +void ScummEngine_v0::clearSentenceLine() { + Common::Rect sentenceline; + sentenceline.top = _virtscr[kVerbVirtScreen].topline; + sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8; + sentenceline.left = 0; + sentenceline.right = _virtscr[kVerbVirtScreen].w - 1; + restoreBackground(sentenceline); +} - _v0ObjectInInventory = false; - _v0ObjectIndex = false; +void ScummEngine_v0::flushSentenceLine() { + byte string[80]; + const char *ptr = _sentenceBuf.c_str(); + int i = 0, len = 0; - // Append the 'object-name' - if (temp) { - _sentenceBuf += " "; - _sentenceBuf += (const char *)temp; - } + // Maximum length of printable characters + int maxChars = 40; + while (*ptr) { + if (*ptr != '@') + len++; + if (len > maxChars) { + break; + } - // Append the modifier? (With / On / To / In) - if (!usePrep) - return; + string[i++] = *ptr++; - if (_verbs[_activeVerb].prep == 0xFF) { - _v0ObjectInInventory = objInInventory; - sentencePrep = verbPrep(object); - } else { - sentencePrep = _verbs[_activeVerb].prep; } + string[i] = 0; - if (sentencePrep > 0 && sentencePrep <= 4) { - // The prepositions, like the fonts, were hard code in the engine. Thus - // we have to do that, too, and provde localized versions for all the - // languages MM/Zak are available in. - static const char *const prepositions[][5] = { - { " ", " in", " with", " on", " to" }, // English - { " ", " mit", " mit", " mit", " zu" }, // German - { " ", " dans", " avec", " sur", " <" }, // French - { " ", " in", " con", " su", " a" }, // Italian - { " ", " en", " con", " en", " a" }, // Spanish - }; - int lang; - switch (_language) { - case Common::DE_DEU: - lang = 1; - break; - case Common::FR_FRA: - lang = 2; - break; - case Common::IT_ITA: - lang = 3; - break; - case Common::ES_ESP: - lang = 4; - break; - default: - lang = 0; // Default to english - } + _string[2].charset = 1; + _string[2].ypos = _virtscr[kVerbVirtScreen].topline; + _string[2].xpos = 0; + _string[2].right = _virtscr[kVerbVirtScreen].w - 1; + _string[2].color = 16; + drawString(2, (byte *)string); +} - _sentenceBuf += prepositions[lang][sentencePrep]; +void ScummEngine_v0::drawSentenceObject(int object) { + const byte *temp; + temp = getObjOrActorName(object); + if (temp) { + _sentenceBuf += " "; + _sentenceBuf += (const char *)temp; } } -void ScummEngine_v0::drawSentence() { - Common::Rect sentenceline; - bool inventoryFirst = false; - if (!(_userState & 32)) - return; +void ScummEngine_v0::drawSentenceLine() { + _redrawSentenceLine = false; - // Current Verb, Walk/Use - if (getResourceAddress(rtVerb, _activeVerb)) { - _sentenceBuf = (char *)getResourceAddress(rtVerb, _activeVerb); - } else { + if (!(_userState & USERSTATE_IFACE_SENTENCE)) return; - } - - // If using inventory first, draw it first - if (_activeInvExecute && _activeInventory) { - drawSentenceWord(_activeInventory, true, true); - } else { - // Not using inventory, use selected object - if (_activeObject) - drawSentenceWord(_activeObjectIndex, true, false); - else - inventoryFirst = true; - } - - // Draw the inventory? - if (_activeInventory > 0 && _activeObject2 == 0) { - // Only if inventory isnt first (it will already be drawn by now) - if (!_activeInvExecute) { - drawSentenceWord(_activeInventory, inventoryFirst, true); - } else { - // Draw the active object, which could be inventory based, or room based - if (_activeObject && !_activeObjectIndex) { - drawSentenceWord(_activeObject, inventoryFirst, true); - } else // Room based - drawSentenceWord(_activeObjectIndex, inventoryFirst, false); - } - - // Draw the 2nd active object - } else if (_activeObject2) { - - // 2nd Object is in inventory - if (_activeObject2Inv) { - _v0ObjectInInventory = true; - drawSentenceWord(_activeObject2, inventoryFirst, true); - } else { - drawSentenceWord(_activeObject2Index, inventoryFirst, false); + clearSentenceLine(); + + if (_activeVerb == kVerbNewKid) { + _sentenceBuf = ""; + for (int i = 0; i < 3; ++i) { + const char *actorName; + int actorId = VAR(97 + i); + if (actorId == 0) { + // after usage of the radiation suit, kid vars are set to 0 + actorName = " "; + } else { + Actor *a = derefActor(actorId, "drawSentenceLine"); + actorName = (char *)a->getActorName(); + } + _sentenceBuf += Common::String::format("%-13s", actorName); } + flushSentenceLine(); + return; } - // Draw the active actor - if (_activeActor) { - Actor *a = derefActor(_activeActor, ""); + // Current Verb + if (_activeVerb == kVerbNone) + _activeVerb = kVerbWalkTo; - _sentenceBuf += " "; - _sentenceBuf += (const char *)a->getActorName(); - } + char *verbName = (char *)getResourceAddress(rtVerb, _activeVerb); + assert(verbName); + _sentenceBuf = verbName; - _string[2].charset = 1; - _string[2].ypos = _virtscr[kVerbVirtScreen].topline; - _string[2].xpos = 0; - _string[2].right = _virtscr[kVerbVirtScreen].w - 1; - _string[2].color = 16; + if (_activeObject) { + // Draw the 1st active object + drawSentenceObject(_activeObject); - byte string[80]; - const char *ptr = _sentenceBuf.c_str(); - int i = 0, len = 0; + // Append verb preposition + int sentencePrep = activeVerbPrep(); + if (sentencePrep) { + drawPreposition(sentencePrep); - // Maximum length of printable characters - int maxChars = 40; - while (*ptr) { - if (*ptr != '@') - len++; - if (len > maxChars) { - break; + // Draw the 2nd active object + if (_activeObject2) + drawSentenceObject(_activeObject2); } - - string[i++] = *ptr++; - } - string[i] = 0; - sentenceline.top = _virtscr[kVerbVirtScreen].topline; - sentenceline.bottom = _virtscr[kVerbVirtScreen].topline + 8; - sentenceline.left = 0; - sentenceline.right = _virtscr[kVerbVirtScreen].w - 1; - restoreBackground(sentenceline); - - drawString(2, (byte *)string); + flushSentenceLine(); } void ScummEngine_v0::o_stopCurrentScript() { - int script; + stopScriptCommon(0); +} - script = vm.slot[_currentScript].number; +void ScummEngine_v0::o_walkActorToObject() { + int actor = getVarOrDirectByte(PARAM_1); + int objId = fetchScriptByte(); + int obj; - if (_currentScript != 0 && vm.slot[_currentScript].number == script) - stopObjectCode(); + if (_opcode & 0x40) + obj = OBJECT_V0(objId, kObjectV0TypeBG); else - stopScript(script); + obj = OBJECT_V0(objId, kObjectV0TypeFG); + + if (whereIsObject(obj) != WIO_NOT_FOUND) { + walkActorToObject(actor, obj); + } } void ScummEngine_v0::o_loadSound() { @@ -625,18 +575,16 @@ void ScummEngine_v0::o_loadRoom() { } void ScummEngine_v0::o_loadRoomWithEgo() { - Actor *a; + Actor_v0 *a; int obj, room, x, y, dir; obj = fetchScriptByte(); room = fetchScriptByte(); - a = derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo"); + a = (Actor_v0 *)derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo"); //0x634F - if (((ActorC64 *)a)->_miscflags & 0x40) { - // TODO: Check if this is the correct function - // to be calling here + if (a->_miscflags & kActorMiscFlagFreeze) { stopObjectCode(); return; } @@ -654,15 +602,14 @@ void ScummEngine_v0::o_loadRoomWithEgo() { x = r.x; y = r.y; a->putActor(x, y, _currentRoom); - a->setDirection(dir + 180); - + camera._dest.x = camera._cur.x = a->getPos().x; setCameraAt(a->getPos().x, a->getPos().y); setCameraFollows(a); _fullRedraw = true; - resetSentence(false); + resetSentence(); if (x >= 0 && y >= 0) { a->startWalkActor(x, y, -1); @@ -679,27 +626,39 @@ void ScummEngine_v0::o_unlockRoom() { _res->unlock(rtRoom, resid); } -void ScummEngine_v0::o_cursorCommand() { - // TODO - int state = 0; +void ScummEngine_v0::setMode(byte mode) { + int state; + + _currentMode = mode; - _currentMode = fetchScriptByte(); switch (_currentMode) { - case 0: - state = 15; + case kModeCutscene: + _redrawSentenceLine = false; + // Note: do not change freeze state here + state = USERSTATE_SET_IFACE | + USERSTATE_SET_CURSOR; break; - case 1: - state = 31; + case kModeKeypad: + _redrawSentenceLine = false; + state = USERSTATE_SET_IFACE | + USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON | + USERSTATE_SET_FREEZE | USERSTATE_FREEZE_ON; break; - case 2: - break; - case 3: - state = 247; + case kModeNormal: + case kModeNoNewKid: + state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL | + USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON | + USERSTATE_SET_FREEZE; break; + default: + error("Invalid mode: %d", mode); } setUserState(state); - debug(0, "o_cursorCommand(%d)", _currentMode); +} + +void ScummEngine_v0::o_setMode() { + setMode(fetchScriptByte()); } void ScummEngine_v0::o_lights() { @@ -724,24 +683,31 @@ void ScummEngine_v0::o_lights() { void ScummEngine_v0::o_animateActor() { int act = getVarOrDirectByte(PARAM_1); int anim = getVarOrDirectByte(PARAM_2); - int unk = fetchScriptByte(); - - debug(0,"o_animateActor: unk %d", unk); - - ActorC64 *a = (ActorC64*) derefActor(act, "o_animateActor"); - - // 0x6993 - if (anim == 0xFE) { - a->_speaking = 0x80; // Enabled, but not switching - return; - } - // 0x69A3 - if (anim == 0xFD) { - a->_speaking = 0x00; - return; + int8 repeat = (int8) fetchScriptByte(); + + Actor_v0 *a = (Actor_v0*) derefActor(act, "o_animateActor"); + + a->_animFrameRepeat = repeat; + + switch (anim) { + + case 0xFE: + // 0x6993 + a->_speaking = 0x80; // Enabled, but not switching + return; + + case 0xFD: + // 0x69A3 + a->_speaking = 0x00; + return; + + case 0xFF: + a->stopActorMoving(); + return; } a->animateActor(anim); + a->animateCostume(); } void ScummEngine_v0::o_getActorMoving() { @@ -760,7 +726,12 @@ void ScummEngine_v0::o_putActorAtObject() { a = derefActor(getVarOrDirectByte(PARAM_1), "o_putActorAtObject"); - obj = fetchScriptByte(); + int objId = fetchScriptByte(); + if (_opcode & 0x40) + obj = OBJECT_V0(objId, kObjectV0TypeBG); + else + obj = OBJECT_V0(objId, kObjectV0TypeFG); + if (whereIsObject(obj) != WIO_NOT_FOUND) { getObjectXYPos(obj, x, y); AdjustBoxResult r = a->adjustXYToBeInBox(x, y); @@ -776,20 +747,13 @@ void ScummEngine_v0::o_putActorAtObject() { void ScummEngine_v0::o_pickupObject() { int obj = fetchScriptByte(); - if (obj == 0) { - obj = _activeObject; - } + if (!obj) + obj = _cmdObject; - if (obj < 1) { - error("pickupObject received invalid index %d (script %d)", obj, vm.slot[_currentScript].number); - } - - if (getObjectIndex(obj) == -1) + /* Don't take an object twice */ + if (whereIsObject(obj) == WIO_INVENTORY) return; - if (whereIsObjectInventory(_activeObject2) == WIO_INVENTORY) /* Don't take an */ - return; /* object twice */ - addObjectToInventory(obj, _roomResource); markObjectRectAsDirty(obj); putOwner(obj, VAR(VAR_EGO)); @@ -800,14 +764,22 @@ void ScummEngine_v0::o_pickupObject() { } void ScummEngine_v0::o_setObjectName() { - int obj = fetchScriptByte(); + int obj; + int objId = fetchScriptByte(); + if (!objId) { + obj = _cmdObject; + } else { + if (_opcode & 0x80) + obj = OBJECT_V0(objId, kObjectV0TypeBG); + else + obj = OBJECT_V0(objId, kObjectV0TypeFG); + } setObjectName(obj); } void ScummEngine_v0::o_nop() { } -// TODO: Maybe translate actor flags in future. void ScummEngine_v0::o_setActorBitVar() { byte act = getVarOrDirectByte(PARAM_1); byte mask = getVarOrDirectByte(PARAM_2); @@ -817,7 +789,7 @@ void ScummEngine_v0::o_setActorBitVar() { if (act >= _numActors) return; - ActorC64 *a = (ActorC64 *)derefActor(act, "o_setActorBitVar"); + Actor_v0 *a = (Actor_v0 *)derefActor(act, "o_setActorBitVar"); if (mod) a->_miscflags |= mask; @@ -825,20 +797,24 @@ void ScummEngine_v0::o_setActorBitVar() { a->_miscflags &= ~mask; // This flag causes the actor to stop moving (used by script #158, Green Tentacle 'Oomph!') - if (a->_miscflags & 0x40) + if (a->_miscflags & kActorMiscFlagFreeze) a->stopActorMoving(); - if (a->_miscflags & 0x80) - a->setActorCostume(0); debug(0, "o_setActorBitVar(%d, %d, %d)", act, mask, mod); } +void ScummEngine_v0::o_getObjectOwner() { + getResultPos(); + int obj = getVarOrDirectWord(PARAM_1); + setResult(getOwner(obj ? obj : _cmdObject)); +} + void ScummEngine_v0::o_getActorBitVar() { getResultPos(); byte act = getVarOrDirectByte(PARAM_1); byte mask = getVarOrDirectByte(PARAM_2); - ActorC64 *a = (ActorC64 *)derefActor(act, "o_getActorBitVar"); + Actor_v0 *a = (Actor_v0 *)derefActor(act, "o_getActorBitVar"); setResult((a->_miscflags & mask) ? 1 : 0); debug(0, "o_getActorBitVar(%d, %d, %d)", act, mask, (a->_miscflags & mask)); @@ -867,74 +843,97 @@ void ScummEngine_v0::o_getBitVar() { debug(0, "o_getBitVar (%d, %d %d)", flag, mask, _bitVars[flag] & (1 << mask)); } -void ScummEngine_v0::o_print_c64() { +void ScummEngine_v0::o_print() { _actorToPrintStrFor = fetchScriptByte(); decodeParseString(); } -void ScummEngine_v0::o_printEgo_c64() { +void ScummEngine_v0::o_printEgo() { _actorToPrintStrFor = (byte)VAR(VAR_EGO); decodeParseString(); } void ScummEngine_v0::o_doSentence() { - byte entry = fetchScriptByte(); - byte obj = fetchScriptByte(); - fetchScriptByte(); + byte verb = fetchScriptByte(); + int obj, obj2; + byte b; + + b = fetchScriptByte(); + if (b == 0xFF) { + obj = _cmdObject2; + } else if (b == 0xFE) { + obj = _cmdObject; + } else { + obj = OBJECT_V0(b, (_opcode & 0x80) ? kObjectV0TypeBG : kObjectV0TypeFG); + } - runObjectScript(obj, entry, false, false, NULL); -} + b = fetchScriptByte(); + if (b == 0xFF) { + obj2 = _cmdObject2; + } else if (b == 0xFE) { + obj2 = _cmdObject; + } else { + obj2 = OBJECT_V0(b, (_opcode & 0x40) ? kObjectV0TypeBG : kObjectV0TypeFG); + } -void ScummEngine_v0::o_unknown2() { - byte var1 = fetchScriptByte(); - error("STUB: o_unknown2(%d)", var1); + doSentence(verb, obj, obj2); } -void ScummEngine_v0::o_ifActiveObject() { +bool ScummEngine_v0::ifEqualActiveObject2Common(bool checkType) { byte obj = fetchScriptByte(); + if (!checkType || (OBJECT_V0_TYPE(_cmdObject2) == kObjectV0TypeFG)) + return (obj == OBJECT_V0_ID(_cmdObject2)); + return false; +} - jumpRelative(obj == _activeInventory); +void ScummEngine_v0::o_ifEqualActiveObject2() { + bool equal = ifEqualActiveObject2Common((_opcode & 0x80) == 0); + jumpRelative(equal); } -void ScummEngine_v0::o_getClosestObjActor() { - int obj; - int act; +void ScummEngine_v0::o_ifNotEqualActiveObject2() { + bool equal = ifEqualActiveObject2Common((_opcode & 0x80) == 0); + jumpRelative(!equal); +} + +void ScummEngine_v0::o_getClosestActor() { + int act, check_act; int dist; // This code can't detect any actors farther away than 255 units // (pixels in newer games, characters in older ones.) But this is // perfectly OK, as it is exactly how the original behaved. - int closest_obj = 0xFF, closest_dist = 0xFF; + int closest_act = 0xFF, closest_dist = 0xFF; getResultPos(); act = getVarOrDirectByte(PARAM_1); - obj = (_opcode & PARAM_2) ? 25 : 7; + check_act = (_opcode & PARAM_2) ? 25 : 7; do { - dist = getObjActToObjActDist(act, obj); + dist = getObjActToObjActDist(actorToObj(act), actorToObj(check_act)); if (dist < closest_dist) { closest_dist = dist; - closest_obj = obj; + closest_act = check_act; } - } while (--obj); + } while (--check_act); - setResult(closest_obj); + setResult(closest_act); } void ScummEngine_v0::o_cutscene() { - vm.cutSceneData[0] = _userState | (_userPut ? 16 : 0); + vm.cutSceneData[0] = _currentMode; vm.cutSceneData[2] = _currentRoom; - vm.cutSceneData[3] = camera._mode; - // Hide inventory, freeze scripts, hide cursor - setUserState(15); + freezeScripts(0); + setMode(kModeCutscene); _sentenceNum = 0; - resetSentence(false); + resetSentence(); vm.cutScenePtr[0] = 0; + vm.cutSceneScript[0] = 0; } void ScummEngine_v0::o_endCutscene() { @@ -944,68 +943,43 @@ void ScummEngine_v0::o_endCutscene() { vm.cutSceneScript[0] = 0; vm.cutScenePtr[0] = 0; - // Reset user state to values before cutscene - setUserState(vm.cutSceneData[0] | 7); + setMode(vm.cutSceneData[0]); - camera._mode = (byte) vm.cutSceneData[3]; - if (camera._mode == kFollowActorCameraMode) { - actorFollowCamera(VAR(VAR_EGO)); - } else if (vm.cutSceneData[2] != _currentRoom) { + if (_currentMode == kModeKeypad) { startScene(vm.cutSceneData[2], 0, 0); + // in contrast to the normal keypad behavior we unfreeze scripts here + unfreezeScripts(); + } else { + unfreezeScripts(); + actorFollowCamera(VAR(VAR_EGO)); + // set mode again to have the freeze mode right + setMode(vm.cutSceneData[0]); + _redrawSentenceLine = true; } } -void ScummEngine_v0::o_beginOverride() { - const int idx = vm.cutSceneStackPointer; - assert(0 <= idx && idx < 5); - - vm.cutScenePtr[idx] = _scriptPointer - _scriptOrgPointer; - vm.cutSceneScript[idx] = _currentScript; - - // Skip the jump instruction following the override instruction - // (the jump is responsible for "skipping" cutscenes, and the reason - // why we record the current script position in vm.cutScenePtr). - fetchScriptByte(); - ScummEngine::fetchScriptWord(); - - // This is based on disassembly - VAR(VAR_OVERRIDE) = 0; -} - void ScummEngine_v0::o_setOwnerOf() { int obj, owner; obj = getVarOrDirectWord(PARAM_1); owner = getVarOrDirectByte(PARAM_2); - if (obj == 0) - obj = _activeInventory; + if (!obj) + obj = _cmdObject; setOwnerOf(obj, owner); } -void ScummEngine_v0::resetSentence(bool walking) { - _activeVerb = 13; - - // If the actor is walking, or the screen is a keypad (no sentence verbs/objects are drawn) - // Then reset all active objects (stops the radio crash, bug #3077966) - if (!walking || !(_userState & 32)) { - _v0ObjectFlag = 0; - _activeInventory = 0; - _activeObject = 0; - _activeObject2 = 0; - _activeObjectIndex = 0; - _activeObject2Index = 0; - } +void ScummEngine_v0::resetSentence() { + _activeVerb = kVerbWalkTo; + _activeObject = 0; + _activeObject2 = 0; - _verbExecuting = false; - _verbPickup = false; + _walkToObjectState = kWalkToObjectStateDone; + _redrawSentenceLine = true; - _activeActor = 0; - _activeInvExecute = false; - _activeObject2Inv = false; - _activeObjectObtained = false; - _activeObject2Obtained = false; + _sentenceNum = 0; + _sentenceNestedCount = 0; } } // End of namespace Scumm |