diff options
-rw-r--r-- | kyra/debugger.cpp | 11 | ||||
-rw-r--r-- | kyra/debugger.h | 1 | ||||
-rw-r--r-- | kyra/kyra.cpp | 139 | ||||
-rw-r--r-- | kyra/kyra.h | 9 | ||||
-rw-r--r-- | kyra/script_v1.cpp | 58 |
5 files changed, 189 insertions, 29 deletions
diff --git a/kyra/debugger.cpp b/kyra/debugger.cpp index 989f7f1eba..036c884af6 100644 --- a/kyra/debugger.cpp +++ b/kyra/debugger.cpp @@ -43,6 +43,7 @@ Debugger::Debugger(KyraEngine *vm) DCmd_Register("queryflag", &Debugger::cmd_queryFlag); DCmd_Register("timers", &Debugger::cmd_listTimers); DCmd_Register("settimercountdown", &Debugger::cmd_setTimerCountdown); + DCmd_Register("give", &Debugger::cmd_giveItem); } void Debugger::preEnter() { @@ -176,4 +177,14 @@ bool Debugger::cmd_setTimerCountdown(int argc, const char **argv) { return true; } +bool Debugger::cmd_giveItem(int argc, const char **argv) { + if (argc) { + int item = atoi(argv[1]); + _vm->setMouseItem(item); + _vm->_itemInHand = item; + } else + DebugPrintf("Syntax: give <itemid>\n"); + + return true; +} } // End of namespace Kyra diff --git a/kyra/debugger.h b/kyra/debugger.h index b764e2a303..ea7f1aba7c 100644 --- a/kyra/debugger.h +++ b/kyra/debugger.h @@ -48,6 +48,7 @@ protected: bool cmd_queryFlag(int argc, const char **argv); bool cmd_listTimers(int argc, const char **argv); bool cmd_setTimerCountdown(int argc, const char **argv); + bool cmd_giveItem(int argc, const char **argv); }; } // End of namespace Kyra diff --git a/kyra/kyra.cpp b/kyra/kyra.cpp index 2a44a11a34..b83c9d5c86 100644 --- a/kyra/kyra.cpp +++ b/kyra/kyra.cpp @@ -298,6 +298,10 @@ int KyraEngine::init(GameDetector &detector) { _npcScriptData = new ScriptData; memset(_npcScriptData, 0, sizeof(ScriptData)); assert(_npcScriptData); + _npcScript = new ScriptState; + assert(_npcScript); + memset(_npcScript, 0, sizeof(ScriptState)); + _scriptMain = new ScriptState; assert(_scriptMain); memset(_scriptMain, 0, sizeof(ScriptState)); @@ -352,6 +356,7 @@ int KyraEngine::init(GameDetector &detector) { _handleInput = false; _currentRoom = 0xFFFF; + _scenePhasingFlag = 0; _lastProcessedItem = 0; _lastProcessedItemHeight = 16; @@ -1265,13 +1270,28 @@ void KyraEngine::enterNewScene(int sceneId, int facing, int unk1, int unk2, int } } +void KyraEngine::transcendScenes(int roomIndex, int roomName) { + debug(9, "transcendScenes(%d, %d, %d, %d)", roomIndex, roomName); + assert(roomIndex < _roomTableSize); + _roomTable[roomIndex].nameIndex = roomName; + // _game_unkScreenVar2 = 1; + // _game_unkScreenVar3 = 1; + // _game_unkScreenVar1 = 0; + _brandonPosX = _currentCharacter->x1; + _brandonPosY = _currentCharacter->y1; + enterNewScene(roomIndex, _currentCharacter->facing, 0, 0, 0); + // _game_unkScreenVar1 = 1; + // _game_unkScreenVar2 = 0; + // _game_unkScreenVar3 = 0; +} + void KyraEngine::moveCharacterToPos(int character, int facing, int xpos, int ypos) { debug(9, "moveCharacterToPos(%d, %d, %d, %d)", character, facing, xpos, ypos); Character *ch = &_characterList[character]; ch->facing = facing; _screen->hideMouse(); - xpos &= 0xFFFC; - ypos &= 0xFFFE; + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); disableTimer(19); disableTimer(14); disableTimer(18); @@ -1710,10 +1730,10 @@ void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) { } } - xpos2 &= 0xFFFC; - ypos2 &= 0xFFFE; - xpos &= 0xFFFC; - ypos &= 0xFFFE; + xpos2 = (int16)(xpos2 & 0xFFFC); + ypos2 = (int16)(ypos2 & 0xFFFE); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); _currentCharacter->facing = facing; _currentCharacter->x1 = xpos; _currentCharacter->x2 = xpos; @@ -1909,7 +1929,7 @@ void KyraEngine::initSceneObjectList(int brandonAlive) { byte curItem = curRoom->itemsTable[i]; if (curItem != 0xFF) { curAnimState->drawY = curRoom->itemsYPos[i]; - curAnimState->sceneAnimPtr = _shapes[220+i]; + curAnimState->sceneAnimPtr = _shapes[220+curItem]; curAnimState->animFrameNumber = 0xFFFF; curAnimState->y1 = curRoom->itemsYPos[i]; curAnimState->x1 = curRoom->itemsXPos[i]; @@ -3492,6 +3512,30 @@ void KyraEngine::animAddGameItem(int index, uint16 sceneId) { animObj->bkgdChangeFlag = 1; } +void KyraEngine::animAddNPC(int character) { + debug(9, "animAddNPC(%d)", character); + restoreAllObjectBackgrounds(); + AnimObject *animObj = &_charactersAnimState[character]; + const Character *ch = &_characterList[character]; + + animObj->active = 1; + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; + animObj->drawY = ch->y1; + animObj->sceneAnimPtr = _shapes[4+ch->currentAnimFrame]; + animObj->x1 = animObj->x2 = ch->x1 + _defaultShapeTable[ch->currentAnimFrame-7].xOffset; + animObj->y1 = animObj->y2 = ch->y1 + _defaultShapeTable[ch->currentAnimFrame-7].yOffset; + if (ch->facing >= 1 && ch->facing <= 3) { + animObj->flags |= 1; + } else if (ch->facing >= 5 && ch->facing <= 7) { + animObj->flags &= 0xFFFFFFFE; + } + _objectQueue = objectQueue(_objectQueue, animObj); + preserveAnyChangedBackgrounds(); + animObj->refreshFlag = 1; + animObj->bkgdChangeFlag = 1; +} + #pragma mark - #pragma mark - Queue handling #pragma mark - @@ -3662,6 +3706,7 @@ int KyraEngine::findWay(int x, int y, int toX, int toY, int *moveTable, int move debug(9, "findWay(%d, %d, %d, %d, 0x%X, %d)", x, y, toX, toY, moveTable, moveTableSize); x &= 0xFFFC; toX &= 0xFFFC; y &= 0xFFFE; toY &= 0xFFFE; + x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY; if (x == toY && y == toY) { moveTable[0] = 8; @@ -4092,10 +4137,10 @@ int KyraEngine::handleSceneChange(int xpos, int ypos, int unk1, int frameReset) } } - int x = _currentCharacter->x1 & 0xFFFC; - int y = _currentCharacter->y1 & 0xFFFE; - xpos &= 0xFFFC; - ypos &= 0xFFFE; + int x = (int16)(_currentCharacter->x1 & 0xFFFC); + int y = (int16)(_currentCharacter->y1 & 0xFFFE); + xpos = (int16)(xpos & 0xFFFC); + ypos = (int16)(ypos & 0xFFFE); int ret = findWay(x, y, xpos, ypos, _movFacingTable, 150); _pathfinderFlag = 0; if (ret >= _lastFindWayRet) { @@ -4572,6 +4617,11 @@ void KyraEngine::processInput(int xpos, int ypos) { handleSceneChange(xpos, ypos, 1, 1); return; } else { + int script = checkForNPCScriptRun(xpos, ypos); + if (script >= 0) { + runNpcScript(script); + return; + } if (_itemInHand != -1) { if (ypos < 155) { if (hasClickedOnExit(xpos, ypos)) { @@ -4769,4 +4819,71 @@ void KyraEngine::clickEventHandler2() { } } +int KyraEngine::checkForNPCScriptRun(int xpos, int ypos) { + debug(9, "checkForNPCScriptRun(%d, %d)", xpos, ypos); + int returnValue = -1; + const Character *currentChar = _currentCharacter; + int charLeft = 0, charRight = 0, charTop = 0, charBottom = 0; + + int scaleFactor = _scaleTable[currentChar->y1]; + int addX = (((scaleFactor*8)*3)>>8)>>1; + int addY = ((scaleFactor*3)<<4)>>8; + + charLeft = currentChar->x1 - addX; + charRight = currentChar->x1 + addX; + charTop = currentChar->y1 - addY; + charBottom = currentChar->y1; + + if (xpos >= charLeft && charRight >= xpos && charTop <= ypos && charBottom >= ypos) { + return 0; + } + + if (xpos > 304 || xpos < 16) { + return -1; + } + + for (int i = 1; i < 5; ++i) { + currentChar = &_characterList[i]; + + if (currentChar->sceneId != _currentCharacter->sceneId) + continue; + + charLeft = currentChar->x1 - 12; + charRight = currentChar->x1 + 11; + charTop = currentChar->y1 - 48; + // if (!i) { + // charBottom = currentChar->y2 - 16; + // } else { + charBottom = currentChar->y1; + // } + + if (xpos < charLeft || xpos > charRight || ypos < charTop || charBottom < ypos) { + continue; + } + + if (returnValue != -1) { + if (currentChar->y1 >= _characterList[returnValue].y1) { + returnValue = i; + } + } else { + returnValue = i; + } + } + + return returnValue; +} + +void KyraEngine::runNpcScript(int func) { + debug(9, "runNpcScript(%d)", func); + _scriptInterpreter->initScript(_npcScript, _npcScriptData); + _scriptInterpreter->startScript(_npcScript, func); + _npcScript->variables[0] = _currentCharacter->sceneId; + _npcScript->variables[4] = _itemInHand; + _npcScript->variables[5] = func; + + while (_scriptInterpreter->validScript(_npcScript)) { + _scriptInterpreter->runScript(_npcScript); + } +} + } // End of namespace Kyra diff --git a/kyra/kyra.h b/kyra/kyra.h index c85ac18c14..db9d912bc5 100644 --- a/kyra/kyra.h +++ b/kyra/kyra.h @@ -419,6 +419,7 @@ protected: int resetGameFlag(int flag); void enterNewScene(int sceneId, int facing, int unk1, int unk2, int brandonAlive); + void transcendScenes(int roomIndex, int roomName); void moveCharacterToPos(int character, int facing, int xpos, int ypos); void setCharacterPositionWithUpdate(int character); int setCharacterPosition(int character, int *facingTable); @@ -470,6 +471,8 @@ protected: void clickEventHandler2(); void updateMousePointer(); bool hasClickedOnExit(int xpos, int ypos); + int checkForNPCScriptRun(int xpos, int ypos); + void runNpcScript(int func); int countItemsInScene(uint16 sceneId); int processItemDrop(uint16 sceneId, uint8 item, int x, int y, int unk1, int unk2); @@ -484,6 +487,7 @@ protected: void animRemoveGameItem(int index); void animAddGameItem(int index, uint16 sceneId); + void animAddNPC(int character); AnimObject *objectRemoveQueue(AnimObject *queue, AnimObject *rem); AnimObject *objectAddHead(AnimObject *queue, AnimObject *head); @@ -603,6 +607,7 @@ protected: int16 _exitList[11]; SceneExits _sceneExits; uint16 _currentRoom; + int _scenePhasingFlag; uint8 *_maskBuffer; int _sceneChangeState; @@ -640,9 +645,11 @@ protected: Debugger *_debugger; ScriptState *_scriptMain; + + ScriptState *_npcScript; ScriptData *_npcScriptData; - ScriptState *_scriptClick; // TODO: rename to a better name + ScriptState *_scriptClick; ScriptData *_scriptClickData; Character *_characterList; diff --git a/kyra/script_v1.cpp b/kyra/script_v1.cpp index 966625faa8..db0b0643cb 100644 --- a/kyra/script_v1.cpp +++ b/kyra/script_v1.cpp @@ -421,7 +421,7 @@ int KyraEngine::cmd_dropItemInScene(ScriptState *script) { room->itemsYPos[freeItem] = ypos; room->itemsTable[freeItem] = item; - animAddGameItem(sceneId, freeItem); + animAddGameItem(freeItem, sceneId); updateAllObjectShapes(); } else { if (item == 43) { @@ -526,23 +526,26 @@ int KyraEngine::cmd_playAdlibScore(ScriptState *script) { } int KyraEngine::cmd_phaseInSameScene(ScriptState *script) { - warning("STUB: cmd_phaseInSameScene"); + debug(3, "cmd_phaseInSameScene(0x%X) (%d, %d)", script, stackPos(0), stackPos(1)); + transcendScenes(stackPos(0), stackPos(1)); return 0; } int KyraEngine::cmd_setScenePhasingFlag(ScriptState *script) { - warning("STUB: cmd_setScenePhasingFlag"); - return 0; + debug(3, "cmd_setScenePhasingFlag(0x%X) ()"); + _scenePhasingFlag = 1; + return 1; } int KyraEngine::cmd_resetScenePhasingFlag(ScriptState *script) { - warning("STUB: cmd_resetScenePhasingFlag"); + debug(3, "cmd_resetScenePhasingFlag(0x%X) ()"); + _scenePhasingFlag = 0; return 0; } int KyraEngine::cmd_queryScenePhasingFlag(ScriptState *script) { - warning("STUB: cmd_queryScenePhasingFlag"); - return 0; + debug(3, "cmd_queryScenePhasingFlag(0x%X) ()"); + return _scenePhasingFlag; } int KyraEngine::cmd_sceneToDirection(ScriptState *script) { @@ -567,7 +570,8 @@ int KyraEngine::cmd_placeItemInGenericMapScene(ScriptState *script) { } int KyraEngine::cmd_setBrandonStatusBit(ScriptState *script) { - warning("STUB: cmd_setBrandonStatusBit"); + debug(3, "cmd_setBrandonStatusBit(0x%X) (%d)", script, stackPos(0)); + _brandonStatusBit |= stackPos(0); return 0; } @@ -579,8 +583,8 @@ int KyraEngine::cmd_pauseSeconds(ScriptState *script) { } int KyraEngine::cmd_getCharactersLocation(ScriptState *script) { - warning("STUB: cmd_getCharactersLocation"); - return 0; + debug(3, "cmd_getCharactersLocation(0x%X) (%d)", script, stackPos(0)); + return _characterList[stackPos(0)].sceneId; } int KyraEngine::cmd_runNPCSubscript(ScriptState *script) { @@ -709,8 +713,8 @@ int KyraEngine::cmd_runWSAFrames(ScriptState *script) { int KyraEngine::cmd_popBrandonIntoScene(ScriptState *script) { debug(3, "cmd_popBrandonIntoScene(0x%X) (%d, %d, %d, %d)", script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); int changeScaleMode = stackPos(3); - int xpos = stackPos(0) & 0xFFFC; - int ypos = stackPos(1) & 0xFFFE; + int xpos = (int16)(stackPos(0) & 0xFFFC); + int ypos = (int16)(stackPos(1) & 0xFFFE); int facing = stackPos(2); _currentCharacter->x1 = _currentCharacter->x2 = xpos; _currentCharacter->y1 = _currentCharacter->y2 = ypos; @@ -997,8 +1001,8 @@ int KyraEngine::cmd_placeCharacterInOtherScene(ScriptState *script) { debug(3, "cmd_placeCharacterInOtherScene(0x%X) (%d, %d, %d, %d, %d, %d)", script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5)); int id = stackPos(0); int sceneId = stackPos(1); - int xpos = stackPos(2) & 0xFFFC; - int ypos = stackPos(3) & 0xFE; + int xpos = (int16)(stackPos(2) & 0xFFFC); + int ypos = (int16)(stackPos(3) & 0xFFFE); int facing = stackPos(4); int animFrame = stackPos(5); @@ -1021,7 +1025,23 @@ int KyraEngine::cmd_specificItemInInventory(ScriptState *script) { } int KyraEngine::cmd_popMobileNPCIntoScene(ScriptState *script) { - warning("STUB: cmd_popMobileNPCIntoScene"); + debug(3, "cmd_popMobileNPCIntoScene(0x%X) (%d, %d, %d, %d, %d, %d)", script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), (int16)(stackPos(4) & 0xFFFC), (int8)(stackPos(5) & 0xFE)); + int character = stackPos(0); + int sceneId = stackPos(1); + int animFrame = stackPos(2); + int facing = stackPos(3); + int16 xpos = (int16)(stackPos(4) & 0xFFFC); + int8 ypos = (int16)(stackPos(5) & 0xFFFE); + Character *curChar = &_characterList[character]; + + curChar->sceneId = sceneId; + curChar->currentAnimFrame = animFrame; + curChar->facing = facing; + curChar->x1 = curChar->x2 = xpos; + curChar->y1 = curChar->y2 = ypos; + + animAddNPC(character); + updateAllObjectShapes(); return 0; } @@ -1169,7 +1189,8 @@ int KyraEngine::cmd_sceneAnimationActive(ScriptState *script) { } int KyraEngine::cmd_setCharactersMovementDelay(ScriptState *script) { - warning("STUB: cmd_setCharactersMovementDelay"); + debug(3, "cmd_setCharactersMovementDelay(0x%X) (%d, %d)", script, stackPos(0), stackPos(1)); + setTimerCountdown(stackPos(0)+5, stackPos(1)); return 0; } @@ -1297,7 +1318,10 @@ int KyraEngine::cmd_getBirthstoneGem(ScriptState *script) { } int KyraEngine::cmd_queryBrandonStatusBit(ScriptState *script) { - warning("STUB: cmd_queryBrandonStatusBit"); + debug(3, "cmd_queryBrandonStatusBit(0x%X) (%d)", script, stackPos(0)); + if (_brandonStatusBit & stackPos(0)) { + return 1; + } return 0; } |