From dcf32be3f656b0adda3feb3c07c1f5940ebfa979 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 15 Mar 2009 16:48:20 +0000 Subject: LOL: - added some missing animations for the shops - added support for dropping/picking up items (no throwing yet) svn-id: r39422 --- engines/kyra/gui_lol.cpp | 56 +++++++++++-- engines/kyra/items_lol.cpp | 106 +++++++++++++----------- engines/kyra/lol.cpp | 12 +-- engines/kyra/lol.h | 68 ++++++++-------- engines/kyra/resource.h | 1 + engines/kyra/scene_lol.cpp | 37 +++++---- engines/kyra/script_lol.cpp | 8 +- engines/kyra/script_tim.cpp | 25 +++++- engines/kyra/script_tim.h | 9 ++- engines/kyra/sprites_lol.cpp | 189 ++++++++++++++++++++++++++++++------------- engines/kyra/staticres.cpp | 30 ++++--- 11 files changed, 350 insertions(+), 191 deletions(-) (limited to 'engines') diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index ffc3009bdb..453e4280ea 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -1196,22 +1196,47 @@ int LoLEngine::clickedExitCharInventory(Button *button) { return 1; } -int LoLEngine::clickedUnk16(Button *button) { +int LoLEngine::clickedSceneDropItem(Button *button) { + static const uint8 offsX[] = { 0x40, 0xC0, 0x40, 0xC0 }; + static const uint8 offsY[] = { 0x40, 0x40, 0xC0, 0xC0 }; + static const uint8 dirIndex[] = { 0, 1, 2, 3, 1, 3, 0, 2, 3, 2, 1, 0, 2, 0, 3, 1 }; + + if ((_updateFlags & 1) || !_itemInHand) + return 0; + + uint16 block = _currentBlock; + if (button->data2Val2 > 1) { + block = calcNewBlockPosition(_currentBlock, _currentDirection); + int f = _wllWallFlags[_levelBlockProperties[block].walls[_currentDirection ^ 2]]; + if (!(f & 0x80) || (f & 2)) + return 1; + } + + uint16 x = 0; + uint16 y = 0; + int i = dirIndex[(_currentDirection << 2) + button->data2Val2]; + + calcCoordinates(x, y, block, offsX[i], offsY[i]); + dropItem(_itemInHand, x, y, 0, 1); + setHandItem(0); + return 1; } int LoLEngine::clickedScenePickupItem(Button *button) { static const int8 checkX[] = { 0, 0, 1, 0, -1, -1, 1, 1, -1, 0, 2, 0, -2, -1, 1, 2, 2, 1, -1, -2, -2 }; static const int8 checkY[] = { 0, -1, 0, 1, 0, -1, -1, 1, 1, -2, 0, 2, 0, -2, -2, -1, 1, 2, 2, 1, -1 }; + static const int len = ARRAYSIZE(checkX); - if (_updateFlags & 1) + if ((_updateFlags & 1) || _itemInHand) return 0; + int cp = _screen->setCurPage(_sceneDrawPage1); - clickSceneSub1(); + redrawSceneItem(); int p = 0; - for (int i = 0; i < 21; i++) { + for (int i = 0; i < len; i++) { p = _screen->getPagePixel(_screen->_curPage, _mouseX + checkX[i], _mouseY + checkY[i]); if (p) break; @@ -1224,10 +1249,10 @@ int LoLEngine::clickedScenePickupItem(Button *button) { uint16 block = (p <= 128) ? calcNewBlockPosition(_currentBlock, _currentDirection) : _currentBlock; - int found = checkSceneForItems(&_levelBlockProperties[block], p &0x7f); + int found = checkSceneForItems(&_levelBlockProperties[block].drawObjects, p & 0x7f); if (found != -1) { - foundItemSub(found, block); + pickupItem(found, block); setHandItem(found); } @@ -1368,7 +1393,24 @@ int LoLEngine::clickedUnk24(Button *button) { return 1; } -int LoLEngine::clickedSceneDropItem(Button *button) { +int LoLEngine::clickedSceneThrowItem(Button *button) { + //if (_updateFlags & 1) + return 0; + + uint16 block = calcNewBlockPosition(_currentBlock, _currentDirection); + if ((_wllWallFlags[_levelBlockProperties[block].walls[_currentDirection ^ 2]] & 2) || !_itemInHand) + return 0; + + uint16 x = 0; + uint16 y = 0; + calcCoordinates(x, y, _currentBlock, 0x80, 0x80); + + if (throwItem(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) { + snd_playSoundEffect(18, -1); + setHandItem(0); + } + + _sceneUpdateRequired = true; return 1; } diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index 3852bcf55b..3918d21dfb 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -136,7 +136,7 @@ int LoLEngine::makeItem(int itemIndex, int curFrame, int flags) { if (t) break; else - ii = _itemsInPlay[ii - 1].next; + ii = _itemsInPlay[ii - 1].nextAssignedObject; } if (t) { @@ -149,22 +149,22 @@ int LoLEngine::makeItem(int itemIndex, int curFrame, int flags) { if (cnt) { slot = r; if (testUnkItemFlags(r)) { - if (_itemsInPlay[r].next) - _itemsInPlay[_itemsInPlay[r].next].level = _itemsInPlay[r].level; + if (_itemsInPlay[r].nextAssignedObject) + _itemsInPlay[_itemsInPlay[r].nextAssignedObject].level = _itemsInPlay[r].level; deleteItem(r); slot = r; } else { - int ii = _itemsInPlay[slot].next; + int ii = _itemsInPlay[slot].nextAssignedObject; while (ii) { if (testUnkItemFlags(ii)) { - _itemsInPlay[slot].next = _itemsInPlay[ii].next; + _itemsInPlay[slot].nextAssignedObject = _itemsInPlay[ii].nextAssignedObject; deleteItem(ii); slot = ii; break; } else { slot = ii; } - ii = _itemsInPlay[slot].next; + ii = _itemsInPlay[slot].nextAssignedObject; } } } @@ -222,7 +222,7 @@ void LoLEngine::deleteItem(int itemIndex) { _itemsInPlay[itemIndex].shpCurFrame_flg |= 0x8000; } -ItemInPlay *LoLEngine::findItem(uint16 index) { +ItemInPlay *LoLEngine::findObject(uint16 index) { if (index & 0x8000) return (ItemInPlay *)&_monsters[index & 0x7fff]; else @@ -269,52 +269,58 @@ void LoLEngine::setHandItem(uint16 itemIndex) { _screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(itemIndex)); } -void LoLEngine::clickSceneSub1() { - assignBlockCaps(_currentBlock, _currentDirection); - _screen->fillRect(112, 0, 287, 119, 0); - - static const uint8 sceneItemWidth[] = { 0, 254, 1, 255, 2, 0, 1, 255 } ; - static const uint8 sceneClickTileIndex[] = { 13, 16}; - - int16 x1 = 0; - int16 x2 = 0; +void LoLEngine::dropItem(int item, uint16 x, uint16 y, int a, int b) { + if (!a) { + x = (x & 0xffc0) | 0x40; + y = (y & 0xffc0) | 0x40; + } - for (int i = 0; i < 2; i++) { - uint8 tile = sceneClickTileIndex[i]; - setLevelShapesDim(sceneClickTileIndex[i], x1, x2, 13); - uint16 s = _curBlockCaps[tile]->field_6; + uint16 block = calcBlockIndex(x, y); + _itemsInPlay[item].x = x; + _itemsInPlay[item].y = y; + _itemsInPlay[item].blockPropertyIndex = block; + _itemsInPlay[item].unk4 = a; - int t = (i << 7) + 1; - while (s) { - if (s & 0x8000) { - s &= 0x7fff; - s = _monsters[i].unk2; - } else { - ItemInPlay *item = &_itemsInPlay[s]; + if (b) + _itemsInPlay[item].shpCurFrame_flg |= 0x4000; + else + _itemsInPlay[item].shpCurFrame_flg &= 0xbfff; - if (item->shpCurFrame_flg & 0x4000) { - if (checkMonsterSpace(item->x, item->y, _partyPosX, _partyPosY) > 319) - break; + + assignItemToBlock(&_levelBlockProperties[block].assignedObjects, item); + reassignDrawObjects(_currentDirection, item, &_levelBlockProperties[block], false); + + if (b) + runLevelScriptCustom(block, 0x80, -1, item, 0, 0); - int w = sceneItemWidth[s & 7] << 1; - int h = sceneItemWidth[(s >> 1) & 7] + 5; - if (item->unk4 > 1) - h -= ((item->unk4 - 1) * 6); + checkSceneUpdateNeed(block); +} - uint8 shpIx = _itemProperties[item->itemPropertyIndex].shpIndex; - uint8 *shp = (_itemProperties[item->itemPropertyIndex].flags & 0x40) ? _gameShapes[shpIx] : _itemShapes[_gameShapeMap[shpIx]]; +bool LoLEngine::throwItem(int a, int item, int x, int y, int b, int direction, int c, int charNum, int d) { + return true; +} - drawItemOrMonster(shp, 0, item->x, item->y, w, h, 0, t, 0); - } +void LoLEngine::pickupItem(int item, int block) { + removeAssignedItemFromBlock(&_levelBlockProperties[block].assignedObjects, item); + removeDrawObjectFromBlock(&_levelBlockProperties[block].drawObjects, item); + runLevelScriptCustom(block, 0x100, -1, item, 0, 0); + _itemsInPlay[item].blockPropertyIndex = 0; + _itemsInPlay[item].level = 0; +} - s = item->unk2; - t++; - } - } +void LoLEngine::assignItemToBlock(uint16 *assignedBlockObjects, int id) { + while (*assignedBlockObjects & 0x8000) { + ItemInPlay *tmp = findObject(*assignedBlockObjects); + assignedBlockObjects = &tmp->nextAssignedObject; } + + ItemInPlay *newObject = findObject(id); + newObject->nextAssignedObject = *assignedBlockObjects; + newObject->level = -1; + *assignedBlockObjects = id; } -int LoLEngine::checkMonsterSpace(int itemX, int itemY, int partyX, int partyY) { +int LoLEngine::checkDrawObjectSpace(int itemX, int itemY, int partyX, int partyY) { int a = itemX - partyX; if (a < 0) a = -a; @@ -326,12 +332,18 @@ int LoLEngine::checkMonsterSpace(int itemX, int itemY, int partyX, int partyY) { return a + b; } -int LoLEngine::checkSceneForItems(LevelBlockProperty *block, int pos) { - return -1; -} +int LoLEngine::checkSceneForItems(uint16 *blockDrawObjects, int colour) { + while (*blockDrawObjects) { + if (!(*blockDrawObjects & 0x8000)) { + if (!--colour) + return *blockDrawObjects; + } -void LoLEngine::foundItemSub(int item, int block) { + ItemInPlay *i = findObject(*blockDrawObjects); + blockDrawObjects = &i->nextDrawObject; + } + return -1; } } // end of namespace Kyra diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 022375fd90..2f5ae741c5 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -147,7 +147,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _lampOilStatus = _brightness = _lampStatusUnk = 0; _lampStatusSuspended = false; _tempBuffer5120 = 0; - _tmpData136 = 0; + _throwItemState = 0; _monsters = 0; _unkGameFlag = 0; _lastMouseRegion = 0; @@ -294,7 +294,7 @@ LoLEngine::~LoLEngine() { delete[] _lvlShapeBottom; delete[] _lvlShapeLeftRight; delete[] _tempBuffer5120; - delete[] _tmpData136; + delete[] _throwItemState; delete[] _monsters; delete[] _levelBlockProperties; delete[] _monsterProperties; @@ -413,8 +413,8 @@ Common::Error LoLEngine::init() { _tempBuffer5120 = new uint8[5120]; memset(_tempBuffer5120, 0, 5120); - _tmpData136 = new uint8[136]; - memset(_tmpData136, 0, 136); + _throwItemState = new uint8[136]; + memset(_throwItemState, 0, 136); memset(_gameFlags, 0, sizeof(_gameFlags)); memset(_globalScriptVars, 0, sizeof(_globalScriptVars)); @@ -1660,9 +1660,9 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) { uint16 *c = &monster->assignedItems; while (*c) - c = &_itemsInPlay[*c].next; + c = &_itemsInPlay[*c].nextAssignedObject; *c = item; - _itemsInPlay[item].next = 0; + _itemsInPlay[item].nextAssignedObject = 0; } const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) { diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index e6e4960fed..b76d562550 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -83,20 +83,16 @@ struct LoLCharacter { }; struct SpellProperty { - uint16 field_0; - uint16 unkArr[4]; - uint16 field_A; - uint16 field_C; - uint16 field_E; uint16 spellNameCode; uint16 mpRequired[4]; - uint16 field_1A; + uint16 unkArr[8]; + uint16 flags; }; struct LevelBlockProperty { uint8 walls[4]; - uint16 itemMonsterIndex; - uint16 field_6; + uint16 assignedObjects; + uint16 drawObjects; uint8 direction; uint8 flags; }; @@ -121,8 +117,8 @@ struct MonsterProperty { }; struct MonsterInPlay { - uint16 next; - uint16 unk2; + uint16 nextAssignedObject; + uint16 nextDrawObject; uint8 unk4; uint16 blockPropertyIndex; uint16 x; @@ -155,8 +151,8 @@ struct MonsterInPlay { }; struct ItemInPlay { - uint16 next; - uint16 unk2; + uint16 nextAssignedObject; + uint16 nextDrawObject; uint8 unk4; uint16 blockPropertyIndex; uint16 x; @@ -439,7 +435,7 @@ private: int clickedPortraitEtcRight(Button *button); int clickedCharInventorySlot(Button *button); int clickedExitCharInventory(Button *button); - int clickedUnk16(Button *button); + int clickedSceneDropItem(Button *button); int clickedScenePickupItem(Button *button); int clickedInventorySlot(Button *button); int clickedInventoryScroll(Button *button); @@ -448,7 +444,7 @@ private: int clickedScroll(Button *button); int clickedUnk23(Button *button); int clickedUnk24(Button *button); - int clickedSceneDropItem(Button *button); + int clickedSceneThrowItem(Button *button); int clickedOptions(Button *button); int clickedRestParty(Button *button); int clickedMoneyBox(Button *button); @@ -520,7 +516,7 @@ private: int olol_closeLevelShapeFile(EMCState *script); int olol_loadDoorShapes(EMCState *script); int olol_initAnimStruct(EMCState *script); - int olol_playAnimSequence(EMCState *script); + int olol_playAnimationPart(EMCState *script); int olol_freeAnimStruct(EMCState *script); int olol_getDirection(EMCState *script); int olol_setMusicTrack(EMCState *script); @@ -877,17 +873,17 @@ private: LevelShapeProperty *_levelFileData; uint8 *_doorShapes[2]; - int16 _shpDmX; - int16 _shpDmY; - int16 _dmScaleW; - int16 _dmScaleH; + int _shpDmX; + int _shpDmY; + uint16 _dmScaleW; + uint16 _dmScaleH; int _lastMouseRegion; int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger; uint8 _unkGameFlag; uint8 *_tempBuffer5120; - uint8 *_tmpData136; + uint8 *_throwItemState; const char *const * _levelDatList; int _levelDatListSize; @@ -947,13 +943,15 @@ private: bool addItemToInventory(int itemIndex); bool testUnkItemFlags(int itemIndex); void deleteItem(int itemIndex); - ItemInPlay *findItem(uint16 index); + ItemInPlay *findObject(uint16 index); void runItemScript(int charNum, int item, int reg0, int reg3, int reg4); void setHandItem(uint16 itemIndex); - void clickSceneSub1(); - int checkMonsterSpace(int itemX, int itemY, int partyX, int partyY); - int checkSceneForItems(LevelBlockProperty *block, int pos); - void foundItemSub(int item, int block); + void dropItem(int item, uint16 x, uint16 y, int a, int b); + bool throwItem(int a, int item, int x, int y, int b, int direction, int c, int charNum, int d); + void pickupItem(int item, int block); + void assignItemToBlock(uint16 *assignedBlockObjects, int id); + int checkDrawObjectSpace(int itemX, int itemY, int partyX, int partyY); + int checkSceneForItems(uint16 *blockDrawObjects, int colour); uint8 _moneyColumnHeight[5]; uint16 _credits; @@ -979,6 +977,8 @@ private: int _itemCostSize; const uint8 *_stashSetupData; int _stashSetupDataSize; + const int8 *_sceneItemOffs; + int _sceneItemOffsSize; // monsters void loadMonsterShapes(const char *file, int monsterIndex, int b); @@ -989,24 +989,26 @@ private: int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2); void setMonsterDirection(MonsterInPlay *monster, int dir); void cmzS3(MonsterInPlay *monster); - void removeItemOrMonsterFromBlock(uint16 *blockItemIndex, int id); - void assignItemOrMonsterToBlock(uint16 *blockItemIndex, int id); + void removeAssignedItemFromBlock(uint16 *blockItemIndex, int id); + void removeDrawObjectFromBlock(uint16 *blockItemIndex, int id); + void assignMonsterToBlock(uint16 *assignedBlockObjects, int id); void giveItemToMonster(MonsterInPlay *monster, uint16 item); int checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int testFlag, int wallFlag); int calcMonsterSkillLevel(int id, int a); int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int testFlag, int wallFlag); bool checkBlockOccupiedByParty(int x, int y, int testFlag); const uint16 *getCharacterOrMonsterStats(int id); - void drawMonstersAndItems(int block); + void drawBlockObjects(int blockArrayIndex); void drawMonster(uint16 id); int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags); - void recalcItemMonsterPositions(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag); + void reassignDrawObjects(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag); + void redrawSceneItem(); int calcItemMonsterPosition(ItemInPlay *i, uint16 direction); void recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, int &itemY, uint16 direction); void drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags); void drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl); - uint8 *drawItemOrMonster(uint8 *shape, uint8 *ovl, int x, int y, int w, int h, int flags, int tblValue, bool flip); - int calcDrawingLayerParameters(int srcX, int srcY, int16 &x2, int16 &y2, int16 &w, int16 &h, uint8 *shape, int flip); + uint8 *drawItemOrMonster(uint8 *shape, uint8 *ovl, int x, int y, int fineX, int fineY, int flags, int tblValue, bool flip); + int calcDrawingLayerParameters(int srcX, int srcY, int &x2, int &y2, uint16 &w, uint16 &h, uint8 *shape, int flip); void updateMonster(MonsterInPlay *monster); void moveMonster(MonsterInPlay *monster); @@ -1034,9 +1036,9 @@ private: int _monsterShiftOffsSize; const uint8 *_monsterDirFlags; int _monsterDirFlagsSize; - const int8 *_monsterScaleX; + const uint8 *_monsterScaleX; int _monsterScaleXSize; - const int8 *_monsterScaleY; + const uint8 *_monsterScaleY; int _monsterScaleYSize; const uint16 *_monsterScaleWH; int _monsterScaleWHSize; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 3de89bc3c9..d4dc4688bf 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -221,6 +221,7 @@ enum kKyraResources { //kLolIngameADLSfxIndex, kLolSpellProperties, kLolGameShapeMap, + kLolSceneItemOffs, kLolCharInvIndex, kLolCharInvDefs, kLolCharDefsMan, diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 1aa82fae94..0bb5d31dbe 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -105,10 +105,10 @@ void LoLEngine::addLevelItems() { if (_itemsInPlay[i].level != _currentLevel) continue; - moveItemToBlock(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].itemMonsterIndex, i); + moveItemToBlock(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].assignedObjects, i); _levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].direction = 5; - _itemsInPlay[i].unk2 = 0; + _itemsInPlay[i].nextDrawObject = 0; } } @@ -116,11 +116,11 @@ void LoLEngine::moveItemToBlock(uint16 *cmzItemIndex, uint16 item) { ItemInPlay *tmp = 0; while (*cmzItemIndex & 0x8000) { - tmp = findItem(*cmzItemIndex); - cmzItemIndex = &tmp->next; + tmp = findObject(*cmzItemIndex); + cmzItemIndex = &tmp->nextAssignedObject; } - tmp = findItem(item); + tmp = findObject(item); tmp->level = -1; uint16 ix = *cmzItemIndex; @@ -129,11 +129,11 @@ void LoLEngine::moveItemToBlock(uint16 *cmzItemIndex, uint16 item) { return; *cmzItemIndex = item; - cmzItemIndex = &tmp->next; + cmzItemIndex = &tmp->nextAssignedObject; while (*cmzItemIndex) { - tmp = findItem(*cmzItemIndex); - cmzItemIndex = &tmp->next; + tmp = findObject(*cmzItemIndex); + cmzItemIndex = &tmp->nextAssignedObject; } *cmzItemIndex = ix; @@ -455,13 +455,12 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight void LoLEngine::resetItems(int flag) { for (int i = 0; i < 1024; i++) { _levelBlockProperties[i].direction = 5; - uint16 id = _levelBlockProperties[i].itemMonsterIndex; + uint16 id = _levelBlockProperties[i].assignedObjects; MonsterInPlay *r = 0; while (id & 0x8000) { - r = (MonsterInPlay*)findItem(id); - assert(r); - id = r->next; + r = (MonsterInPlay*)findObject(id); + id = r->nextAssignedObject; } if (!id) @@ -470,11 +469,11 @@ void LoLEngine::resetItems(int flag) { ItemInPlay *it = &_itemsInPlay[id]; it->level = _currentLevel; it->blockPropertyIndex = i; - r->next = 0; + r->nextAssignedObject = 0; } if (flag) - memset(_tmpData136, 0, 136); + memset(_throwItemState, 0, 136); } void LoLEngine::resetLvlBuffer() { @@ -664,12 +663,12 @@ bool LoLEngine::checkBlockPassability(uint16 block, uint16 direction) { if (testWallFlag(block, direction, 1)) return false; - uint16 d = _levelBlockProperties[block].itemMonsterIndex; + uint16 d = _levelBlockProperties[block].assignedObjects; while (d) { if (d & 0x8000) return false; - d = findItem(d)->next; + d = findObject(d)->nextAssignedObject; } return true; @@ -754,7 +753,7 @@ bool LoLEngine::clickedShape(int shapeIndex) { } void LoLEngine::processDoorSwitch(uint16 block, int unk) { - if ((block == _currentBlock) || (_levelBlockProperties[block].itemMonsterIndex & 0x8000)) + if ((block == _currentBlock) || (_levelBlockProperties[block].assignedObjects & 0x8000)) return; int s = 0; @@ -1496,8 +1495,8 @@ void LoLEngine::drawSceneShapes() { drawIceShapes(t, 0); - if (_curBlockCaps[t]->itemMonsterIndex && (w & 0x80)) - drawMonstersAndItems(t); + if (_curBlockCaps[t]->assignedObjects && (w & 0x80)) + drawBlockObjects(t); drawIceShapes(t, 1); diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index c8b025d2d6..3d20e4112c 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -434,9 +434,9 @@ int LoLEngine::olol_initAnimStruct(EMCState *script) { return 0; } -int LoLEngine::olol_playAnimSequence(EMCState *script) { - debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAnimSequence(%p) (%s, %d, %d, %d)", (const void *)script, stackPosString(0), stackPos(1), stackPos(2), stackPos(3)); - +int LoLEngine::olol_playAnimationPart(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAnimationPart(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3)); + _tim->playAnimationPart(stackPos(0), stackPos(1), stackPos(2), stackPos(3)); return 1; } @@ -1390,7 +1390,7 @@ void LoLEngine::setupOpcodeTable() { // 0x18 Opcode(olol_loadDoorShapes); Opcode(olol_initAnimStruct); - Opcode(olol_playAnimSequence); + Opcode(olol_playAnimationPart); Opcode(olol_freeAnimStruct); // 0x1C diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index c1bb094fee..e9b519a8a8 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -1001,10 +1001,33 @@ void TIMInterpreter_LoL::updateBackgroundAnimation(int animIndex) { anim->wsa->setX(anim->x); anim->wsa->setY(anim->y); anim->wsa->setDrawPage(0); - anim->wsa->displayFrame(anim->curFrame - 1, 0, 0); + anim->wsa->displayFrame(anim->curFrame - 1, 0); anim->nextFrame += _system->getMillis(); } +void TIMInterpreter_LoL::playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) { + Animation *anim = &_animations[animIndex]; + anim->wsa->setX(anim->x); + anim->wsa->setY(anim->y); + + int step = (lastFrame >= firstFrame) ? 1 : -1; + for (int i = firstFrame; i != (lastFrame + step) ; i += step) { + uint32 next = _system->getMillis() + delay * _vm->_tickLength; + if (anim->wsaCopyParams & 0x4000) { + _screen->copyRegion(112, 0, 112, 0, 176, 120, 6, 2); + anim->wsa->setDrawPage(2); + anim->wsa->displayFrame(i - 1, anim->wsaCopyParams & 0x1000 ? 0x5000 : 0x4000, _vm->_trueLightTable1, _vm->_trueLightTable2); + _screen->copyRegion(112, 0, 112, 0, 176, 120, 2, 0); + _screen->updateScreen(); + } else { + anim->wsa->setDrawPage(0); + anim->wsa->displayFrame(i - 1, 0); + _screen->updateScreen(); + } + _vm->delay(next - _system->getMillis()); + } +} + void TIMInterpreter_LoL::drawDialogueButtons() { int cp = _screen->setCurPage(0); Screen::FontId of = _screen->setFont(Screen::FID_6_FNT); diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index b88a88c7f6..668866a2a1 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -143,6 +143,7 @@ public: virtual void startBackgroundAnimation(int animIndex, int part) {} virtual void stopBackgroundAnimation(int animIndex) {} virtual void updateBackgroundAnimation(int animIndex) {} + virtual void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {} virtual void forceDialogue(TIM *tim) {} @@ -230,13 +231,13 @@ public: void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3); uint16 processDialogue(); - + void forceDialogue(TIM *tim); + void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame); void startBackgroundAnimation(int animIndex, int part); void stopBackgroundAnimation(int animIndex); - void updateBackgroundAnimation(int animIndex); - - void forceDialogue(TIM *tim); + void updateBackgroundAnimation(int animIndex); + void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay); private: KyraEngine_v1 *vm(); diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index d9de39db97..9a2f2b43f5 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -136,13 +136,13 @@ void LoLEngine::releaseMonsterShapes(int monsterIndex) { } int LoLEngine::disableMonstersForBlock(int block) { - int i = _levelBlockProperties[block].itemMonsterIndex; + int i = _levelBlockProperties[block].assignedObjects; int cnt = 0; MonsterInPlay *t = 0; while (i) { - t = (MonsterInPlay *)findItem(i); - i = t->next; + t = (MonsterInPlay *)findObject(i); + i = t->nextAssignedObject; if (!(i & 0x8000)) continue; @@ -199,7 +199,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { bool cont = true; int t = monster->blockPropertyIndex; if (monster->blockPropertyIndex) { - removeItemOrMonsterFromBlock(&_levelBlockProperties[t].itemMonsterIndex, ((uint16)monster->id) | 0x8000); + removeAssignedItemFromBlock(&_levelBlockProperties[t].assignedObjects, ((uint16)monster->id) | 0x8000); _levelBlockProperties[t].direction = 5; checkSceneUpdateNeed(t); } else { @@ -217,7 +217,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { if (monster->blockPropertyIndex == 0) return; - assignItemOrMonsterToBlock(&_levelBlockProperties[monster->blockPropertyIndex].itemMonsterIndex, ((uint16)monster->id) | 0x8000); + assignMonsterToBlock(&_levelBlockProperties[monster->blockPropertyIndex].assignedObjects, ((uint16)monster->id) | 0x8000); _levelBlockProperties[monster->blockPropertyIndex].direction = 5; checkSceneUpdateNeed(monster->blockPropertyIndex); @@ -285,24 +285,42 @@ void LoLEngine::cmzS3(MonsterInPlay *l) { // TODO } -void LoLEngine::removeItemOrMonsterFromBlock(uint16 *blockItemIndex, int id) { +void LoLEngine::removeAssignedItemFromBlock(uint16 *blockItemIndex, int id) { + ItemInPlay *i = 0; + while (*blockItemIndex) { if (*blockItemIndex == id) { - ItemInPlay *t = findItem(id); - *blockItemIndex = t->next; - t->next = 0; + i = findObject(id); + *blockItemIndex = i->nextAssignedObject; + i->nextAssignedObject = 0; return; - } else { - ItemInPlay *t = findItem(*blockItemIndex); - blockItemIndex = &t->next; } + + i = findObject(*blockItemIndex); + blockItemIndex = &i->nextAssignedObject; } } -void LoLEngine::assignItemOrMonsterToBlock(uint16 *blockItemIndex, int id) { - ItemInPlay *t = findItem(id); - t->next = *blockItemIndex; - *blockItemIndex = id; +void LoLEngine::removeDrawObjectFromBlock(uint16 *blockItemIndex, int id) { + ItemInPlay *i = 0; + + while (*blockItemIndex) { + if (*blockItemIndex == id) { + i = findObject(id); + *blockItemIndex = i->nextDrawObject; + i->nextDrawObject = 0; + return; + } + + i = findObject(*blockItemIndex); + blockItemIndex = &i->nextDrawObject; + } +} + +void LoLEngine::assignMonsterToBlock(uint16 *assignedBlockObjects, int id) { + ItemInPlay *t = findObject(id); + t->nextAssignedObject = *assignedBlockObjects; + *assignedBlockObjects = id; } int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int testFlag, int wallFlag) { @@ -435,17 +453,17 @@ int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int if (!(testFlag & 2)) return 0; - uint16 b = _levelBlockProperties[block].itemMonsterIndex; + uint16 b = _levelBlockProperties[block].assignedObjects; while (b & 0x8000) { MonsterInPlay *monster = &_monsters[b & 0x7fff]; if (monster->mode < 13) { - int r = checkMonsterSpace(x, y, monster->x, monster->y); + int r = checkDrawObjectSpace(x, y, monster->x, monster->y); if ((monsterWidth + monster->properties->maxWidth) > r) return 2; } - b = findItem(b)->next; + b = findObject(b)->nextAssignedObject; } return 0; @@ -458,34 +476,56 @@ bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) { return false; } -void LoLEngine::drawMonstersAndItems(int block) { - LevelBlockProperty *l = _curBlockCaps[block]; - uint16 s = l->itemMonsterIndex; - ItemInPlay *i = findItem(s); +void LoLEngine::drawBlockObjects(int blockArrayIndex) { + LevelBlockProperty *l = _curBlockCaps[blockArrayIndex]; + uint16 s = l->assignedObjects; + ItemInPlay *i = findObject(s); if (l->direction != _currentDirection) { - l->field_6 = 0; + l->drawObjects = 0; l->direction = _currentDirection; while (s) { - i = findItem(s); - recalcItemMonsterPositions(_currentDirection, s, l, true); - i = findItem(s); - s = i->next; + reassignDrawObjects(_currentDirection, s, l, true); + i = findObject(s); + s = i->nextAssignedObject; } } - s = l->field_6; + s = l->drawObjects; while (s) { if (s & 0x8000) { s &= 0x7fff; - if (block < 15) + if (blockArrayIndex < 15) drawMonster(s); - s = _monsters[s].unk2; + s = _monsters[s].nextDrawObject; } else { - ////////// - // TODO + i = &_itemsInPlay[s]; + int fx = _sceneItemOffs[s & 7] << 1; + int fy = _sceneItemOffs[(s >> 1) & 7] + 5; + + if (i->unk4 > 2 || (i->unk4 == 2 && blockArrayIndex >= 15)) { + s = i->nextDrawObject; + continue; + } + + uint8 *shp = 0; + int flg = 0; + + if (i->unk4 >= 2) + fy -= ((i->unk4 - 1) * 6); + + if ((_itemProperties[i->itemPropertyIndex].flags & 0x1000) && !(i->shpCurFrame_flg & 0xC000)) { + i = i; + //////////// + // TODO + } else { + shp = (_itemProperties[i->itemPropertyIndex].flags & 0x40) ? _gameShapes[_itemProperties[i->itemPropertyIndex].shpIndex] : + _itemShapes[_gameShapeMap[_itemProperties[i->itemPropertyIndex].shpIndex << 1]]; + } + drawItemOrMonster(shp, 0, i->x, i->y, fx, fy, flg, -1, false); + s = i->nextDrawObject; } } } @@ -521,11 +561,6 @@ void LoLEngine::drawMonster(uint16 id) { if (!shp2) continue; - //int dW = (READ_LE_UINT16(shp2 + 4) * _dmScaleW) >> 8; - //int dH = (READ_LE_UINT16(shp2 + 6) * _dmScaleH) >> 8; - //if (flg) - // _screen->getShapeScaledWidth(shp2, _dmScaleW); - drawDoorOrMonsterShape(shp2, 0, _shpDmX, _shpDmY, flg | 1, ovl2); } @@ -615,35 +650,79 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) { return 0; } -void LoLEngine::recalcItemMonsterPositions(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag) { +void LoLEngine::reassignDrawObjects(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag) { if (l->direction != direction) { l->direction = 5; return; } - ItemInPlay *i1 = findItem(itemIndex); - int r = calcItemMonsterPosition(i1, direction); - uint16 *b = &l->field_6; - ItemInPlay *i2 = 0; + ItemInPlay *newObject = findObject(itemIndex); + int r = calcItemMonsterPosition(newObject, direction); + uint16 *b = &l->drawObjects; + ItemInPlay *lastObject = 0; while (*b) { - i2 = findItem(itemIndex); + lastObject = findObject(*b); if (flag) { - if (calcItemMonsterPosition(i2, direction) >= r) + if (calcItemMonsterPosition(lastObject, direction) >= r) break; } else { - if (calcItemMonsterPosition(i2, direction) > r) + if (calcItemMonsterPosition(lastObject, direction) > r) break; } - b = &i2->unk2; + b = &lastObject->nextDrawObject; } - i1->unk2 = *b; + newObject->nextDrawObject = *b; *b = itemIndex; } +void LoLEngine::redrawSceneItem() { + assignBlockCaps(_currentBlock, _currentDirection); + _screen->fillRect(112, 0, 287, 119, 0); + + static const uint8 sceneClickTileIndex[] = { 13, 16}; + + int16 x1 = 0; + int16 x2 = 0; + + for (int i = 0; i < 2; i++) { + uint8 tile = sceneClickTileIndex[i]; + setLevelShapesDim(tile, x1, x2, 13); + uint16 s = _curBlockCaps[tile]->drawObjects; + + int t = (i << 7) + 1; + while (s) { + if (s & 0x8000) { + s &= 0x7fff; + s = _monsters[i].nextDrawObject; + } else { + ItemInPlay *item = &_itemsInPlay[s]; + + if (item->shpCurFrame_flg & 0x4000) { + if (checkDrawObjectSpace(item->x, item->y, _partyPosX, _partyPosY) < 320) { + int fx = _sceneItemOffs[s & 7] << 1; + int fy = _sceneItemOffs[(s >> 1) & 7] + 5; + if (item->unk4 > 1) + fy -= ((item->unk4 - 1) * 6); + + uint8 *shp = (_itemProperties[item->itemPropertyIndex].flags & 0x40) ? _gameShapes[_itemProperties[item->itemPropertyIndex].shpIndex] : + _itemShapes[_gameShapeMap[_itemProperties[item->itemPropertyIndex].shpIndex << 1]]; + + drawItemOrMonster(shp, 0, item->x, item->y, fx, fy, 0, t, 0); + _screen->updateScreen(); + } + } + + s = item->nextDrawObject; + t++; + } + } + } +} + int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) { int x = i->x; int y = i->y; @@ -688,7 +767,8 @@ void LoLEngine::drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, _shpDmY = _dscDoorMonsterY[t] + 120; if (flags & 1) { - // TODO + //TODO + flags |=1; } int u = 0; @@ -753,7 +833,7 @@ void LoLEngine::drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y, } } -uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, int w, int h, int flags, int tblValue, bool flip) { +uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, int fineX, int fineY, int flags, int tblValue, bool flip) { uint8 *ovl2 = 0; uint8 *ovl = 0; uint8 tmpOvl[16]; @@ -791,8 +871,8 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, in flg |= 0x2000; } - _shpDmX += ((_dmScaleW * w) >> 8); - _shpDmY += ((_dmScaleH * h) >> 8); + _shpDmX += ((_dmScaleW * fineX) >> 8); + _shpDmY += ((_dmScaleH * fineY) >> 8); int dH = _screen->getShapeScaledHeight(shape, _dmScaleH) >> 1; @@ -814,7 +894,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, in return ovl; } -int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int16 &x2, int16 &y2, int16 &w, int16 &h, uint8 *shape, int flip) { +int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int &x2, int &y2, uint16 &w, uint16 &h, uint8 *shape, int flip) { recalcSpritePosition(_partyPosX, _partyPosY, x1, y1, _currentDirection); if (y1 < 0) { @@ -825,6 +905,7 @@ int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int16 &x2, int16 &y2, int l = y1 >> 5; y2 = _monsterScaleY[l]; x2 = ((_monsterScaleX[l] * x1) >> 8) + 200; + assert (_shpDmY - 56 < 66); w = h = _monsterScaleWH[_shpDmY - 56]; if (flip) @@ -1057,7 +1138,7 @@ int LoLEngine::walkMonster_s3(uint16 monsterBlock, int direction, int distance, if (_wllWallFlags[_levelBlockProperties[p].walls[direction ^ 2]] & 2) return 5; - if (_levelBlockProperties[p].itemMonsterIndex & 0x8000) + if (_levelBlockProperties[p].assignedObjects & 0x8000) return 5; } diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index dfe1f00d56..724fe872d1 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 41 +#define RESFILE_VERSION 42 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -382,6 +382,7 @@ bool StaticResource::init() { { kLolIngameMT32SfxIndex, kRawData, "SFX_MT32.MAP" }, { kLolSpellProperties, kLolSpellData, "SPELLS.DEF" }, { kLolGameShapeMap, kRawData, "GAMESHP.MAP" }, + { kLolSceneItemOffs, kRawData, "ITEMOFFS.DEF" }, { kLolCharInvIndex, kRawData, "CHARINV.MAP" }, { kLolCharInvDefs, kRawData, "CHARINV.DEF" }, { kLolCharDefsMan, kLolRawDataBe16, "CHMAN.DEF" }, @@ -1037,16 +1038,12 @@ bool StaticResource::loadSpellData(const char *filename, void *&ptr, int &size) for (int i = 0; i < size; i++) { SpellProperty *t = &spellData[i]; - t->field_0 = file->readUint16LE(); - for (int ii = 0; ii < 4; ii++) - t->unkArr[ii] = file->readUint16LE(); - t->field_A = file->readUint16LE(); - t->field_C = file->readUint16LE(); - t->field_E = file->readUint16LE(); t->spellNameCode = file->readUint16LE(); for (int ii = 0; ii < 4; ii++) t->mpRequired[ii] = file->readUint16LE(); - t->field_1A = file->readUint16LE(); + for (int ii = 0; ii < 8; ii++) + t->unkArr[ii] = file->readUint16LE(); + t->flags = file->readUint16LE(); }; ptr = spellData; @@ -1756,6 +1753,7 @@ void LoLEngine::initStaticResource() { //_ingameADLSoundIndex = _staticres->loadRawData(kLolIngameADLSfxIndex, _ingameADLSoundIndexSize); _spellProperties = _staticres->loadSpellData(kLolSpellProperties, _spellPropertiesSize); _gameShapeMap = (const int8*)_staticres->loadRawData(kLolGameShapeMap, _gameShapeMapSize); + _sceneItemOffs = (const int8*)_staticres->loadRawData(kLolSceneItemOffs, _sceneItemOffsSize); _charInvIndex = _staticres->loadRawData(kLolCharInvIndex, _charInvIndexSize); _charInvDefs = _staticres->loadRawData(kLolCharInvDefs, _charInvDefsSize); _charDefsMan = _staticres->loadRawDataBe16(kLolCharDefsMan, _charDefsManSize); @@ -1766,8 +1764,8 @@ void LoLEngine::initStaticResource() { _monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, _monsterModifiersSize); _monsterShiftOffs = (const int8*)_staticres->loadRawData(kLolMonsterShiftOffsets, _monsterShiftOffsSize); _monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, _monsterDirFlagsSize); - _monsterScaleX = (const int8*)_staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize); - _monsterScaleY = (const int8*)_staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize); + _monsterScaleX = _staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize); + _monsterScaleY = _staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize); _monsterScaleWH = _staticres->loadRawDataBe16(kLolMonsterScaleWH, _monsterScaleWHSize); _inventorySlotDesc = _staticres->loadRawDataBe16(kLolInventoryDesc, _inventorySlotDescSize); _levelShpList = _staticres->loadStrings(kLolLevelShpList, _levelShpListSize); @@ -1870,10 +1868,10 @@ void LoLEngine::assignButtonCallback(Button *button, int index) { cb(clickedCharInventorySlot), cb(clickedCharInventorySlot), cb(clickedExitCharInventory), - cb(clickedUnk16), - cb(clickedUnk16), - cb(clickedUnk16), - cb(clickedUnk16), + cb(clickedSceneDropItem), + cb(clickedSceneDropItem), + cb(clickedSceneDropItem), + cb(clickedSceneDropItem), cb(clickedScenePickupItem), cb(clickedInventorySlot), cb(clickedInventorySlot), @@ -1911,8 +1909,8 @@ void LoLEngine::assignButtonCallback(Button *button, int index) { cb(clickedUnk23), cb(clickedUnk23), cb(clickedUnk24), - cb(clickedSceneDropItem), - cb(clickedSceneDropItem), + cb(clickedSceneThrowItem), + cb(clickedSceneThrowItem), cb(clickedOptions), cb(clickedRestParty), cb(clickedMoneyBox), -- cgit v1.2.3