diff options
-rw-r--r-- | dists/engine-data/kyra.dat | bin | 256483 -> 256570 bytes | |||
-rw-r--r-- | engines/kyra/gui_lol.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/items_lol.cpp | 200 | ||||
-rw-r--r-- | engines/kyra/lol.cpp | 60 | ||||
-rw-r--r-- | engines/kyra/lol.h | 69 | ||||
-rw-r--r-- | engines/kyra/resource.h | 5 | ||||
-rw-r--r-- | engines/kyra/scene_lol.cpp | 8 | ||||
-rw-r--r-- | engines/kyra/script_lol.cpp | 4 | ||||
-rw-r--r-- | engines/kyra/script_tim.cpp | 2 | ||||
-rw-r--r-- | engines/kyra/script_tim.h | 2 | ||||
-rw-r--r-- | engines/kyra/sprites_lol.cpp | 84 | ||||
-rw-r--r-- | engines/kyra/staticres.cpp | 40 | ||||
-rw-r--r-- | engines/kyra/timer_lol.cpp | 12 | ||||
-rw-r--r-- | tools/create_kyradat/create_kyradat.cpp | 3 | ||||
-rw-r--r-- | tools/create_kyradat/create_kyradat.h | 1 | ||||
-rw-r--r-- | tools/create_kyradat/lol_cd.h | 3 | ||||
-rw-r--r-- | tools/create_kyradat/misc.h | 1 |
17 files changed, 417 insertions, 79 deletions
diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat Binary files differindex 1e1de8ab74..e3f56b61f8 100644 --- a/dists/engine-data/kyra.dat +++ b/dists/engine-data/kyra.dat diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index 9f36e060df..e4ba477f2a 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -1217,7 +1217,7 @@ int LoLEngine::clickedSceneDropItem(Button *button) { int i = dirIndex[(_currentDirection << 2) + button->data2Val2]; calcCoordinates(x, y, block, offsX[i], offsY[i]); - dropItem(_itemInHand, x, y, 0, 1); + setItemPosition(_itemInHand, x, y, 0, 1); setHandItem(0); return 1; diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index 3918d21dfb..06667023ad 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -229,7 +229,7 @@ ItemInPlay *LoLEngine::findObject(uint16 index) { return &_itemsInPlay[index]; } -void LoLEngine::runItemScript(int charNum, int item, int reg0, int reg3, int reg4) { +void LoLEngine::runItemScript(int charNum, int item, int sub, int next, int reg4) { EMCState scriptState; memset(&scriptState, 0, sizeof(EMCState)); @@ -240,14 +240,18 @@ void LoLEngine::runItemScript(int charNum, int item, int reg0, int reg3, int reg _emc->init(&scriptState, &_itemScript); _emc->start(&scriptState, func); - scriptState.regs[0] = reg0; + scriptState.regs[0] = sub; scriptState.regs[1] = charNum; scriptState.regs[2] = item; - scriptState.regs[3] = reg3; + scriptState.regs[3] = next; scriptState.regs[4] = reg4; - while (_emc->isValid(&scriptState)) - _emc->run(&scriptState); + if (_emc->isValid(&scriptState)) { + if (*(scriptState.ip - 1) & sub) { + while (_emc->isValid(&scriptState)) + _emc->run(&scriptState); + } + } } void LoLEngine::setHandItem(uint16 itemIndex) { @@ -269,8 +273,8 @@ void LoLEngine::setHandItem(uint16 itemIndex) { _screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(itemIndex)); } -void LoLEngine::dropItem(int item, uint16 x, uint16 y, int a, int b) { - if (!a) { +void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b) { + if (!flyingHeight) { x = (x & 0xffc0) | 0x40; y = (y & 0xffc0) | 0x40; } @@ -279,7 +283,7 @@ void LoLEngine::dropItem(int item, uint16 x, uint16 y, int a, int b) { _itemsInPlay[item].x = x; _itemsInPlay[item].y = y; _itemsInPlay[item].blockPropertyIndex = block; - _itemsInPlay[item].unk4 = a; + _itemsInPlay[item].flyingHeight = flyingHeight; if (b) _itemsInPlay[item].shpCurFrame_flg |= 0x4000; @@ -296,18 +300,186 @@ void LoLEngine::dropItem(int item, uint16 x, uint16 y, int a, int b) { checkSceneUpdateNeed(block); } -bool LoLEngine::throwItem(int a, int item, int x, int y, int b, int direction, int c, int charNum, int d) { - return true; -} - void LoLEngine::pickupItem(int item, int block) { - removeAssignedItemFromBlock(&_levelBlockProperties[block].assignedObjects, item); - removeDrawObjectFromBlock(&_levelBlockProperties[block].drawObjects, item); + removeAssignedObjectFromBlock(&_levelBlockProperties[block], item); + removeDrawObjectFromBlock(&_levelBlockProperties[block], item); runLevelScriptCustom(block, 0x100, -1, item, 0, 0); _itemsInPlay[item].blockPropertyIndex = 0; _itemsInPlay[item].level = 0; } +bool LoLEngine::throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c) { + int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, x, y); + FlyingObject *t = _flyingItems; + int slot = -1; + int i = 0; + + for (; i < 8; i++) { + if (!t->enable) { + sp = -1; + break; + } + + int csp = checkDrawObjectSpace(_partyPosX, _partyPosX, t->x, t->y); + if (csp > sp){ + sp = csp; + slot = i; + } + t++; + } + + if (sp != -1 && slot != -1) { + i = slot; + + t = &_flyingItems[i]; + endObjectFlight(t, x, y, 8); + } + + if (i == 8) + return false; + + t->enable = 1; + t->a = a; + t->item = item; + t->x = x; + t->y = y; + t->flyingHeight = flyingHeight; + t->direction = direction; + t->distance = 255; + t->charNum = charNum; + t->flags = 7; + t->wallFlags = 2; + t->c = c; + + if (charNum != -1) { + if (charNum & 0x8000) { + t->flags &= 0xfd; + } else { + t->flags &= 0xfb; + increaseExperience(charNum, 1, 2); + } + } + + updateObjectFlightPosition(t); + + return true; +} + +void LoLEngine::endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock) { + int cx = x; + int cy = y; + uint16 block = calcBlockIndex(t->x, t->y); + removeAssignedObjectFromBlock(&_levelBlockProperties[block], t->item); + removeDrawObjectFromBlock(&_levelBlockProperties[block], t->item); + + if (objectOnNextBlock == 1) { + cx = t->x; + cy = t->y; + } + + if (t->a == 0 || t->a == 1) { + objectFlightProcessHits(t, cx, cy, objectOnNextBlock); + t->x = (cx & 0xffc0) | 0x40; + t->y = (cy & 0xffc0) | 0x40; + t->flyingHeight = 0; + updateObjectFlightPosition(t); + } + + t->enable = 0; +} + +void LoLEngine::processObjectFlight(FlyingObject *t, int x, int y) { + int bl = calcBlockIndex(t->x, t->y); + LevelBlockProperty *l = &_levelBlockProperties[bl]; + removeAssignedObjectFromBlock(l, t->item); + removeDrawObjectFromBlock(l, t->item); + t->x = x; + t->y = y; + updateObjectFlightPosition(t); + checkSceneUpdateNeed(bl); +} + +void LoLEngine::updateObjectFlightPosition(FlyingObject *t) { + if (t->a == 0) { + setItemPosition(t->item, t->x, t->y, t->flyingHeight, (t->flyingHeight == 0) ? 1 : 0); + } else if (t->a == 1) { + if (t->flyingHeight == 0) { + deleteItem(t->item); + checkSceneUpdateNeed(calcBlockIndex(t->x, t->y)); + } else { + setItemPosition(t->item, t->x, t->y, t->flyingHeight, 0); + } + } +} + +void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock) { + int r = 0; + + if (objectOnNextBlock == 1) { + runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].blockPropertyIndex, t->direction >> 1), 0x8000, -1, t->item, 0, 0); + return; + + } else if (objectOnNextBlock == 2) { + if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) { + int o = _levelBlockProperties[_itemsInPlay[t->item].blockPropertyIndex].assignedObjects; + + while (o & 0x8000) { + ItemInPlay *i = findObject(o); + o = i->nextAssignedObject; + runItemScript(t->charNum, t->item, 0x8000, o, 0); + } + + return; + + } else { + r = flyingObjectHitMonsters(x, y); + } + + } else if (objectOnNextBlock == 4) { + _unkDrawLevelBool = true; + if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) { + for (int i = 0; i < 4; i++) { + if (_characters[i].flags & 1) + runItemScript(t->charNum, t->item, 0x8000, i, 0); + } + return; + + } else { + r = flyingObjectHitParty(x, y); + } + } + + runItemScript(t->charNum, t->item, 0x8000, r, 0); +} + +uint16 LoLEngine::flyingObjectHitMonsters(int x, int y) { + //////////// + // TODO + return 0; +} + +uint16 LoLEngine::flyingObjectHitParty(int x, int y) { + //////////// + // TODO + return 0; +} + +void LoLEngine::updateFlyingObjects(FlyingObject *t) { + int x = 0; + int y = 0; + getNextStepCoords(t->x, t->y, x, y, t->direction); + int objectOnNextBlock = checkBlockBeforeObjectPlacement(x, y, _itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000 ? 256 : 63, t->flags, t->wallFlags); + if (objectOnNextBlock) { + endObjectFlight(t, x, y, objectOnNextBlock); + } else { + if (--t->distance) { + processObjectFlight(t, x, y); + } else { + endObjectFlight(t, x, y, 8); + } + } +} + void LoLEngine::assignItemToBlock(uint16 *assignedBlockObjects, int id) { while (*assignedBlockObjects & 0x8000) { ItemInPlay *tmp = findObject(*assignedBlockObjects); diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 337c3e375d..e17275545d 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; - _throwItemState = 0; + _flyingItems = 0; _monsters = 0; _unkGameFlag = 0; _lastMouseRegion = 0; @@ -296,7 +296,7 @@ LoLEngine::~LoLEngine() { delete[] _lvlShapeBottom; delete[] _lvlShapeLeftRight; delete[] _tempBuffer5120; - delete[] _throwItemState; + delete[] _flyingItems; delete[] _monsters; delete[] _levelBlockProperties; delete[] _monsterProperties; @@ -415,8 +415,8 @@ Common::Error LoLEngine::init() { _tempBuffer5120 = new uint8[5120]; memset(_tempBuffer5120, 0, 5120); - _throwItemState = new ThrownItem[8]; - memset(_throwItemState, 0, 8 * sizeof(ThrownItem)); + _flyingItems = new FlyingObject[8]; + memset(_flyingItems, 0, 8 * sizeof(FlyingObject)); memset(_gameFlags, 0, sizeof(_gameFlags)); memset(_globalScriptVars, 0, sizeof(_globalScriptVars)); @@ -1093,6 +1093,58 @@ int LoLEngine::calculateProtection(int index) { return c; } +void LoLEngine::increaseExperience(int charNum, int skill, uint32 points) { + if (charNum & 0x8000) + return; + + if (_characters[charNum].flags & 8) + return; + + _characters[charNum].experiencePts[skill] += points; + + bool loop = true; + while (loop) { + if (_characters[charNum].experiencePts[skill] <= _expRequirements[_characters[charNum].skillLevels[skill]]) + break; + + _characters[charNum].skillLevels[skill]++; + _characters[charNum].flags |= (0x200 << skill); + int inc = 0; + + switch (skill) { + case 0: + _txt->printMessage(0x8003, getLangString(0x4023), _characters[charNum].name); + inc = _rnd.getRandomNumberRng(4, 6); + _characters[charNum].hitPointsCur += inc; + _characters[charNum].hitPointsMax += inc; + break; + + case 1: + _txt->printMessage(0x8003, getLangString(0x4025), _characters[charNum].name); + inc = _rnd.getRandomNumberRng(2, 6); + _characters[charNum].hitPointsCur += inc; + _characters[charNum].hitPointsMax += inc; + break; + + case 2: + _txt->printMessage(0x8003, getLangString(0x4024), _characters[charNum].name); + inc = (_characters[charNum].defaultModifiers[6] * (_rnd.getRandomNumberRng(1, 8) + 17)) >> 8; + _characters[charNum].magicPointsCur += inc; + _characters[charNum].magicPointsMax += inc; + inc = _rnd.getRandomNumberRng(1, 6); + _characters[charNum].hitPointsCur += inc; + _characters[charNum].hitPointsMax += inc; + break; + + default: + break; + } + + snd_playSoundEffect(118, -1); + gui_drawCharPortraitWithStats(charNum); + } +} + void LoLEngine::setupScreenDims() { if (textEnabled()) { _screen->modifyScreenDim(4, 11, 124, 28, 45); diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 2673afad19..51db2e04e4 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -119,7 +119,7 @@ struct MonsterProperty { struct MonsterInPlay { uint16 nextAssignedObject; uint16 nextDrawObject; - uint8 unk4; + uint8 flyingHeight; uint16 blockPropertyIndex; uint16 x; uint16 y; @@ -153,7 +153,7 @@ struct MonsterInPlay { struct ItemInPlay { uint16 nextAssignedObject; uint16 nextDrawObject; - uint8 unk4; + uint8 flyingHeight; uint16 blockPropertyIndex; uint16 x; uint16 y; @@ -207,20 +207,34 @@ struct ButtonDef { uint16 screenDim; }; -struct ThrownItem { +struct OpenDoorState { + uint16 block; + int8 wall; + int8 state; +}; + +struct FlyingObject { uint8 enable; uint8 a; - uint16 c; + uint16 charNum; uint16 item; uint16 x; uint16 y; - uint8 b; + uint8 flyingHeight; uint8 direction; - int8 field_C; + uint8 distance; int8 field_D; - uint8 charNum; + uint8 c; uint8 flags; - uint8 field_10; + uint8 wallFlags; +}; + +struct FlyingObjectShape { + uint8 shapeFront; + uint8 shapeBack; + uint8 shapeLeft; + uint8 drawFlags; + uint8 flipFlags; }; class LoLEngine : public KyraEngine_v1 { @@ -323,7 +337,7 @@ private: void timerProcessDoors(int timerNum); void timerProcessMonsters(int timerNum); void timerSub3(int timerNum); - void timerSub4(int timerNum); + void timerProcessFlyingObjects(int timerNum); void timerRunSceneAnimScript(int timerNum); void timerSub6(int timerNum); void timerUpdatePortraitAnimations(int skipUpdate); @@ -696,6 +710,8 @@ private: int calculateCharacterStats(int charNum, int index); int calculateProtection(int index); + void increaseExperience(int charNum, int skill, uint32 points); + LoLCharacter *_characters; uint16 _activeCharsXpos[3]; int _updateFlags; @@ -743,7 +759,7 @@ private: void loadLevel(int index); void addLevelItems(); void loadLevelWLL(int index, bool mapShapes); - void moveItemToBlock(uint16 *cmzItemIndex, uint16 item); + void assignBlockObject(uint16 *cmzItemIndex, uint16 item); int assignLevelShapes(int index); uint8 *getLevelShapes(int index); void loadLevelCmzFile(int index); @@ -812,12 +828,6 @@ private: int smoothScrollDrawSpecialShape(int pageNum); void updateAutoMap(int block); - struct OpenDoorState { - uint16 block; - int8 field_2; - int8 state; - }; - OpenDoorState _openDoorState[3]; int _emcDoorState; @@ -959,11 +969,20 @@ private: bool testUnkItemFlags(int itemIndex); void deleteItem(int itemIndex); ItemInPlay *findObject(uint16 index); - void runItemScript(int charNum, int item, int reg0, int reg3, int reg4); + void runItemScript(int charNum, int item, int sub, int next, int reg4); void setHandItem(uint16 itemIndex); - 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 setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b); void pickupItem(int item, int block); + bool throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c); + void endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock); + void processObjectFlight(FlyingObject *t, int x, int y); + void updateObjectFlightPosition(FlyingObject *t); + void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock); + uint16 flyingObjectHitMonsters(int x, int y); + uint16 flyingObjectHitParty(int x, int y); + void updateFlyingObjects(FlyingObject *t); + void assignItemToBlock(uint16 *assignedBlockObjects, int id); int checkDrawObjectSpace(int itemX, int itemY, int partyX, int partyY); int checkSceneForItems(uint16 *blockDrawObjects, int colour); @@ -980,7 +999,7 @@ private: int _hideControls; int _lastCharInventory; - ThrownItem *_throwItemState; + FlyingObject *_flyingItems; EMCData _itemScript; @@ -996,6 +1015,8 @@ private: int _stashSetupDataSize; const int8 *_sceneItemOffs; int _sceneItemOffsSize; + const FlyingObjectShape *_flyingItemShapes; + int _flyingItemShapesSize; // monsters void loadMonsterShapes(const char *file, int monsterIndex, int b); @@ -1006,11 +1027,11 @@ private: int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2); void setMonsterDirection(MonsterInPlay *monster, int dir); void cmzS3(MonsterInPlay *monster); - void removeAssignedItemFromBlock(uint16 *blockItemIndex, int id); - void removeDrawObjectFromBlock(uint16 *blockItemIndex, int id); + void removeAssignedObjectFromBlock(LevelBlockProperty *l, int id); + void removeDrawObjectFromBlock(LevelBlockProperty *l, 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 checkBlockBeforeObjectPlacement(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); @@ -1034,7 +1055,7 @@ private: int getMonsterDistance(uint16 block1, uint16 block2); int walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock); int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk); - void walkMonsterGetNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 unk); + void getNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 direction); MonsterInPlay *_monsters; MonsterProperty *_monsterProperties; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index d4dc4688bf..80f56c81cc 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -236,6 +236,7 @@ enum kKyraResources { kLolMonsterScaleY, kLolMonsterScaleX, kLolMonsterScaleWH, + kLolFlyingObjectShp, kLolInventoryDesc, kLolLevelShpList, @@ -312,6 +313,7 @@ public: const LoLCharacter *loadCharData(int id, int &entries); const SpellProperty *loadSpellData(int id, int &entries); const CompassDef *loadCompassData(int id, int &entries); + const FlyingObjectShape *loadFlyingObjectData(int id, int &entries); const uint16 *loadRawDataBe16(int id, int &entries); const uint32 *loadRawDataBe32(int id, int &entries); const ButtonDef *loadButtonDefs(int id, int &entries); @@ -351,6 +353,7 @@ private: bool loadCharData(const char *filename, void *&ptr, int &size); bool loadSpellData(const char *filename, void *&ptr, int &size); bool loadCompassData(const char *filename, void *&ptr, int &size); + bool loadFlyingObjectData(const char *filename, void *&ptr, int &size); bool loadRawDataBe16(const char *filename, void *&ptr, int &size); bool loadRawDataBe32(const char *filename, void *&ptr, int &size); bool loadButtonDefs(const char *filename, void *&ptr, int &size); @@ -368,6 +371,7 @@ private: void freeCharData(void *&ptr, int &size); void freeSpellData(void *&ptr, int &size); void freeCompassData(void *&ptr, int &size); + void freeFlyingObjectData(void *&ptr, int &size); void freeRawDataBe16(void *&ptr, int &size); void freeRawDataBe32(void *&ptr, int &size); void freeButtonDefs(void *&ptr, int &size); @@ -391,6 +395,7 @@ private: kLolCharData, kLolSpellData, kLolCompassData, + kLolFlightShpData, kLolRawDataBe16, kLolRawDataBe32, kLolButtonData diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 615b40a4c2..705fc042a1 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -105,14 +105,14 @@ void LoLEngine::addLevelItems() { if (_itemsInPlay[i].level != _currentLevel) continue; - moveItemToBlock(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].assignedObjects, i); + assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].assignedObjects, i); _levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].direction = 5; _itemsInPlay[i].nextDrawObject = 0; } } -void LoLEngine::moveItemToBlock(uint16 *cmzItemIndex, uint16 item) { +void LoLEngine::assignBlockObject(uint16 *cmzItemIndex, uint16 item) { ItemInPlay *tmp = 0; while (*cmzItemIndex & 0x8000) { @@ -473,7 +473,7 @@ void LoLEngine::resetItems(int flag) { } if (flag) - memset(_throwItemState, 0, 8 * sizeof(ThrownItem)); + memset(_flyingItems, 0, 8 * sizeof(FlyingObject)); } void LoLEngine::resetLvlBuffer() { @@ -798,7 +798,7 @@ void LoLEngine::openCloseDoor(uint16 block, int openClose) { _openDoorState[s1].block = block; _openDoorState[s1].state = openClose; - _openDoorState[s1].field_2 = c; + _openDoorState[s1].wall = c; flg = (-openClose == 1) ? 0x10 : (-openClose == -1 ? 0x20 : 0); diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 3d20e4112c..e6193c0b4e 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -675,7 +675,7 @@ int LoLEngine::olol_initMonster(EMCState *script) { calcCoordinates(x, y, stackPos(0), stackPos(1), stackPos(2)); uint16 w = _monsterProperties[stackPos(4)].maxWidth; - if (checkBlockBeforeMonsterPlacement(x, y, w, 7, 7)) + if (checkBlockBeforeObjectPlacement(x, y, w, 7, 7)) return -1; for (uint8 i = 0; i < 30; i++) { @@ -698,7 +698,7 @@ int LoLEngine::olol_initMonster(EMCState *script) { l->field_25 = l->properties->unk6[0]; l->field_27 = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1; - l->unk4 = 2; + l->flyingHeight = 2; l->flags = stackPos(5); l->assignedItems = 0; diff --git a/engines/kyra/script_tim.cpp b/engines/kyra/script_tim.cpp index e9b519a8a8..89d32f1de4 100644 --- a/engines/kyra/script_tim.cpp +++ b/engines/kyra/script_tim.cpp @@ -795,7 +795,7 @@ TIMInterpreter_LoL::TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, _dialogueButtonPosX = _dialogueButtonPosY = _dialogueNumButtons = _dialogueButtonXoffs = _dialogueHighlightedButton = 0; } -TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int offscreenBuffer, uint16 wsaFlags) { +TIMInterpreter::Animation *TIMInterpreter_LoL::initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaFlags) { Animation *anim = &_animations[index]; anim->x = x; anim->y = y; diff --git a/engines/kyra/script_tim.h b/engines/kyra/script_tim.h index 668866a2a1..3748867f54 100644 --- a/engines/kyra/script_tim.h +++ b/engines/kyra/script_tim.h @@ -226,7 +226,7 @@ friend class LoLEngine; public: TIMInterpreter_LoL(LoLEngine *engine, Screen_v2 *screen_v2, OSystem *system); - Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int offscreenBuffer, uint16 wsaCopyParams); + Animation *initAnimStruct(int index, const char *filename, int x, int y, int frameDelay, int, uint16 wsaCopyParams); int freeAnimStruct(int index); void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3); diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index 0609c7d00d..52bebab931 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -199,7 +199,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { bool cont = true; int t = monster->blockPropertyIndex; if (monster->blockPropertyIndex) { - removeAssignedItemFromBlock(&_levelBlockProperties[t].assignedObjects, ((uint16)monster->id) | 0x8000); + removeAssignedObjectFromBlock(&_levelBlockProperties[t], ((uint16)monster->id) | 0x8000); _levelBlockProperties[t].direction = 5; checkSceneUpdateNeed(t); } else { @@ -285,7 +285,8 @@ void LoLEngine::cmzS3(MonsterInPlay *l) { // TODO } -void LoLEngine::removeAssignedItemFromBlock(uint16 *blockItemIndex, int id) { +void LoLEngine::removeAssignedObjectFromBlock(LevelBlockProperty *l, int id) { + uint16 *blockItemIndex = &l->assignedObjects; ItemInPlay *i = 0; while (*blockItemIndex) { @@ -301,7 +302,8 @@ void LoLEngine::removeAssignedItemFromBlock(uint16 *blockItemIndex, int id) { } } -void LoLEngine::removeDrawObjectFromBlock(uint16 *blockItemIndex, int id) { +void LoLEngine::removeDrawObjectFromBlock(LevelBlockProperty *l, int id) { + uint16 *blockItemIndex = &l->drawObjects; ItemInPlay *i = 0; while (*blockItemIndex) { @@ -323,7 +325,7 @@ void LoLEngine::assignMonsterToBlock(uint16 *assignedBlockObjects, int id) { *assignedBlockObjects = id; } -int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int testFlag, int wallFlag) { +int LoLEngine::checkBlockBeforeObjectPlacement(int x, int y, int monsterWidth, int testFlag, int wallFlag) { _monsterLastWalkDirection = 0; int x2 = 0; int y2 = 0; @@ -504,27 +506,67 @@ void LoLEngine::drawBlockObjects(int blockArrayIndex) { int fx = _sceneItemOffs[s & 7] << 1; int fy = _sceneItemOffs[(s >> 1) & 7] + 5; - if (i->unk4 > 2 || (i->unk4 == 2 && blockArrayIndex >= 15)) { + if (i->flyingHeight >= 2 && blockArrayIndex >= 15) { s = i->nextDrawObject; continue; } uint8 *shp = 0; - int flg = 0; + uint16 flg = 0; - if (i->unk4 >= 2) - fy -= ((i->unk4 - 1) * 6); + if (i->flyingHeight >= 2) + fy -= ((i->flyingHeight - 1) * 6); if ((_itemProperties[i->itemPropertyIndex].flags & 0x1000) && !(i->shpCurFrame_flg & 0xC000)) { - i = i; - //////////// - // TODO + int shpIndex = _itemProperties[i->itemPropertyIndex].flags & 0x800 ? 7 : _itemProperties[i->itemPropertyIndex].shpIndex; + + int ii = 0; + for (; ii < 8; ii++) { + if (!_flyingItems[ii].enable) + continue; + + if (_flyingItems[ii].item == s) + break; + } + + if (_flyingItemShapes[shpIndex].flipFlags && ((i->x ^ i->y) & 0x20)) + flg |= 0x20; + + flg |= _flyingItemShapes[shpIndex].drawFlags; + + if (ii != 8) { + switch (_currentDirection - (_flyingItems[ii].direction >> 1) + 3) { + case 1: + case 5: + shpIndex = _flyingItemShapes[shpIndex].shapeFront; + break; + case 3: + shpIndex = _flyingItemShapes[shpIndex].shapeBack; + break; + case 2: + case 6: + flg |= 0x10; + case 0: + case 4: + shpIndex = _flyingItemShapes[shpIndex].shapeLeft; + break; + default: + break; + } + + shp = _thrownShapes[shpIndex]; + } + + if (shp) + fy += (shp[2] >> 2); + } 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); + if (shp) + drawItemOrMonster(shp, 0, i->x, i->y, fx, fy, flg, -1, false); s = i->nextDrawObject; } } @@ -705,8 +747,8 @@ void LoLEngine::redrawSceneItem() { 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); + if (item->flyingHeight > 1) + fy -= ((item->flyingHeight - 1) * 6); uint8 *shp = (_itemProperties[item->itemPropertyIndex].flags & 0x40) ? _gameShapes[_itemProperties[item->itemPropertyIndex].shpIndex] : _itemShapes[_gameShapeMap[_itemProperties[item->itemPropertyIndex].shpIndex << 1]]; @@ -732,7 +774,7 @@ int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) { if (y < 0) y = 0; - int res = (i->unk4 << 12); + int res = (i->flyingHeight << 12); res |= (4095 - y); return res; @@ -1040,7 +1082,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) { int fx = 0; int fy = 0; - walkMonsterGetNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _monsterLastWalkDirection : s); + getNextStepCoords(monster->x, monster->y, fx, fy, (s == -1) ? _monsterLastWalkDirection : s); placeMonster(monster, fx, fy); } @@ -1075,7 +1117,7 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) { int fx = 0; int fy = 0; - walkMonsterGetNextStepCoords(sx, sy, fx, fy, s); + getNextStepCoords(sx, sy, fx, fy, s); d = walkMonsterCheckDest(fx, fy, monster, 4); if (!d) @@ -1149,18 +1191,18 @@ int LoLEngine::walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int un uint8 m = monster->mode; monster->mode = 15; - int res = checkBlockBeforeMonsterPlacement(x, y, monster->properties->maxWidth, 7, monster->properties->flags & 0x1000 ? 32 : unk); + int res = checkBlockBeforeObjectPlacement(x, y, monster->properties->maxWidth, 7, monster->properties->flags & 0x1000 ? 32 : unk); monster->mode = m; return res; } -void LoLEngine::walkMonsterGetNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY, uint16 unk) { +void LoLEngine::getNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY, uint16 direction) { static const int8 shiftTableX[] = { 0, 32, 32, 32, 0, -32, -32, -32 }; static const int8 shiftTableY[] = { -32, -32, 0, 32, 32, 32, 0, -32 }; - newX = (srcX + shiftTableX[unk]) & 0x1fff; - newY = (srcY + shiftTableY[unk]) & 0x1fff; + newX = (srcX + shiftTableX[direction]) & 0x1fff; + newY = (srcY + shiftTableY[direction]) & 0x1fff; } } // end of namespace Kyra diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 724fe872d1..3442ba3ced 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 42 +#define RESFILE_VERSION 43 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -226,6 +226,7 @@ bool StaticResource::init() { { kLolCharData, proc(loadCharData), proc(freeCharData) }, { kLolSpellData, proc(loadSpellData), proc(freeSpellData) }, { kLolCompassData, proc(loadCompassData), proc(freeCompassData) }, + { kLolFlightShpData, proc(loadFlyingObjectData), proc(freeFlyingObjectData) }, { kLolRawDataBe16, proc(loadRawDataBe16), proc(freeRawDataBe16) }, { kLolRawDataBe32, proc(loadRawDataBe32), proc(freeRawDataBe32) }, { kLolButtonData, proc(loadButtonDefs), proc(freeButtonDefs) }, @@ -397,6 +398,7 @@ bool StaticResource::init() { { kLolMonsterScaleY, kRawData, "MONSTZY.DEF" }, { kLolMonsterScaleX, kRawData, "MONSTZX.DEF" }, { kLolMonsterScaleWH, kLolRawDataBe16, "MONSTSCL.DEF" }, + { kLolFlyingObjectShp, kLolFlightShpData, "THRWNSHP.DEF" }, { kLolInventoryDesc, kLolRawDataBe16, "INVDESC.DEF" }, { kLolLevelShpList, kStringList, "SHPFILES.TXT" }, @@ -521,6 +523,10 @@ const CompassDef *StaticResource::loadCompassData(int id, int &entries) { return (const CompassDef*)getData(id, kLolCompassData, entries); } +const FlyingObjectShape *StaticResource::loadFlyingObjectData(int id, int &entries) { + return (const FlyingObjectShape*)getData(id, kLolFlightShpData, entries); +} + const uint16 *StaticResource::loadRawDataBe16(int id, int &entries) { return (const uint16*)getData(id, kLolRawDataBe16, entries); } @@ -1073,6 +1079,29 @@ bool StaticResource::loadCompassData(const char *filename, void *&ptr, int &size return true; } +bool StaticResource::loadFlyingObjectData(const char *filename, void *&ptr, int &size) { + Common::SeekableReadStream *file = getFile(filename); + + if (!file) + return false; + + size = file->size() / 5; + FlyingObjectShape *defs = new FlyingObjectShape[size]; + + for (int i = 0; i < size; i++) { + FlyingObjectShape *t = &defs[i]; + t->shapeFront = file->readByte(); + t->shapeBack = file->readByte(); + t->shapeLeft = file->readByte(); + t->drawFlags = file->readByte(); + t->flipFlags = file->readByte(); + }; + + ptr = defs; + + return true; +} + bool StaticResource::loadRawDataBe16(const char *filename, void *&ptr, int &size) { Common::SeekableReadStream *file = getFile(filename); @@ -1227,6 +1256,14 @@ void StaticResource::freeCompassData(void *&ptr, int &size) { size = 0; } +void StaticResource::freeFlyingObjectData(void *&ptr, int &size) { + FlyingObjectShape *d = (FlyingObjectShape *)ptr; + delete[] d; + ptr = 0; + size = 0; +} + + void StaticResource::freeRawDataBe16(void *&ptr, int &size) { uint16 *data = (uint16*)ptr; delete[] data; @@ -1771,6 +1808,7 @@ void LoLEngine::initStaticResource() { _levelShpList = _staticres->loadStrings(kLolLevelShpList, _levelShpListSize); _levelDatList = _staticres->loadStrings(kLolLevelDatList, _levelDatListSize); _compassDefs = _staticres->loadCompassData(kLolCompassDefs, _compassDefsSize); + _flyingItemShapes = _staticres->loadFlyingObjectData(kLolFlyingObjectShp, _flyingItemShapesSize); _itemCost = _staticres->loadRawDataBe16(kLolItemPrices, _itemCostSize); _stashSetupData = _staticres->loadRawData(kLolStashSetup, _stashSetupDataSize); diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index 30ef9d6a26..96344b0472 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -41,7 +41,7 @@ void LoLEngine::setupTimers() { _timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true); _timer->setNextRun(0x11, _system->getMillis() + 3 * _tickLength); _timer->addTimer(3, TimerV2(timerSub3), 15, true); - _timer->addTimer(4, TimerV2(timerSub4), 1, true); + _timer->addTimer(4, TimerV2(timerProcessFlyingObjects), 1, true); _timer->addTimer(0x50, TimerV2(timerRunSceneAnimScript), 0, false); _timer->addTimer(0x51, TimerV2(timerRunSceneAnimScript), 0, false); _timer->addTimer(0x52, TimerV2(timerRunSceneAnimScript), 0, false); @@ -79,7 +79,7 @@ void LoLEngine::timerProcessDoors(int timerNum) { continue; int v = _openDoorState[i].state; - int c = _openDoorState[i].field_2; + int c = _openDoorState[i].wall; _levelBlockProperties[b].walls[c] += v; _levelBlockProperties[b].walls[c ^ 2] += v; @@ -115,8 +115,12 @@ void LoLEngine::timerSub3(int timerNum) { } -void LoLEngine::timerSub4(int timerNum) { - +void LoLEngine::timerProcessFlyingObjects(int timerNum) { + for (int i = 0; i < 8; i++) { + if (!_flyingItems[i].enable) + continue; + updateFlyingObjects(&_flyingItems[i]); + } } void LoLEngine::timerRunSceneAnimScript(int timerNum) { diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp index 178cab0929..623be1aaeb 100644 --- a/tools/create_kyradat/create_kyradat.cpp +++ b/tools/create_kyradat/create_kyradat.cpp @@ -31,7 +31,7 @@ #include "md5.h" enum { - kKyraDatVersion = 42, + kKyraDatVersion = 43, kIndexSize = 12 }; @@ -291,6 +291,7 @@ const ExtractFilename extractFilenames[] = { { lolMonsterScaleY, kTypeRawData, "MONSTZY.DEF" }, { lolMonsterScaleX, kTypeRawData, "MONSTZX.DEF" }, { lolMonsterScaleWH, lolTypeRaw16, "MONSTSCL.DEF" }, + { lolFlyingItemShp, k3TypeRaw16to8, "THRWNSHP.DEF" }, { lolInventoryDesc, lolTypeRaw16, "INVDESC.DEF" }, { lolLevelShpList, kTypeStringList, "SHPFILES.TXT" }, { lolLevelDatList, kTypeStringList, "DATFILES.TXT" }, diff --git a/tools/create_kyradat/create_kyradat.h b/tools/create_kyradat/create_kyradat.h index ee83bcfa5c..048391d631 100644 --- a/tools/create_kyradat/create_kyradat.h +++ b/tools/create_kyradat/create_kyradat.h @@ -200,6 +200,7 @@ enum kExtractID { lolMonsterScaleY, lolMonsterScaleX, lolMonsterScaleWH, + lolFlyingItemShp, lolInventoryDesc, lolLevelShpList, diff --git a/tools/create_kyradat/lol_cd.h b/tools/create_kyradat/lol_cd.h index b7f80d075e..420a7bb55a 100644 --- a/tools/create_kyradat/lol_cd.h +++ b/tools/create_kyradat/lol_cd.h @@ -22,7 +22,8 @@ const ExtractEntry lolCDFile2[] = { { lolMonsterDirFlags, 0x00031FFF, 0x0003200F }, { lolMonsterScaleY, 0x00031BC0, 0x00031BDE }, { lolMonsterScaleX, 0x00031BDE, 0x00031BFE }, - { lolMonsterScaleWH, 0x000285C0, 0x00028644 }, + { lolMonsterScaleWH, 0x000285C0, 0x00028642 }, + { lolFlyingItemShp, 0x00028642, 0x000286C4 }, { lolInventoryDesc, 0x00032706, 0x0003271C }, { lolLevelShpList, 0x00032826, 0x000328A5 }, diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h index 51f3246775..8f0d0b6316 100644 --- a/tools/create_kyradat/misc.h +++ b/tools/create_kyradat/misc.h @@ -506,6 +506,7 @@ const int lolCDFile2Need[] = { lolMonsterScaleY, lolMonsterScaleX, lolMonsterScaleWH, + lolFlyingItemShp, lolInventoryDesc, lolLevelShpList, |