From 7ea5cefef4fb1ef9db52cbf5df7f884770113684 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sun, 1 Mar 2009 14:45:30 +0000 Subject: LOL: implemented some monster related code (monsters now get placed in the maze, but they still don't do anything) svn-id: r39039 --- dists/engine-data/kyra.dat | Bin 255891 -> 256287 bytes engines/kyra/gui_lol.cpp | 10 +- engines/kyra/items_lol.cpp | 34 +- engines/kyra/lol.cpp | 40 +- engines/kyra/lol.h | 149 +++-- engines/kyra/module.mk | 1 + engines/kyra/resource.h | 6 + engines/kyra/scene_lol.cpp | 433 ++------------- engines/kyra/screen.cpp | 21 +- engines/kyra/screen.h | 2 + engines/kyra/script_lol.cpp | 141 ++++- engines/kyra/sprites_lol.cpp | 942 ++++++++++++++++++++++++++++++++ engines/kyra/staticres.cpp | 18 +- engines/kyra/timer_lol.cpp | 10 +- tools/create_kyradat/create_kyradat.cpp | 8 +- tools/create_kyradat/create_kyradat.h | 6 + tools/create_kyradat/lol_cd.h | 6 + tools/create_kyradat/misc.h | 6 + 18 files changed, 1333 insertions(+), 500 deletions(-) create mode 100644 engines/kyra/sprites_lol.cpp diff --git a/dists/engine-data/kyra.dat b/dists/engine-data/kyra.dat index 0ad8f84071..d4967caa17 100644 Binary files a/dists/engine-data/kyra.dat and b/dists/engine-data/kyra.dat differ diff --git a/engines/kyra/gui_lol.cpp b/engines/kyra/gui_lol.cpp index 81f65c0a9d..34ae13b000 100644 --- a/engines/kyra/gui_lol.cpp +++ b/engines/kyra/gui_lol.cpp @@ -1304,7 +1304,7 @@ int LoLEngine::clickedInventoryScroll(Button *button) { return 1; } -int LoLEngine::clickedScenePressSwitch(Button *button) { +int LoLEngine::clickedWall(Button *button) { int block = calcNewBlockPosition(_currentBlock, _currentDirection); int dir = _currentDirection ^ 2; uint8 type = _wllBuffer3[_levelBlockProperties[block].walls[dir]]; @@ -1312,23 +1312,27 @@ int LoLEngine::clickedScenePressSwitch(Button *button) { int res = 0; switch (type) { case 1: - res = clickedDecoration(block, dir); + res = clickedWallShape(block, dir); break; case 2: + res = clicked2(block, dir); break; case 3: + res = clicked3(block, dir); break; case 4: + res = clickedWallOnlyScript(block); break; case 5: - res = switchOpenDoor(block, dir); + res = clickedDoorSwitch(block, dir); break; case 6: + res = clicked6(block, dir); break; default: diff --git a/engines/kyra/items_lol.cpp b/engines/kyra/items_lol.cpp index 741cb20d6d..7c584f7738 100644 --- a/engines/kyra/items_lol.cpp +++ b/engines/kyra/items_lol.cpp @@ -96,7 +96,7 @@ int LoLEngine::makeItem(int itemIndex, int curFrame, int flags) { if (t) break; else - ii = _itemsInPlay[ii - 1].itemIndexUnk; + ii = _itemsInPlay[ii - 1].next; } if (t) { @@ -109,22 +109,22 @@ int LoLEngine::makeItem(int itemIndex, int curFrame, int flags) { if (cnt) { slot = r; if (testUnkItemFlags(r)) { - if (_itemsInPlay[r].itemIndexUnk) - _itemsInPlay[_itemsInPlay[r].itemIndexUnk].level = _itemsInPlay[r].level; + if (_itemsInPlay[r].next) + _itemsInPlay[_itemsInPlay[r].next].level = _itemsInPlay[r].level; deleteItem(r); slot = r; } else { - int ii = _itemsInPlay[slot].itemIndexUnk; + int ii = _itemsInPlay[slot].next; while (ii) { if (testUnkItemFlags(ii)) { - _itemsInPlay[slot].itemIndexUnk = _itemsInPlay[ii].itemIndexUnk; + _itemsInPlay[slot].next = _itemsInPlay[ii].next; deleteItem(ii); slot = ii; break; } else { slot = ii; } - ii = _itemsInPlay[slot].itemIndexUnk; + ii = _itemsInPlay[slot].next; } } } @@ -154,11 +154,11 @@ void LoLEngine::deleteItem(int itemIndex) { _itemsInPlay[itemIndex].shpCurFrame_flg |= 0x8000; } -MonsterInPlay *LoLEngine::findItem(uint16 index) { +ItemInPlay *LoLEngine::findItem(uint16 index) { if (index & 0x8000) - return &_monsters[index & 0x7fff]; + return (ItemInPlay *)&_monsters[index & 0x7fff]; else - return (MonsterInPlay *)&_itemsInPlay[index]; + return &_itemsInPlay[index]; } void LoLEngine::runItemScript(int charNum, int item, int reg0, int reg3, int reg4) { @@ -225,7 +225,7 @@ void LoLEngine::clickSceneSub1() { ItemInPlay *item = &_itemsInPlay[s]; if (item->shpCurFrame_flg & 0x4000) { - if (clickSceneSub1Sub1(item->x, item->y, _partyPosX, _partyPosY) > 319) + if (checkMonsterSpace(item->x, item->y, _partyPosX, _partyPosY) > 319) break; int w = sceneItemWidth[s & 7] << 1; @@ -236,7 +236,7 @@ void LoLEngine::clickSceneSub1() { uint8 shpIx = _itemProperties[item->itemPropertyIndex].shpIndex; uint8 *shp = (_itemProperties[item->itemPropertyIndex].flags & 0x40) ? _gameShapes[shpIx] : _itemShapes[_gameShapeMap[shpIx]]; - drawSceneItem(shp, 0, item->x, item->y, w, h, 0, t, 0); + drawItemOrMonster(shp, 0, item->x, item->y, w, h, 0, t, 0); } s = item->unk2; @@ -246,8 +246,16 @@ void LoLEngine::clickSceneSub1() { } } -int LoLEngine::clickSceneSub1Sub1(int itemX, int itemY, int partyX, int partyY) { - return 1; +int LoLEngine::checkMonsterSpace(int itemX, int itemY, int partyX, int partyY) { + int a = itemX - partyX; + if (a < 0) + a = -a; + + int b = itemY - partyY; + if (b < 0) + b = -b; + + return a + b; } int LoLEngine::checkSceneForItems(LevelBlockProperty *block, int pos) { diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 7ee1a32c85..96fddd8660 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -89,7 +89,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _itemIconShapes = _itemShapes = _gameShapes = _thrownShapes = _iceShapes = _fireballShapes = 0; _levelShpList = _levelDatList = 0; _monsterShapes = _monsterPalettes = 0; - _buf4 = 0; + _monsterShapesEx = 0; _gameShapeMap = 0; memset(_monsterUnk, 0, 3); @@ -111,7 +111,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy _buttonPressTimer = 0; _selectedCharacter = 0; _unkFlag = 0; - _scriptBoolSkipExec = _sceneUpdateRequired = false; + _suspendScript = _sceneUpdateRequired = false; _scriptDirection = 0; _currentDirection = 0; _currentBlock = 0; @@ -259,10 +259,10 @@ LoLEngine::~LoLEngine() { delete[] _monsterPalettes[i]; delete[] _monsterPalettes; } - if (_buf4) { - for (int i = 0; i < 384; i++) - delete[] _buf4[i]; - delete[] _buf4; + if (_monsterShapesEx) { + for (int i = 0; i < 576; i++) + delete[] _monsterShapesEx[i]; + delete[] _monsterShapesEx; } for (Common::Array::iterator i = _timIntroOpcodes.begin(); i != _timIntroOpcodes.end(); ++i) @@ -417,8 +417,8 @@ Common::Error LoLEngine::init() { _monsterPalettes = new uint8*[48]; memset(_monsterPalettes, 0, 48 * sizeof(uint8*)); - _buf4 = new uint8*[384]; - memset(_buf4, 0, 384 * sizeof(uint8*)); + _monsterShapesEx = new uint8*[576]; + memset(_monsterShapesEx, 0, 576 * sizeof(uint8*)); memset(&_scriptData, 0, sizeof(EMCData)); _levelFlagUnk = 0; @@ -1501,6 +1501,25 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str return 1; } +void LoLEngine::cmzS7(int a, int block) { + if (!(_unkGameFlag & 1)) + return; + + // TODO +} + +void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) { + uint16 *c = &monster->assignedItems; + while (*c) + c = &_itemsInPlay[*c].next; + *c = item; + _itemsInPlay[item].next = 0; +} + +const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) { + return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->pos : _characters[id].defaultModifiers; +} + void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) { uint32 endTime = _system->getMillis() + millis; while (endTime > _system->getMillis()) { @@ -1514,11 +1533,6 @@ void LoLEngine::runLoopSub4(int a) { cmzS7(a, _currentBlock); } -void LoLEngine::calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs) { - x = (block & 0x1f) << 8 | xOffs; - y = ((block & 0xffe0) << 3) | yOffs; -} - bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) { if (_spellProperties[spellNum].mpRequired[spellLevel] > _characters[charNum].magicPointsCur) { if (characterSays(0x4043, _characters[charNum].id, true)) diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index 63b8a47d20..23ae1831df 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -93,14 +93,14 @@ struct SpellProperty { struct LevelBlockProperty { uint8 walls[4]; - uint16 itemIndex; + uint16 itemMonsterIndex; uint16 field_6; - uint8 field_8; + uint8 direction; uint8 flags; }; struct MonsterProperty { - uint8 id; + uint8 shapeIndex; uint8 maxWidth; uint16 field2[2]; uint16 protection; @@ -111,14 +111,15 @@ struct MonsterProperty { uint16 itemProtection; uint16 might; uint8 b; - uint16 unk5[2]; + uint16 flags; + uint16 unk5; uint16 unk6[5]; uint8 unk7[4]; uint8 unk8[3]; }; struct MonsterInPlay { - uint16 itemIndexUnk; + uint16 next; uint16 unk2; uint8 unk4; uint16 blockPropertyIndex; @@ -128,34 +129,31 @@ struct MonsterInPlay { uint16 itemPosX; uint16 itemPosY; uint8 field10; - uint16 anon8; + uint8 anon8; + uint8 anonh; uint8 anon9; - uint8 field_14; + uint8 mode; uint8 field_15; - uint8 field_16; + uint8 id; uint8 field_17; - uint8 field_18; - uint16 field_19; + uint8 facing; + uint16 flags; uint8 field_1B; uint8 field_1C; - int16 monsterMight; + int16 might; uint8 field_1F; uint8 type; MonsterProperty *properties; uint8 field_25; uint8 field_26; uint8 field_27; - uint16 itix; - uint8 field_2A; - uint8 field_2B; - uint16 field_2C; - uint8 field_2D; - uint8 field_2E; + uint16 assignedItems; + uint8 field_2A[4]; }; struct ItemInPlay { - uint16 itemIndexUnk; + uint16 next; uint16 unk2; uint8 unk4; uint16 blockPropertyIndex; @@ -165,7 +163,8 @@ struct ItemInPlay { uint16 itemPropertyIndex; uint16 shpCurFrame_flg; uint8 field10; - uint16 anon8; + uint8 anon8; + uint8 anonh; uint8 anon9; }; @@ -310,7 +309,7 @@ private: void enableTimer(int id); void timerProcessOpenDoor(int timerNum); - void timerSub2(int timerNum); + void timerProcessMonsters(int timerNum); void timerSub3(int timerNum); void timerSub4(int timerNum); void timerSub5(int timerNum); @@ -434,7 +433,7 @@ private: int clickedScenePickupItem(Button *button); int clickedInventorySlot(Button *button); int clickedInventoryScroll(Button *button); - int clickedScenePressSwitch(Button *button); + int clickedWall(Button *button); int clickedScene(Button *button); int clickedScroll(Button *button); int clickedUnk23(Button *button); @@ -474,14 +473,14 @@ private: TextDisplayer_LoL *_txt; // emc scripts - void runInitScript(const char *filename, int func); + void runInitScript(const char *filename, int optionalFunc); void runInfScript(const char *filename); void runLevelScript(int block, int sub); void runLevelScriptCustom(int block, int sub, int charNum, int item, int reg3, int reg4); - bool checkScriptUnk(int func); + bool checkSceneUpdateNeed(int func); EMCData _scriptData; - bool _scriptBoolSkipExec; + bool _suspendScript; uint16 _scriptDirection; uint16 _currentDirection; uint16 _currentBlock; @@ -515,6 +514,7 @@ private: int olol_setGlobalVar(EMCState *script); int olol_mapShapeToBlock(EMCState *script); int olol_resetBlockShapeAssignment(EMCState *script); + int olol_initMonster(EMCState *script); int olol_loadMonsterProperties(EMCState *script); int olol_68(EMCState *script); int olol_setScriptTimer(EMCState *script); @@ -523,14 +523,16 @@ private: int olol_releaseTimScript(EMCState *script); int olol_initDialogueSequence(EMCState *script); int olol_restoreSceneAfterDialogueSequence(EMCState *script); - int olol_85(EMCState *script); + int olol_giveItemToMonster(EMCState *script); int olol_loadLangFile(EMCState *script); + int olol_playSoundEffect(EMCState *script); int olol_stopTimScript(EMCState *script); int olol_playCharacterScriptChat(EMCState *script); int olol_loadSoundFile(EMCState *script); int olol_setPaletteBrightness(EMCState *script); + int olol_printMessage(EMCState *script); int olol_playDialogueTalkText(EMCState *script); - int olol_checkDialogueState(EMCState *script); + int olol_checkForMonsterMode1(EMCState *script); int olol_setNextFunc(EMCState *script); int olol_setDoorState(EMCState *script); int olol_assignCustomSfx(EMCState *script); @@ -627,14 +629,8 @@ private: int _loadLevelFlag; int _levelFlagUnk; int _unkCharNum; - int _charStatsTemp[5]; - uint8 **_monsterShapes; - uint8 **_monsterPalettes; - uint8 **_buf4; - uint8 _monsterUnk[3]; - const LoLCharacter *_charDefaults; int _charDefaultsSize; @@ -663,16 +659,6 @@ private: // level void loadLevel(int index); void addLevelItems(); - int initCmzWithScript(int block); - void initCMZ1(MonsterInPlay *l, int a); - void initCMZ2(MonsterInPlay *l, uint16 a, uint16 b); - int cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2); - void cmzS2(MonsterInPlay *l, int a); - void cmzS3(MonsterInPlay *l); - void cmzS4(uint16 &itemIndex, int a); - int cmzS5(uint16 a, uint16 b); - void cmzS6(uint16 &itemIndex, int a); - void cmzS7(int a, int block); void loadLevelWLL(int index, bool mapShapes); void moveItemToBlock(uint16 *cmzItemIndex, uint16 item); int assignLevelShapes(int index); @@ -680,8 +666,6 @@ private: void loadLevelCmzFile(int index); void loadCMZ_Sub(int index1, int index2); void loadCmzFile(const char *file); - void loadMonsterShapes(const char *file, int monsterIndex, int b); - void releaseMonsterShapes(int monsterIndex); void loadLevelShpDat(const char *shpFile, const char *datFile, bool flag); void loadLevelGraphics(const char *file, int specialColor, int weight, int vcnLen, int vmpLen, const char *palFile); @@ -706,10 +690,6 @@ private: void drawLevelModifyScreenDim(int dim, int16 x1, int16 y1, int16 x2, int16 y2); void drawDecorations(int index); void drawIceShapes(int index, int iceShapeIndex); - void drawMonstersAndItems(int block); - 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); - void drawSceneItem(uint8 *shape, uint8 *ovl, int x, int y, int w, int h, int flags, int unk1, int unk2); void drawScriptShapes(int pageNum); void updateSceneWindow(); @@ -719,12 +699,19 @@ private: void updateCompass(); void moveParty(uint16 direction, int unk1, int unk2, int buttonShape); - uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction); bool checkBlockPassability(uint16 block, uint16 direction); void notifyBlockNotPassable(int scrollFlag); - int clickedDecoration(uint16 block, uint16 direction); - int switchOpenDoor(uint16 block, uint16 direction); + uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction); + uint16 calcBlockIndex(uint16 x, uint16 y); + void calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs); + + int clickedWallShape(uint16 block, uint16 direction); + int clicked2(uint16 block, uint16 direction); + int clicked3(uint16 block, uint16 direction); + int clickedWallOnlyScript(uint16 block); + int clickedDoorSwitch(uint16 block, uint16 direction); + int clicked6(uint16 block, uint16 direction); bool clickedShape(int shapeIndex); void openDoorSub1(uint16 block, int unk); @@ -800,8 +787,6 @@ private: LevelBlockProperty *_levelBlockProperties; LevelBlockProperty *_curBlockCaps[18]; - MonsterInPlay *_monsters; - MonsterProperty *_monsterProperties; uint16 _partyPosX; uint16 _partyPosY; @@ -880,11 +865,11 @@ private: int makeItem(int itemIndex, int curFrame, int flags); bool testUnkItemFlags(int itemIndex); void deleteItem(int itemIndex); - MonsterInPlay *findItem(uint16 index); + ItemInPlay *findItem(uint16 index); void runItemScript(int charNum, int item, int reg0, int reg3, int reg4); void setHandItem(uint16 itemIndex); void clickSceneSub1(); - int clickSceneSub1Sub1(int itemX, int itemY, int partyX, int partyY); + int checkMonsterSpace(int itemX, int itemY, int partyX, int partyY); int checkSceneForItems(LevelBlockProperty *block, int pos); void foundItemSub(int item, int block); @@ -910,10 +895,62 @@ private: const uint16 *_inventorySlotDesc; int _inventorySlotDescSize; + // monsters + void loadMonsterShapes(const char *file, int monsterIndex, int b); + void releaseMonsterShapes(int monsterIndex); + int placeMonstersUnk(int block); + void setMonsterMode(MonsterInPlay *monster, int a); + void placeMonster(MonsterInPlay *monster, uint16 x, uint16 y); + int cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2); + void cmzS2(MonsterInPlay *monster, int a); + void cmzS3(MonsterInPlay *monster); + void removeItemOrMonsterFromBlock(uint16 *blockItemIndex, int id); + void assignItemOrMonsterToBlock(uint16 *blockItemIndex, int id); + void cmzS7(int a, int block); + void giveItemToMonster(MonsterInPlay *monster, uint16 a); + int checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int p1, int p2); + int calcMonsterSkillLevel(int id, int a); + int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int p1, int p2); + bool checkBlockOccupiedByParty(int x, int y, int p1); + const uint16 *getCharacterOrMonsterStats(int id); + void drawMonstersAndItems(int block); + void drawMonster(uint16 id); + int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags); + void recalcItemMonsterPositions(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag); + 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); + + void updateMonster(MonsterInPlay *monster); + void moveMonster(MonsterInPlay *monster); + void shiftMonster(MonsterInPlay *monster); + + MonsterInPlay *_monsters; + MonsterProperty *_monsterProperties; + uint8 **_monsterShapes; + uint8 **_monsterPalettes; + uint8 **_monsterShapesEx; + uint8 _monsterUnk[3]; + + const uint16 *_monsterModifiers; + int _monsterModifiersSize; + const int8 *_monsterLevelOffs; + int _monsterLevelOffsSize; + const uint8 *_monsterDirFlags; + int _monsterDirFlagsSize; + const int8 *_monsterScaleX; + int _monsterScaleXSize; + const int8 *_monsterScaleY; + int _monsterScaleYSize; + const uint16 *_monsterScaleWH; + int _monsterScaleWHSize; + // misc void delay(uint32 millis, bool cUpdate = false, bool isMainLoop = false); void runLoopSub4(int a); - void calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs); uint8 *_pageBuffer1; uint8 *_pageBuffer2; diff --git a/engines/kyra/module.mk b/engines/kyra/module.mk index f83b936092..b5c62ab394 100644 --- a/engines/kyra/module.mk +++ b/engines/kyra/module.mk @@ -63,6 +63,7 @@ MODULE_OBJS := \ sound.o \ sound_lok.o \ sprites.o \ + sprites_lol.o \ staticres.o \ text.o \ text_lok.o \ diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index d28001d893..d48b590792 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -228,6 +228,12 @@ enum kKyraResources { //lolCharDefsUnk, lolCharDefsAkshel, lolExpRequirements, + lolMonsterModifiers, + lolMonsterLevelOffsets, + lolMonsterDirFlags, + lolMonsterScaleY, + lolMonsterScaleX, + lolMonsterScaleWH, lolInventoryDesc, lolLevelShpList, diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 7c34bdc945..7922345973 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -71,7 +71,7 @@ void LoLEngine::loadLevel(int index) { char filename[13]; snprintf(filename, sizeof(filename), "LEVEL%d.INI", index); - int f = _levelFlagUnk & (1 << ((index + 0xff) & 0xff)); + int f = _levelFlagUnk & (1 << (index - 1)); runInitScript(filename, f ? 0 : 1); @@ -82,7 +82,7 @@ void LoLEngine::loadLevel(int index) { runInfScript(filename); addLevelItems(); - initCmzWithScript(_currentBlock); + placeMonstersUnk(_currentBlock); _screen->generateGrayOverlay(_screen->_currentPalette, _screen->_grayOverlay,32, 16, 0, 0, 128, true); @@ -103,186 +103,19 @@ void LoLEngine::addLevelItems() { if (_itemsInPlay[i].level != _currentLevel) continue; - moveItemToBlock(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].itemIndex, i); + moveItemToBlock(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].itemMonsterIndex, i); - _levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].field_8 = 5; + _levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].direction = 5; _itemsInPlay[i].unk2 = 0; } } -int LoLEngine::initCmzWithScript(int block) { - int i = _levelBlockProperties[block].itemIndex; - int cnt = 0; - MonsterInPlay *t = 0; - - while (i) { - t = findItem(i); - i = t->itemIndexUnk; - if (!(i & 0x8000)) - continue; - - i &= 0x7fff; - t = &_monsters[i]; - - cnt++; - initCMZ1(t, 14); - - checkScriptUnk(t->blockPropertyIndex); - - initCMZ2(t, 0, 0); - } - return cnt; -} - -void LoLEngine::initCMZ1(MonsterInPlay *l, int a) { - if (l->field_14 == 13 && a != 14) - return; - if (a == 7) { - l->itemPosX = _partyPosX; - l->itemPosY = _partyPosX; - } - - if (l->field_14 == 1 && a == 7) { - for (int i = 0; i < 30; i++) { - if (l->field_14 != 1) - continue; - l->field_14 = a; - l->field_15 = 0; - l->itemPosX = _partyPosX; - l->itemPosY = _partyPosY; - cmzS2(l, cmzS1(l->x, l->y, l->itemPosX, l->itemPosY)); - } - } else { - l->field_14 = a; - l->field_15 = 0; - if (a == 14) - l->monsterMight = 0; - if (a == 13 && (l->field_19 & 0x20)) { - l->field_14 = 0; - cmzS3(l); - if (_currentLevel != 29) - initCMZ1(l, 14); - runLevelScriptCustom(0x404, -1, l->field_16, l->field_16, 0, 0); - checkScriptUnk(l->blockPropertyIndex); - if (l->field_14 == 14) - initCMZ2(l, 0, 0); - } - } - -} - -void LoLEngine::initCMZ2(MonsterInPlay *l, uint16 a, uint16 b) { - bool cont = true; - int t = l->blockPropertyIndex; - if (l->blockPropertyIndex) { - cmzS4(_levelBlockProperties[l->blockPropertyIndex].itemIndex, ((uint16)l->field_16) | 0x8000); - _levelBlockProperties[l->blockPropertyIndex].field_8 = 5; - checkScriptUnk(l->blockPropertyIndex); - } else { - cont = false; - } - - l->blockPropertyIndex = cmzS5(a, b); - - if (l->x != a || l->y != b) { - l->x = a; - l->y = b; - l->anon9 = (++l->anon9) & 3; - } - - if (l->blockPropertyIndex == 0) - return; - - cmzS6(_levelBlockProperties[l->blockPropertyIndex].itemIndex, ((uint16)l->field_16) | 0x8000); - _levelBlockProperties[l->blockPropertyIndex].field_8 = 5; - checkScriptUnk(l->blockPropertyIndex); - - if (l->properties->unk8[0] == 0 || cont == false) - return; - - if ((!(l->properties->unk5[0] & 0x100) || ((l->anon9 & 1) == 0)) && l->blockPropertyIndex == t) - return; - - if (l->blockPropertyIndex != t) - runLevelScriptCustom(l->blockPropertyIndex, 0x800, -1, l->field_16, 0, 0); - - if (_updateFlags & 1) - return; - - cmzS7(l->properties->unk3[5], l->blockPropertyIndex); -} - -int LoLEngine::cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { - int16 r = 0; - int16 t1 = y1 - y2; - if (t1 < 0) { - r++; - t1 = -t1; - } - - r <<= 1; - - int16 t2 = x2 - x1; - - if (t2 < 0) { - r++; - t2 = -t2; - } - - uint8 f = 0; - - if (t2 >= t1) { - if (t2 > t1) - f = 1; - SWAP(t1, t2); - } - - r = (r << 1) | f; - - t1 = (t1 + 1) >> 1; - - f = 0; - f = (t2 > t1) ? 1 : 0; - r = (r << 1) | f; - - static const uint8 Retv[] = { 1, 2, 1, 0, 7, 6, 7, 0, 3, 2, 3, 4, 5, 6, 5, 4}; - return Retv[r]; -} - -void LoLEngine::cmzS2(MonsterInPlay *l, int a) { - // TODO -} - -void LoLEngine::cmzS3(MonsterInPlay *l) { - // TODO -} - -void LoLEngine::cmzS4(uint16 &itemIndex, int a) { - // TODO -} - -int LoLEngine::cmzS5(uint16 a, uint16 b) { - // TODO - return 0; -} - -void LoLEngine::cmzS6(uint16 &itemIndex, int a) { - // TODO -} - -void LoLEngine::cmzS7(int a, int block) { - if (!(_unkGameFlag & 1)) - return; - - // TODO -} - void LoLEngine::moveItemToBlock(uint16 *cmzItemIndex, uint16 item) { - MonsterInPlay *tmp = 0; + ItemInPlay *tmp = 0; while (*cmzItemIndex & 0x8000) { tmp = findItem(*cmzItemIndex); - cmzItemIndex = &tmp->itemIndexUnk; + cmzItemIndex = &tmp->next; } tmp = findItem(item); @@ -294,11 +127,11 @@ void LoLEngine::moveItemToBlock(uint16 *cmzItemIndex, uint16 item) { return; *cmzItemIndex = item; - cmzItemIndex = &tmp->itemIndexUnk; + cmzItemIndex = &tmp->next; while (*cmzItemIndex) { tmp = findItem(*cmzItemIndex); - cmzItemIndex = &tmp->itemIndexUnk; + cmzItemIndex = &tmp->next; } *cmzItemIndex = ix; @@ -434,7 +267,7 @@ void LoLEngine::loadLevelCmzFile(int index) { if (_monsters[i].blockPropertyIndex) { _monsters[i].blockPropertyIndex = 0; _monsters[i].properties = &_monsterProperties[_monsters[i].type]; - initCMZ2(&_monsters[i], _monsters[i].x, _monsters[i].y); + placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y); } } @@ -450,15 +283,15 @@ void LoLEngine::loadCMZ_Sub(int index1, int index2) { //int r = 0; for (int i = 0; i < 30; i++) { - if (_monsters[i].field_14 >= 14 || _monsters[i].blockPropertyIndex == 0 || _monsters[i].monsterMight <= 0) + if (_monsters[i].mode >= 14 || _monsters[i].blockPropertyIndex == 0 || _monsters[i].might <= 0) continue; - int t = (val * _monsters[i].monsterMight) >> 8; - _monsters[i].monsterMight = t; + int t = (val * _monsters[i].might) >> 8; + _monsters[i].might = t; if (index2 < index1) - _monsters[i].monsterMight++; - if (_monsters[i].monsterMight == 0) - _monsters[i].monsterMight = 1; + _monsters[i].might++; + if (_monsters[i].might == 0) + _monsters[i].might = 1; } } @@ -473,7 +306,7 @@ void LoLEngine::loadCmzFile(const char *file) { for (int ii = 0; ii < 4; ii++) _levelBlockProperties[i].walls[ii] = p[i * len + ii]; - _levelBlockProperties[i].field_8 = 5; + _levelBlockProperties[i].direction = 5; if (_wllBuffer4[_levelBlockProperties[i].walls[0]] == 17) { _levelBlockProperties[i].flags &= 0xef; @@ -482,111 +315,6 @@ void LoLEngine::loadCmzFile(const char *file) { } } -void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) { - releaseMonsterShapes(monsterIndex); - _screen->loadBitmap(file, 3, 3, 0); - - const uint8 *p = _screen->getCPagePtr(2); - const uint8 *ts[16]; - - for (int i = 0; i < 16; i++) { - ts[i] = _screen->getPtrToShape(p, i); - - bool replaced = false; - int pos = monsterIndex << 4; - - for (int ii = 0; ii < i; ii++) { - if (ts[i] != ts[ii]) - continue; - - _monsterShapes[pos + i] = _monsterShapes[pos + ii]; - replaced = true; - break; - } - - if (!replaced) - _monsterShapes[pos + i] = _screen->makeShapeCopy(p, i); - - int size = _screen->getShapePaletteSize(_monsterShapes[pos + i]) << 3; - _monsterPalettes[pos + i] = new uint8[size]; - memset(_monsterPalettes[pos + i], 0, size); - } - - for (int i = 0; i < 4; i++) { - for (int ii = 0; ii < 16; ii++) { - uint8 **of = &_buf4[(monsterIndex << 7) + (i << 5) + (ii << 1)]; - int s = (i << 4) + ii + 17; - *of = _screen->makeShapeCopy(p, s); - - ////TODO - } - } - _monsterUnk[monsterIndex] = b & 0xff; - - uint8 *tsh = _screen->makeShapeCopy(p, 16); - - _screen->clearPage(3); - _screen->drawShape(2, tsh, 0, 0, 0, 0); - - uint8 *tmpPal1 = new uint8[64]; - uint8 *tmpPal2 = new uint8[256]; - uint16 *tmpPal3 = new uint16[256]; - memset (tmpPal1, 0, 64); - memset (tmpPal2, 0, 256); - memset (tmpPal3, 0xff, 512); - - for (int i = 0; i < 64; i++) { - tmpPal1[i] = *p; - p += 320; - } - - p = _screen->getCPagePtr(2); - - for (int i = 0; i < 16; i++) { - int pos = (monsterIndex << 4) + i; - memcpy(tmpPal2, _monsterShapes[pos] + 10, 256); - uint8 numCol = *tmpPal2; - - for (int ii = 0; ii < numCol; ii++) { - uint8 *cl = (uint8*)memchr(tmpPal1, tmpPal2[1 + ii], 64); - if (!cl) - continue; - tmpPal3[ii] = (uint16) (cl - tmpPal1); - } - - for (int ii = 0; ii < 8; ii++) { - memcpy(tmpPal2, _monsterShapes[pos] + 10, 256); - for (int iii = 0; iii < numCol; iii++) { - if (tmpPal3[iii] == 0xffff) - continue; - if (p[tmpPal3[iii] * 320 + ii + 1]) - tmpPal2[1 + iii] = p[tmpPal3[iii] * 320 + ii + 1]; - } - memcpy(_monsterPalettes[pos] + ii * numCol, &tmpPal2[1], numCol); - } - } - - delete[] tmpPal1; - delete[] tmpPal2; - delete[] tmpPal3; - delete[] tsh; -} - -void LoLEngine::releaseMonsterShapes(int monsterIndex) { - for (int i = 0; i < 16; i++) { - int pos = (monsterIndex << 4) + i; - if (_monsterShapes[pos]) { - delete[] _monsterShapes[pos]; - _monsterShapes[pos] = 0; - } - - if (_monsterPalettes[pos]) { - delete[] _monsterPalettes[pos]; - _monsterPalettes[pos] = 0; - } - } -} - void LoLEngine::loadLevelShpDat(const char *shpFile, const char *datFile, bool flag) { memset(_tempBuffer5120, 0, 5120); @@ -724,14 +452,14 @@ void LoLEngine::loadLevelGraphics(const char *file, int specialColor, int weight void LoLEngine::resetItems(int flag) { for (int i = 0; i < 1024; i++) { - _levelBlockProperties[i].field_8 = 5; - uint16 id = _levelBlockProperties[i].itemIndex; + _levelBlockProperties[i].direction = 5; + uint16 id = _levelBlockProperties[i].itemMonsterIndex; MonsterInPlay *r = 0; while (id & 0x8000) { r = (MonsterInPlay*)findItem(id); assert(r); - id = r->itemIndexUnk; + id = r->next; } if (!id) @@ -740,7 +468,7 @@ void LoLEngine::resetItems(int flag) { ItemInPlay *it = &_itemsInPlay[id]; it->level = _currentLevel; it->blockPropertyIndex = i; - r->itemIndexUnk = 0; + r->next = 0; } if (flag) @@ -750,7 +478,7 @@ void LoLEngine::resetItems(int flag) { void LoLEngine::resetLvlBuffer() { memset(_monsters, 0, 30 * sizeof(MonsterInPlay)); for (int i = 0; i < 30; i++) - _monsters[i].field_14 = 0x10; + _monsters[i].mode = 0x10; } void LoLEngine::resetBlockProperties() { @@ -921,16 +649,25 @@ uint16 LoLEngine::calcNewBlockPosition(uint16 curBlock, uint16 direction) { return (curBlock + blockPosTable[direction]) & 0x3ff; } +uint16 LoLEngine::calcBlockIndex(uint16 x, uint16 y) { + return ((y & 0xff00) >> 3) | (x >> 8); +} + +void LoLEngine::calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs) { + x = (block & 0x1f) << 8 | xOffs; + y = ((block & 0xffe0) << 3) | yOffs; +} + bool LoLEngine::checkBlockPassability(uint16 block, uint16 direction) { if (testWallFlag(block, direction, 1)) return false; - uint16 d = _levelBlockProperties[block].itemIndex; + uint16 d = _levelBlockProperties[block].itemMonsterIndex; while (d) { if (d & 0x8000) return false; - d = findItem(d)->itemIndexUnk; + d = findItem(d)->next; } return true; @@ -945,7 +682,7 @@ void LoLEngine::notifyBlockNotPassable(int scrollFlag) { snd_playSoundEffect(19, -1); } -int LoLEngine::clickedDecoration(uint16 block, uint16 direction) { +int LoLEngine::clickedWallShape(uint16 block, uint16 direction) { uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]]; if (!clickedShape(v)) return 0; @@ -956,7 +693,20 @@ int LoLEngine::clickedDecoration(uint16 block, uint16 direction) { return 1; } -int LoLEngine::switchOpenDoor(uint16 block, uint16 direction) { +int LoLEngine::clicked2(uint16 block, uint16 direction) { + return 1; +} + +int LoLEngine::clicked3(uint16 block, uint16 direction) { + return 1; +} + +int LoLEngine::clickedWallOnlyScript(uint16 block) { + runLevelScript(block, 0x40); + return 1; +} + +int LoLEngine::clickedDoorSwitch(uint16 block, uint16 direction) { uint8 v = _wllShapeMap[_levelBlockProperties[block].walls[direction]]; if (!clickedShape(v)) return 0; @@ -973,6 +723,10 @@ int LoLEngine::switchOpenDoor(uint16 block, uint16 direction) { return 1; } +int LoLEngine::clicked6(uint16 block, uint16 direction) { + return 1; +} + bool LoLEngine::clickedShape(int shapeIndex) { while (shapeIndex) { uint16 s = _levelShapeProperties[shapeIndex].shapeIndex[1]; @@ -1654,7 +1408,7 @@ void LoLEngine::drawSceneShapes() { drawIceShapes(t, 0); - if (_curBlockCaps[t]->itemIndex && (w & 0x80)) + if (_curBlockCaps[t]->itemMonsterIndex && (w & 0x80)) drawMonstersAndItems(t); drawIceShapes(t, 1); @@ -1847,89 +1601,6 @@ void LoLEngine::drawIceShapes(int index, int iceShapeIndex) { return; } -void LoLEngine::drawMonstersAndItems(int block) { - - -} - -void LoLEngine::drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags) { - uint8 c = _dscDoor1[(_currentDirection << 5) + unk2]; - int r = (c / 5) + 5 * _dscDimMap[index]; - uint16 d = _dscShapeOvlIndex[r]; - uint16 t = (index << 5) + c; - - _shpDmY = _dscDoorMonsterY[t] + 120; - - if (flags & 1) { - // TODO - } - - int u = 0; - - if (flags & 2) { - uint8 dimW = _dscDimMap[index]; - _dmScaleW = _dscDoorMonsterScaleTable[dimW << 1]; - _dmScaleH = _dscDoorMonsterScaleTable[(dimW << 1) + 1]; - u = _dscDoor4[dimW]; - } - - d += 2; - - if (!_dmScaleW || !_dmScaleH) - return; - - int s = _screen->getShapeScaledHeight(shape, _dmScaleH) >> 1; - - if (w) - w = (w * _dmScaleW) >> 8; - - if (h) - h = (h * _dmScaleH) >> 8; - - _shpDmX = _dscDoorMonsterX[t] + w + 200; - _shpDmY = _shpDmY + 4 - s + h - u; - - if (d > 7) - d = 7; - - uint8 *ovl = _screen->getLevelOverlay(d); - int doorScaledWitdh = _screen->getShapeScaledWidth(shape, _dmScaleW); - - _shpDmX -= (doorScaledWitdh >> 1); - _shpDmY -= s; - - drawDoorOrMonsterShape(shape, table, _shpDmX, _shpDmY, flags, ovl); -} - -void LoLEngine::drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl) { - int flg = 0; - - if (flags & 0x10) - flg |= 1; - - if (flags & 0x20) - flg |= 0x1000; - - if (flags & 0x40) - flg |= 2; - - if (flg & 0x1000) { - if (table) - _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x9104, table, ovl, 1, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH); - else - _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x1104, ovl, 1, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH); - } else { - if (table) - _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x8104, table, ovl, 1, _dmScaleW, _dmScaleH); - else - _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x104, ovl, 1, _dmScaleW, _dmScaleH); - } -} - -void LoLEngine::drawSceneItem(uint8 *shape, uint8 *ovl, int x, int y, int w, int h, int flags, int unk1, int unk2) { - -} - void LoLEngine::drawScriptShapes(int pageNum) { if (!_scriptAssignedLevelShape) return; diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 71d49a7aae..04227322ed 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -1151,6 +1151,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int _dsTable = 0; _dsTableLoopCount = 0; _dsTable2 = 0; + _dsTable5 = 0; _dsDrawLayer = 0; uint8 *table3 = 0; @@ -1195,7 +1196,7 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int } if ((flags & 0x2000) && _vm->gameFlags().gameID != GI_KYRA1) - va_arg(args, int); + _dsTable5 = va_arg(args, uint8*); static const DsMarginSkipFunc dsMarginFunc[] = { &Screen::drawShapeMarginNoScaleUpwind, @@ -1248,6 +1249,10 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int &Screen::drawShapePlotType14, // used by Kyra 1 (invisibility) &Screen::drawShapePlotType11_15, // used by Kyra 1 (invisibility) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, + &Screen::drawShapePlotType37, // used by LoL (monsters) + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -1808,6 +1813,20 @@ void Screen::drawShapePlotType14(uint8 *dst, uint8 cmd) { *dst = cmd; } +void Screen::drawShapePlotType37(uint8 *dst, uint8 cmd) { + cmd = _dsTable2[cmd]; + + if (cmd == 255) { + cmd = _dsTable5[*dst]; + } else { + for (int i = 0; i < _dsTableLoopCount; ++i) + cmd = _dsTable[cmd]; + } + + if (cmd) + *dst = cmd; +} + void Screen::decodeFrame3(const uint8 *src, uint8 *dst, uint32 size) { debugC(9, kDebugLevelScreen, "Screen::decodeFrame3(%p, %p, %u)", (const void *)src, (const void *)dst, size); const uint8 *dstEnd = dst + size; diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h index 8299262d0e..737cd03082 100644 --- a/engines/kyra/screen.h +++ b/engines/kyra/screen.h @@ -332,6 +332,7 @@ protected: void drawShapePlotType12(uint8 *dst, uint8 cmd); void drawShapePlotType13(uint8 *dst, uint8 cmd); void drawShapePlotType14(uint8 *dst, uint8 cmd); + void drawShapePlotType37(uint8 *dst, uint8 cmd); typedef int (Screen::*DsMarginSkipFunc)(uint8 *&dst, const uint8 *&src, int &cnt); typedef void (Screen::*DsLineFunc)(uint8 *&dst, const uint8 *&src, int &cnt, int scaleState); @@ -345,6 +346,7 @@ protected: const uint8 *_dsTable; int _dsTableLoopCount; const uint8 *_dsTable2; + const uint8 *_dsTable5; int _dsDrawLayer; uint8 *_dsDstPage; int _dsTmpWidth; diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index 8e65cd3d9b..77bfba3025 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -32,7 +32,8 @@ namespace Kyra { -void LoLEngine::runInitScript(const char *filename, int func) { +void LoLEngine::runInitScript(const char *filename, int optionalFunc) { + _suspendScript = true; EMCData scriptData; EMCState scriptState; memset(&scriptData, 0, sizeof(EMCData)); @@ -43,14 +44,15 @@ void LoLEngine::runInitScript(const char *filename, int func) { while (_emc->isValid(&scriptState)) _emc->run(&scriptState); - if (func) { + if (optionalFunc) { _emc->init(&scriptState, &scriptData); - _emc->start(&scriptState, func); + _emc->start(&scriptState, optionalFunc); while (_emc->isValid(&scriptState)) _emc->run(&scriptState); } _emc->unload(&scriptData); + _suspendScript = false; } void LoLEngine::runInfScript(const char *filename) { @@ -66,7 +68,7 @@ void LoLEngine::runLevelScriptCustom(int block, int sub, int charNum, int item, EMCState scriptState; memset(&scriptState, 0, sizeof(EMCState)); - if (!_scriptBoolSkipExec) { + if (!_suspendScript) { _emc->init(&scriptState, &_scriptData); _emc->start(&scriptState, block); @@ -78,14 +80,18 @@ void LoLEngine::runLevelScriptCustom(int block, int sub, int charNum, int item, scriptState.regs[5] = block; scriptState.regs[6] = _scriptDirection; - while (_emc->isValid(&scriptState)) - _emc->run(&scriptState); + if (_emc->isValid(&scriptState)) { + if (*(scriptState.ip - 1) & sub) { + while (_emc->isValid(&scriptState)) + _emc->run(&scriptState); + } + } } - checkScriptUnk(block); + checkSceneUpdateNeed(block); } -bool LoLEngine::checkScriptUnk(int func) { +bool LoLEngine::checkSceneUpdateNeed(int func) { if (_sceneUpdateRequired) return true; @@ -116,7 +122,7 @@ int LoLEngine::olol_setGameFlag(EMCState *script) { int LoLEngine::olol_testGameFlag(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_testGameFlag(%p) (%d)", (const void *)script, stackPos(0)); - if (!stackPos(0)) + if (stackPos(0) < 0) return 0; if (_gameFlags[stackPos(0) >> 4] & (1 << (stackPos(0) & 0x0f))) @@ -454,6 +460,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) { break; case 3: + setHandItem(b); break; case 4: @@ -488,7 +495,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) { case 10: _sceneDefaultUpdate = b & 0xff; - //TODO + gui_toggleButtonDisplayMode(0, 0); break; case 11: @@ -519,6 +526,56 @@ int LoLEngine::olol_resetBlockShapeAssignment(EMCState *script) { return 1; } +int LoLEngine::olol_initMonster(EMCState *script) { + uint16 x = 0; + uint16 y = 0; + calcCoordinates(x, y, stackPos(0), stackPos(1), stackPos(2)); + uint16 w = _monsterProperties[stackPos(4)].maxWidth; + + if (checkBlockBeforeMonsterPlacement(x, y, w, 7, 7)) + return -1; + + for (uint8 i = 0; i < 30; i++) { + MonsterInPlay *l = &_monsters[i]; + if (l->might || l->mode == 13) + continue; + + memset(l, 0, sizeof(MonsterInPlay)); + l->id = i; + l->x = x; + l->y = y; + l->facing = stackPos(3); + l->type = stackPos(4); + l->properties = &_monsterProperties[l->type]; + l->field_17 = l->facing << 1; + l->might = (l->properties->might * _monsterModifiers[((_unkGameFlag & 0x30) >> 4)]) >> 8; + + if (_currentLevel == 12 && l->type == 2) + l->might = (l->might * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8; + + l->field_25 = l->properties->unk6[0]; + l->field_27 = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1; + l->unk4 = 2; + l->flags = stackPos(5); + l->assignedItems = 0; + + setMonsterMode(l, stackPos(6)); + placeMonster(l, l->x, l->y); + + l->itemPosX = l->x; + l->itemPosY = l->y; + l->field10 = l->field_17; + + for (int ii = 0; ii < 4; ii++) + l->field_2A[ii] = stackPos(7 + ii); + + checkSceneUpdateNeed(l->blockPropertyIndex); + return i; + } + + return -1; +} + int LoLEngine::olol_loadMonsterProperties(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadMonsterProperties(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), @@ -529,12 +586,12 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) { stackPos(35), stackPos(36), stackPos(37), stackPos(38), stackPos(39), stackPos(40), stackPos(41)); MonsterProperty *l = &_monsterProperties[stackPos(0)]; - l->id = stackPos(1) & 0xff; + l->shapeIndex = stackPos(1) & 0xff; int shpWidthMax = 0; for (int i = 0; i < 16; i++) { - uint8 m = _monsterShapes[(l->id << 4) + i][3]; + uint8 m = _monsterShapes[(l->shapeIndex << 4) + i][3]; if (m > shpWidthMax) shpWidthMax = m; } @@ -556,18 +613,18 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) { l->unk3[i] = (stackPos(17 + i) << 8) / 100; } - l->pos = &l->unk[0]; + l->pos = &l->field2[0]; l->itemProtection = stackPos(25); l->might = stackPos(26); l->b = 1; - l->unk5[0] = stackPos(27); - l->unk5[1] = stackPos(28); + l->flags = stackPos(27); + l->unk5 = stackPos(28); // FIXME??? - l->unk5[1] = stackPos(29); + l->unk5 = stackPos(29); // for (int i = 0; i < 5; i++) - l->unk6[2 + i] = stackPos(30 + i); + l->unk6[i] = stackPos(30 + i); for (int i = 0; i < 2; i++) { l->unk7[i] = stackPos(35 + i); @@ -575,12 +632,23 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) { } for (int i = 0; i < 3; i++) - l->unk8[2 + i] = stackPos(39 + i); + l->unk8[i] = stackPos(39 + i); return 1; } int LoLEngine::olol_68(EMCState *script) { + + MonsterInPlay *m = &_monsters[stackPos(0)]; + + if (m->mode == 1 || m->mode == 2) { + calcCoordinates(m->itemPosX, m->itemPosY, stackPos(1), stackPos(2), stackPos(3)); + m->field10 = stackPos(4); + + if (m->x != m->itemPosX || m->y != m->itemPosY) + cmzS2(m, cmzS1(m->x, m->y, m->itemPosX, m->itemPosY)); + } + return 1; } @@ -632,7 +700,11 @@ int LoLEngine::olol_restoreSceneAfterDialogueSequence(EMCState *script) { return 1; } -int LoLEngine::olol_85(EMCState *script) { +int LoLEngine::olol_giveItemToMonster(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_giveItemToMonster(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1)); + if (stackPos(0) == -1) + return 0; + giveItemToMonster(&_monsters[stackPos(0)], stackPos(1)); return 1; } @@ -646,6 +718,12 @@ int LoLEngine::olol_loadLangFile(EMCState *script) { return 1; } +int LoLEngine::olol_playSoundEffect(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playSoundEffect(%p) (%d)", (const void *)script, stackPos(0)); + snd_playSoundEffect(stackPos(0), 255); + return 1; +} + int LoLEngine::olol_stopTimScript(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_stopTimScript(%p) (%d)", (const void *)script, stackPos(0)); _tim->stopAllFuncs(_activeTim[stackPos(0)]); @@ -674,6 +752,17 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) { return old; } +int LoLEngine::olol_printMessage(EMCState *script) { + debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_printMessage(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); + int snd = stackPos(2); + _txt->printMessage(stackPos(0), getLangString(stackPos(1)), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7), stackPos(8), stackPos(9)); + + if (snd) + snd_playSoundEffect(snd, 255); + + return 1; +} + int LoLEngine::olol_playDialogueTalkText(EMCState *script) { debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playDialogueTalkText(%p) (%d)", (const void *)script, stackPos(0)); int track = stackPos(0); @@ -686,11 +775,11 @@ int LoLEngine::olol_playDialogueTalkText(EMCState *script) { return 1; } -int LoLEngine::olol_checkDialogueState(EMCState *script) { +int LoLEngine::olol_checkForMonsterMode1(EMCState *script) { for (int i = 0; i < 30; i++) { if (stackPos(0) != _monsters[i].type && stackPos(0) != -1) continue; - return (_monsters[i].field_14 == 1) ? 0 : 1; + return (_monsters[i].mode == 1) ? 0 : 1; } return 1; } @@ -895,7 +984,7 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); // 0x38 - OpcodeUnImpl(); + Opcode(olol_initMonster); OpcodeUnImpl(); OpcodeUnImpl(); OpcodeUnImpl(); @@ -938,9 +1027,9 @@ void LoLEngine::setupOpcodeTable() { // 0x54 OpcodeUnImpl(); - Opcode(olol_85); + Opcode(olol_giveItemToMonster); Opcode(olol_loadLangFile); - OpcodeUnImpl(); + Opcode(olol_playSoundEffect); // 0x58 OpcodeUnImpl(); @@ -976,7 +1065,7 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); OpcodeUnImpl(); OpcodeUnImpl(); - OpcodeUnImpl(); + Opcode(olol_printMessage); // 0x70 OpcodeUnImpl(); @@ -994,7 +1083,7 @@ void LoLEngine::setupOpcodeTable() { OpcodeUnImpl(); OpcodeUnImpl(); Opcode(olol_playDialogueTalkText); - Opcode(olol_checkDialogueState); + Opcode(olol_checkForMonsterMode1); // 0x7C Opcode(olol_setNextFunc); diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp new file mode 100644 index 0000000000..603a45cb93 --- /dev/null +++ b/engines/kyra/sprites_lol.cpp @@ -0,0 +1,942 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "kyra/lol.h" +#include "kyra/screen_lol.h" + +namespace Kyra { + +void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) { + releaseMonsterShapes(monsterIndex); + _screen->loadBitmap(file, 3, 3, 0); + + const uint8 *p = _screen->getCPagePtr(2); + const uint8 *ts[16]; + + for (int i = 0; i < 16; i++) { + ts[i] = _screen->getPtrToShape(p, i); + + bool replaced = false; + int pos = monsterIndex << 4; + + for (int ii = 0; ii < i; ii++) { + if (ts[i] != ts[ii]) + continue; + + _monsterShapes[pos + i] = _monsterShapes[pos + ii]; + replaced = true; + break; + } + + if (!replaced) + _monsterShapes[pos + i] = _screen->makeShapeCopy(p, i); + + int size = _screen->getShapePaletteSize(_monsterShapes[pos + i]) << 3; + _monsterPalettes[pos + i] = new uint8[size]; + memset(_monsterPalettes[pos + i], 0, size); + } + + for (int i = 0; i < 4; i++) { + for (int ii = 0; ii < 16; ii++) { + uint8 **of = &_monsterShapesEx[monsterIndex * 192 + i * 48 + ii * 3]; + int s = (i << 4) + ii + 17; + of[0] = _screen->makeShapeCopy(p, s); + of[1] = _screen->makeShapeCopy(p, s + 1); + of[2] = _screen->makeShapeCopy(p, s + 2); + } + } + _monsterUnk[monsterIndex] = b & 0xff; + + uint8 *tsh = _screen->makeShapeCopy(p, 16); + + _screen->clearPage(3); + _screen->drawShape(2, tsh, 0, 0, 0, 0); + + uint8 *tmpPal1 = new uint8[64]; + uint8 *tmpPal2 = new uint8[256]; + uint16 *tmpPal3 = new uint16[256]; + memset (tmpPal1, 0, 64); + memset (tmpPal2, 0, 256); + memset (tmpPal3, 0xff, 512); + + for (int i = 0; i < 64; i++) { + tmpPal1[i] = *p; + p += 320; + } + + p = _screen->getCPagePtr(2); + + for (int i = 0; i < 16; i++) { + int pos = (monsterIndex << 4) + i; + memcpy(tmpPal2, _monsterShapes[pos] + 10, 256); + uint8 numCol = *tmpPal2; + + for (int ii = 0; ii < numCol; ii++) { + uint8 *cl = (uint8*)memchr(tmpPal1, tmpPal2[1 + ii], 64); + if (!cl) + continue; + tmpPal3[ii] = (uint16) (cl - tmpPal1); + } + + for (int ii = 0; ii < 8; ii++) { + memcpy(tmpPal2, _monsterShapes[pos] + 10, 256); + for (int iii = 0; iii < numCol; iii++) { + if (tmpPal3[iii] == 0xffff) + continue; + if (p[tmpPal3[iii] * 320 + ii + 1]) + tmpPal2[1 + iii] = p[tmpPal3[iii] * 320 + ii + 1]; + } + memcpy(_monsterPalettes[pos] + ii * numCol, &tmpPal2[1], numCol); + } + } + + delete[] tmpPal1; + delete[] tmpPal2; + delete[] tmpPal3; + delete[] tsh; +} + +void LoLEngine::releaseMonsterShapes(int monsterIndex) { + for (int i = 0; i < 16; i++) { + int pos = (monsterIndex << 4) + i; + if (_monsterShapes[pos]) { + delete[] _monsterShapes[pos]; + _monsterShapes[pos] = 0; + } + + if (_monsterPalettes[pos]) { + delete[] _monsterPalettes[pos]; + _monsterPalettes[pos] = 0; + } + } +} + +int LoLEngine::placeMonstersUnk(int block) { + int i = _levelBlockProperties[block].itemMonsterIndex; + int cnt = 0; + MonsterInPlay *t = 0; + + while (i) { + t = (MonsterInPlay *)findItem(i); + i = t->next; + if (!(i & 0x8000)) + continue; + + i &= 0x7fff; + t = &_monsters[i]; + + cnt++; + setMonsterMode(t, 14); + + checkSceneUpdateNeed(t->blockPropertyIndex); + + placeMonster(t, 0, 0); + } + return cnt; +} + +void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) { + if (monster->mode == 13 && mode != 14) + return; + if (mode == 7) { + monster->itemPosX = _partyPosX; + monster->itemPosY = _partyPosX; + } + + if (monster->mode == 1 && mode == 7) { + for (int i = 0; i < 30; i++) { + if (monster->mode != 1) + continue; + monster->mode = mode; + monster->field_15 = 0; + monster->itemPosX = _partyPosX; + monster->itemPosY = _partyPosY; + cmzS2(monster, cmzS1(monster->x, monster->y, monster->itemPosX, monster->itemPosY)); + } + } else { + monster->mode = mode; + monster->field_15 = 0; + if (mode == 14) + monster->might = 0; + if (mode == 13 && (monster->flags & 0x20)) { + monster->mode = 0; + cmzS3(monster); + if (_currentLevel != 29) + setMonsterMode(monster, 14); + runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0); + checkSceneUpdateNeed(monster->blockPropertyIndex); + if (monster->mode == 14) + placeMonster(monster, 0, 0); + } + } +} + +void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) { + bool cont = true; + int t = monster->blockPropertyIndex; + if (monster->blockPropertyIndex) { + removeItemOrMonsterFromBlock(&_levelBlockProperties[monster->blockPropertyIndex].itemMonsterIndex, ((uint16)monster->id) | 0x8000); + _levelBlockProperties[monster->blockPropertyIndex].direction = 5; + checkSceneUpdateNeed(monster->blockPropertyIndex); + } else { + cont = false; + } + + monster->blockPropertyIndex = calcBlockIndex(x, y); + + if (monster->x != x || monster->y != y) { + monster->x = x; + monster->y = y; + monster->anon9 = (++monster->anon9) & 3; + } + + if (monster->blockPropertyIndex == 0) + return; + + assignItemOrMonsterToBlock(&_levelBlockProperties[monster->blockPropertyIndex].itemMonsterIndex, ((uint16)monster->id) | 0x8000); + _levelBlockProperties[monster->blockPropertyIndex].direction = 5; + checkSceneUpdateNeed(monster->blockPropertyIndex); + + if (monster->properties->unk8[0] == 0 || cont == false) + return; + + if ((!(monster->properties->flags & 0x100) || ((monster->anon9 & 1) == 0)) && monster->blockPropertyIndex == t) + return; + + if (monster->blockPropertyIndex != t) + runLevelScriptCustom(monster->blockPropertyIndex, 0x800, -1, monster->id, 0, 0); + + if (_updateFlags & 1) + return; + + cmzS7(monster->properties->unk3[5], monster->blockPropertyIndex); +} + +int LoLEngine::cmzS1(uint16 x1, uint16 y1, uint16 x2, uint16 y2) { + int16 r = 0; + int16 t1 = y1 - y2; + if (t1 < 0) { + r++; + t1 = -t1; + } + + r <<= 1; + + int16 t2 = x2 - x1; + + if (t2 < 0) { + r++; + t2 = -t2; + } + + uint8 f = 0; + + if (t2 >= t1) { + if (t2 > t1) + f = 1; + SWAP(t1, t2); + } + + r = (r << 1) | f; + + t1 = (t1 + 1) >> 1; + + f = 0; + f = (t2 > t1) ? 1 : 0; + r = (r << 1) | f; + + static const uint8 retVal[] = { 1, 2, 1, 0, 7, 6, 7, 0, 3, 2, 3, 4, 5, 6, 5, 4}; + return retVal[r]; +} + +void LoLEngine::cmzS2(MonsterInPlay *monster, int a) { + monster->field_17 = a; + + if (!(a & 1) || ((monster->field_17 - (monster->facing << 1)) < 2)) + monster->facing = monster->field_17 >> 1; + + checkSceneUpdateNeed(monster->blockPropertyIndex); +} + +void LoLEngine::cmzS3(MonsterInPlay *l) { + // TODO +} + +void LoLEngine::removeItemOrMonsterFromBlock(uint16 *blockItemIndex, int id) { + while (*blockItemIndex) { + if (*blockItemIndex == id) { + ItemInPlay *t = findItem(id); + blockItemIndex = &t->next; + t->next = 0; + return; + } else { + ItemInPlay *t = findItem(*blockItemIndex); + blockItemIndex = &t->next; + } + } +} + +void LoLEngine::assignItemOrMonsterToBlock(uint16 *blockItemIndex, int id) { + ItemInPlay *t = findItem(id); + t->next = *blockItemIndex; + *blockItemIndex = id; +} + +int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth, int p1, int p2) { + int monsterUnk_ = 0; + int x2 = 0; + int y2 = 0; + int xOffs = 0; + int yOffs = 0; + int flag = 0; + + int r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y), x, y, monsterWidth, p1, p2); + if (r) + return r; + + r = checkBlockOccupiedByParty(x, y, p1); + if (r) + return 4; + + if (x & 0x80) { + if (((x & 0xff) + monsterWidth) & 0xff00) { + xOffs = 1; + monsterUnk_ = 2; + x2 = x + monsterWidth; + + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, monsterWidth, p1, p2); + if (r) + return r; + + r = checkBlockOccupiedByParty(x + xOffs, y, p1); + if (r) + return 4; + + flag = 1; + } + } else { + if (((x & 0xff) - monsterWidth) & 0xff00) { + xOffs = -1; + monsterUnk_ = 6; + x2 = x - monsterWidth; + + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y), x, y, monsterWidth, p1, p2); + if (r) + return r; + + r = checkBlockOccupiedByParty(x + xOffs, y, p1); + if (r) + return 4; + + flag = 1; + } + } + + if (y & 0x80) { + if (((y & 0xff) + monsterWidth) & 0xff00) { + yOffs = 1; + monsterUnk_ = 4; + y2 = y + monsterWidth; + + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, monsterWidth, p1, p2); + if (r) + return r; + + r = checkBlockOccupiedByParty(x, y + yOffs, p1); + if (r) + return 4; + } else { + flag = 0; + } + } else { + if (((y & 0xff) - monsterWidth) & 0xff00) { + yOffs = -1; + monsterUnk_ = 0; + y2 = y - monsterWidth; + + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y2), x, y, monsterWidth, p1, p2); + if (r) + return r; + + r = checkBlockOccupiedByParty(x, y + yOffs, p1); + if (r) + return 4; + } else { + flag = 0; + } + } + + if (!flag) + return 0; + + r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x2, y2), x, y, monsterWidth, p1, p2); + if (r) + return r; + + r = checkBlockOccupiedByParty(x + xOffs, y + yOffs, p1); + if (r) + return 4; + + return 0; +} + +int LoLEngine::calcMonsterSkillLevel(int id, int a) { + const uint16 *c = getCharacterOrMonsterStats(id); + int r = (a << 8) / c[4]; + + if (!(id & 0x8000)) + r = (r * _monsterModifiers[3 + ((_unkGameFlag & 0x30) << 4)]) >> 8; + + id &= 0x7fff; + + if (_characters[id].skillLevels[1] <= 3) + return r; + else if (_characters[id].skillLevels[1] <= 7) + return (r- (r >> 2)); + + return (r- (r >> 1)); +} + +int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int p1, int p2) { + if (block == _currentBlock) + p1 &= 0xfffe; + + int _monsterBlock = 0; + + if (p1 & 1) { + _monsterBlock = block; + if (testWallFlag(block, -1, p2)) + return 1; + } + + _monsterBlock = 0; + + if (!(p1 & 2)) + return 0; + + uint16 b = _levelBlockProperties[block].itemMonsterIndex; + while (b & 0x8000) { + MonsterInPlay *monster = &_monsters[b & 0x7fff]; + + if (monster->mode < 13) { + int r = checkMonsterSpace(x, y, monster->x, monster->y); + if ((monsterWidth + monster->properties->maxWidth) > r) + return 2; + } + + b = findItem(b)->next; + } + + return 0; +} + +bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int p1) { + if ((p1 & 4) && (_currentBlock == calcBlockIndex(x, y))) + return true; + + return false; +} + +void LoLEngine::drawMonstersAndItems(int block) { + LevelBlockProperty *l = _curBlockCaps[block]; + uint16 s = l->itemMonsterIndex; + ItemInPlay *i = findItem(s); + + if (l->direction != _currentDirection) { + l->field_6 = 0; + l->direction = _currentDirection; + + while (s) { + i = findItem(s); + recalcItemMonsterPositions(_currentDirection, s, l, true); + i = findItem(s); + s = i->next; + } + } + + s = l->field_6; + while (s) { + if (s & 0x8000) { + s &= 0x7fff; + if (block < 15) + drawMonster(s); + s = _monsters[s].unk2; + } else { + ////////// + // TODO + + } + } +} + +void LoLEngine::drawMonster(uint16 id) { + MonsterInPlay *m = &_monsters[id]; + int16 flg = _monsterDirFlags[(_currentDirection << 2) + m->facing]; + int curFrm = getMonsterCurFrame(m, flg & 0xffef); + + if (curFrm == -1) { + //////////// + // TODO + + } else { + int d = m->flags & 7; + bool flip = m->properties->flags & 0x200 ? true : false; + flg &= 0x10; + uint8 *shp = _monsterShapes[(m->properties->shapeIndex << 4) + curFrm]; + + if (m->properties->flags & 0x800) + flg |= 0x20; + + uint8 *ovl1 = d ? _monsterPalettes[(m->properties->shapeIndex << 4) + (curFrm & 0x0f)] + (shp[10] * (d - 1)) : 0; + uint8 *ovl2 = drawItemOrMonster(shp, ovl1, m->x + _monsterLevelOffs[m->level << 1], m->y + _monsterLevelOffs[(m->level << 1) + 1], 0, 0, flg | 1, -1, flip); + + for (int i = 0; i < 4; i++) { + int v = m->field_2A[i] - 1; + if (v == -1) + break; + + uint8 *shp2 = _monsterShapesEx[m->properties->shapeIndex * 192 + v * 48 + curFrm * 3]; + 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); + } + + if (!m->field_1B) + return; + + int dW = _screen->getShapeScaledWidth(shp, _dmScaleW) >> 1; + int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1; + + int a = (m->mode == 13) ? (m->field_15 << 1) : (m->properties->might / (m->field_1B & 0x7fff)); + + shp = _gameShapes[6]; + + int cF = m->properties->flags & 0xc000; + if (cF == 0x4000) + cF = 63; + else if (cF == 0x8000) + cF = 15; + else if (cF == 0xc000) + cF = 74; + else + cF = 0; + + uint8 *tbl = new uint8[256]; + if (cF) { + for (int i = 0; i < 256; i++) { + tbl[i] = i; + if (i < 2 || i > 7) + continue; + tbl[i] += cF; + } + } + + dW += m->anon8; + dH += m->anonh; + + a = CLIP(a, 1, 4); + + int sW = _dmScaleW / a; + int sH = _dmScaleH / a; + + _screen->drawShape(_sceneDrawPage1, shp, _shpDmX + dW, _shpDmY + dH, 13, 0x124, tbl, cF ? 1 : 0, sW, sH); + + delete[] tbl; + } +} + +int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) { + switch (_monsterUnk[m->properties->shapeIndex]) { + case 0: + if (dirFlags) { + return (*m->properties->pos & 0xff) == 13 ? -1 : (dirFlags + m->anon9); + } else { + if (m->field_1B) + return 12; + + switch (m->mode - 5) { + case 0: + return m->field_1B ? 12 : ((m->properties->flags & 4) ? 13 : 0); + case 3: + return (m->field_15 + 13); + case 6: + return 14; + case 8: + return -1; + default: + return m->field_1B ? 12 : m->anon9; + } + } + break; + case 1: + /////// + // TODO + break; + case 2: + /////// + // TODO + break; + case 3: + /////// + // TODO + break; + default: + break; + } + + return 0; +} + +void LoLEngine::recalcItemMonsterPositions(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; + + while (b) { + i2 = findItem(itemIndex); + + if (flag) { + if (calcItemMonsterPosition(i2, direction) >= r) + break; + } else { + if (calcItemMonsterPosition(i2, direction) > r) + break; + } + + b = &i2->unk2; + } + + i1->unk2 = *b; + *b = itemIndex; +} + +int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) { + int x = i->x; + int y = i->y; + + recalcSpritePosition(_partyPosX, _partyPosY, x, y, direction); + + if (y < 0) + y = 0; + + int res = (i->unk4 << 12); + res |= (4095 - y); + + return res; +} + +void LoLEngine::recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, int &itemY, uint16 direction) { + int a = itemX - partyX; + int b = partyY - itemY; + + if (direction) { + if (direction != 2) + SWAP(a, b); + if (direction != 3) { + a = -a; + if (direction != 1) + b = -b; + } else { + b = -b; + } + } + + itemX = a; + itemY = b; +} + +void LoLEngine::drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags) { + uint8 c = _dscDoor1[(_currentDirection << 5) + unk2]; + int r = (c / 5) + 5 * _dscDimMap[index]; + uint16 d = _dscShapeOvlIndex[r]; + uint16 t = (index << 5) + c; + + _shpDmY = _dscDoorMonsterY[t] + 120; + + if (flags & 1) { + // TODO + } + + int u = 0; + + if (flags & 2) { + uint8 dimW = _dscDimMap[index]; + _dmScaleW = _dscDoorMonsterScaleTable[dimW << 1]; + _dmScaleH = _dscDoorMonsterScaleTable[(dimW << 1) + 1]; + u = _dscDoor4[dimW]; + } + + d += 2; + + if (!_dmScaleW || !_dmScaleH) + return; + + int s = _screen->getShapeScaledHeight(shape, _dmScaleH) >> 1; + + if (w) + w = (w * _dmScaleW) >> 8; + + if (h) + h = (h * _dmScaleH) >> 8; + + _shpDmX = _dscDoorMonsterX[t] + w + 200; + _shpDmY = _shpDmY + 4 - s + h - u; + + if (d > 7) + d = 7; + + uint8 *ovl = _screen->getLevelOverlay(d); + int doorScaledWitdh = _screen->getShapeScaledWidth(shape, _dmScaleW); + + _shpDmX -= (doorScaledWitdh >> 1); + _shpDmY -= s; + + drawDoorOrMonsterShape(shape, table, _shpDmX, _shpDmY, flags, ovl); +} + +void LoLEngine::drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl) { + int flg = 0; + + if (flags & 0x10) + flg |= 1; + + if (flags & 0x20) + flg |= 0x1000; + + if (flags & 0x40) + flg |= 2; + + if (flg & 0x1000) { + if (table) + _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x9104, table, ovl, 1, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH); + else + _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x1104, ovl, 1, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH); + } else { + if (table) + _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x8104, table, ovl, 1, _dmScaleW, _dmScaleH); + else + _screen->drawShape(_sceneDrawPage1, shape, x, y, 13, flg | 0x104, ovl, 1, _dmScaleW, _dmScaleH); + } +} + +uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, int w, int h, int flags, int tblValue, bool flip) { + uint8 *ovl2 = 0; + uint8 *ovl = 0; + uint8 tmpOvl[16]; + + if (flags & 0x80) { + flags &= 0xff7f; + ovl2 = table; + table = 0; + } else { + ovl2 = _screen->getLevelOverlay(4); + } + + int r = calcDrawingLayerParameters(x, y, _shpDmX, _shpDmY, _dmScaleW, _dmScaleH, shape, flip); + + if (tblValue == -1) { + r = 7 - ((r / 3) - 1); + r = CLIP(r, 0, 7); + ovl = _screen->getLevelOverlay(r); + } else { + memset (tmpOvl + 1, tblValue, 15); + table = tmpOvl; + ovl = _screen->getLevelOverlay(7); + } + + int flg = flags & 0x10 ? 1 : 0; + if (flags & 0x20) + flg |= 0x1000; + if (flags & 0x40) + flg |= 2; + + if (_currentLevel == 22) { + if (ovl) + ovl[255] = 0; + } else { + flg |= 0x2000; + } + + _shpDmX += ((_dmScaleW * w) >> 8); + _shpDmY += ((_dmScaleH * h) >> 8); + + int dH = _screen->getShapeScaledHeight(shape, _dmScaleH) >> 1; + + if (flg & 0x1000) { + if (table) + _screen->drawShape(_sceneDrawPage1, shape, _shpDmX, _shpDmY, 13, flg | 0x8124, table, ovl, 0, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH, ovl2); + else + _screen->drawShape(_sceneDrawPage1, shape, _shpDmX, _shpDmY, 13, flg | 0x124, ovl, 0, _trueLightTable1, _trueLightTable2, _dmScaleW, _dmScaleH, ovl2); + } else { + if (table) + _screen->drawShape(_sceneDrawPage1, shape, _shpDmX, _shpDmY, 13, flg | 0x8124, table, ovl, 1, _dmScaleW, _dmScaleH, ovl2); + else + _screen->drawShape(_sceneDrawPage1, shape, _shpDmX, _shpDmY, 13, flg | 0x124, ovl, 1, _dmScaleW, _dmScaleH, ovl2); + } + + _shpDmX -= (_screen->getShapeScaledWidth(shape, _dmScaleW) >> 1); + _shpDmY -= dH; + + return ovl; +} + +int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int16 &x2, int16 &y2, int16 &w, int16 &h, uint8 *shape, int flip) { + recalcSpritePosition(_partyPosX, _partyPosY, x1, y1, _currentDirection); + + if (y1 < 0) { + w = h = x2 = y2 = 0; + return 0; + } + + int l = y1 >> 5; + y2 = _monsterScaleY[l]; + x2 = ((_monsterScaleX[l] * x1) >> 8) + 200; + w = h = _monsterScaleWH[_shpDmY - 56]; + + if (flip) + y2 = ((120 - y2) >> 1) + _screen->getShapeScaledHeight(shape, _dmScaleH); + else + y2 -= (_screen->getShapeScaledHeight(shape, _dmScaleH) >> 1); + + return l; +} + +void LoLEngine::updateMonster(MonsterInPlay *monster) { + static const uint8 monsterState[] = { 1, 0, 1, 3, 3, 0, 0, 3, 4, 1, 0, 0, 4, 0, 0 }; + if (monster->mode > 14) + return; + + int s = monsterState[monster->mode]; + int a = monster->field_1F++; + + if ((a < monster->properties->b) && (s & 4)) + return; + + monster->field_1F = 0; + + if (monster->properties->flags & 0x40) { + monster->might += _rnd.getRandomNumberRng(1, 8); + if (monster->might > monster->properties->might) + monster->might = monster->properties->might; + } + + if (monster->flags & 8) { + monster->itemPosX = _partyPosX; + monster->itemPosY = _partyPosY; + } + + if (s & 2) { + + ///// + // TODO + } + + if ((s & 1) && (monster->flags & 0x10)) + setMonsterMode(monster, 7); + + //// + // TODO + + switch (monster->mode) { + case 0: + case 1: + if (monster->flags & 0x10) { + for (int i = 0; i < 30; i++) { + if (_monsters[i].mode == 1) + setMonsterMode(&_monsters[i], 7); + } + } else if (monster->mode == 1) { + moveMonster(monster); + } + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + break; + case 8: + break; + case 9: + break; + case 12: + break; + case 13: + break; + case 14: + break; + default: + break; + } + + if (monster->field_1B) { + if (monster->field_1B & 0x8000) + monster->field_1B &= 0x7fff; + else + monster->field_1B = 0; + checkSceneUpdateNeed(monster->blockPropertyIndex); + } + + monster->flags &= 0xffef; +} + +void LoLEngine::moveMonster(MonsterInPlay *monster) { + static const int8 pos[] = { 0, 1, 3, 3, 0, 1, 2, 2, 1, 1, 2, 3, 0, 0, 2, 3, 0 }; + if (monster->x != monster->itemPosX || monster->y != monster->itemPosY) { + shiftMonster(monster); + } else if (monster->field_17 != monster->field10) { + int i = (monster->facing << 2) + (monster->field10 >> 1); + cmzS2(monster, pos[i]); + } +} + +void LoLEngine::shiftMonster(MonsterInPlay *monster) { + if (monster->properties->flags & 0x400) + return; + + + +} + +} // end of namespace Kyra + diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 17f473568b..df14925037 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -44,7 +44,7 @@ namespace Kyra { -#define RESFILE_VERSION 39 +#define RESFILE_VERSION 40 namespace { bool checkKyraDat(Common::SeekableReadStream *file) { @@ -387,6 +387,12 @@ bool StaticResource::init() { //{ lolCharDefsUnk, lolRawDataBe16, "CHUNK.DEF" }, { lolCharDefsAkshel, lolRawDataBe16, "CHAKSHEL.DEF" }, { lolExpRequirements, lolRawDataBe32, "EXPERIENCE.DEF" }, + { lolMonsterModifiers, lolRawDataBe16, "MONSTMOD.DEF" }, + { lolMonsterLevelOffsets, kRawData, "MONSTLVL.DEF" }, + { lolMonsterDirFlags, kRawData, "MONSTDIR.DEF" }, + { lolMonsterScaleY, kRawData, "MONSTZY.DEF" }, + { lolMonsterScaleX, kRawData, "MONSTZX.DEF" }, + { lolMonsterScaleWH, lolRawDataBe16, "MONSTSCL.DEF" }, { lolInventoryDesc, lolRawDataBe16, "INVDESC.DEF" }, { lolLevelShpList, kStringList, "SHPFILES.TXT" }, @@ -1731,6 +1737,12 @@ void LoLEngine::initStaticResource() { _charDefsKieran = _staticres->loadRawDataBe16(lolCharDefsKieran, _charDefsKieranSize); _charDefsAkshel = _staticres->loadRawDataBe16(lolCharDefsAkshel, _charDefsAkshelSize); _expRequirements = (const int32*)_staticres->loadRawDataBe32(lolExpRequirements, _expRequirementsSize); + _monsterModifiers = _staticres->loadRawDataBe16(lolMonsterModifiers, _monsterModifiersSize); + _monsterLevelOffs = (const int8*)_staticres->loadRawData(lolMonsterLevelOffsets, _monsterLevelOffsSize); + _monsterDirFlags = _staticres->loadRawData(lolMonsterDirFlags, _monsterDirFlagsSize); + _monsterScaleX = (const int8*)_staticres->loadRawData(lolMonsterScaleX, _monsterScaleXSize); + _monsterScaleY = (const int8*)_staticres->loadRawData(lolMonsterScaleY, _monsterScaleYSize); + _monsterScaleWH = _staticres->loadRawDataBe16(lolMonsterScaleWH, _monsterScaleWHSize); _inventorySlotDesc = _staticres->loadRawDataBe16(lolInventoryDesc, _inventorySlotDescSize); _levelShpList = _staticres->loadStrings(lolLevelShpList, _levelShpListSize); _levelDatList = _staticres->loadStrings(lolLevelDatList, _levelDatListSize); @@ -1847,8 +1859,8 @@ void LoLEngine::assignButtonCallback(Button *button, int index) { cb(clickedInventorySlot), cb(clickedInventoryScroll), cb(clickedInventoryScroll), - cb(clickedScenePressSwitch), - cb(clickedScenePressSwitch), + cb(clickedWall), + cb(clickedWall), cb(clickedScene), cb(clickedUpArrow), cb(clickedDownArrow), diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index ab94d97101..994c691aa8 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -35,8 +35,8 @@ void LoLEngine::setupTimers() { debugC(9, kDebugLevelMain | kDebugLevelTimer, "LoLEngine::setupTimers()"); _timer->addTimer(0, TimerV2(timerProcessOpenDoor), 15, true); - _timer->addTimer(0x10, TimerV2(timerSub2), 6, true); - _timer->addTimer(0x11, TimerV2(timerSub2), 6, true); + _timer->addTimer(0x10, TimerV2(timerProcessMonsters), 6, true); + _timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true); _timer->setNextRun(0x11, 3); _timer->addTimer(3, TimerV2(timerSub3), 15, true); _timer->addTimer(4, TimerV2(timerSub4), 1, true); @@ -58,8 +58,12 @@ void LoLEngine::timerProcessOpenDoor(int timerNum) { } -void LoLEngine::timerSub2(int timerNum) { +void LoLEngine::timerProcessMonsters(int timerNum) { + //if (!_updateMonsters) + // return; + for (int i = timerNum & 0x0f; i < 30; i += 2) + updateMonster(&_monsters[i]); } void LoLEngine::timerSub3(int timerNum) { diff --git a/tools/create_kyradat/create_kyradat.cpp b/tools/create_kyradat/create_kyradat.cpp index 4ec75d653c..6ed270638e 100644 --- a/tools/create_kyradat/create_kyradat.cpp +++ b/tools/create_kyradat/create_kyradat.cpp @@ -31,7 +31,7 @@ #include "md5.h" enum { - kKyraDatVersion = 39, + kKyraDatVersion = 40, kIndexSize = 12 }; @@ -284,6 +284,12 @@ const ExtractFilename extractFilenames[] = { //{ lolCharDefsUnk, lolTypeRaw16, "CHUNK.DEF" }, { lolCharDefsAkshel, lolTypeRaw16, "CHAKSHEL.DEF" }, { lolExpRequirements, lolTypeRaw32, "EXPERIENCE.DEF" }, + { lolMonsterModifiers, lolTypeRaw16, "MONSTMOD.DEF" }, + { lolMonsterLevelOffsets, kTypeRawData, "MONSTLVL.DEF" }, + { lolMonsterDirFlags, kTypeRawData, "MONSTDIR.DEF" }, + { lolMonsterScaleY, kTypeRawData, "MONSTZY.DEF" }, + { lolMonsterScaleX, kTypeRawData, "MONSTZX.DEF" }, + { lolMonsterScaleWH, lolTypeRaw16, "MONSTSCL.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 ecd7bdd81e..10ce7494fb 100644 --- a/tools/create_kyradat/create_kyradat.h +++ b/tools/create_kyradat/create_kyradat.h @@ -193,6 +193,12 @@ enum kExtractID { //lolCharDefsUnk, lolCharDefsAkshel, lolExpRequirements, + lolMonsterModifiers, + lolMonsterLevelOffsets, + lolMonsterDirFlags, + lolMonsterScaleY, + lolMonsterScaleX, + lolMonsterScaleWH, lolInventoryDesc, lolLevelShpList, diff --git a/tools/create_kyradat/lol_cd.h b/tools/create_kyradat/lol_cd.h index 66f49d887d..dfc43c1839 100644 --- a/tools/create_kyradat/lol_cd.h +++ b/tools/create_kyradat/lol_cd.h @@ -16,6 +16,12 @@ const ExtractEntry lolCDFile2[] = { //{ lolCharDefsUnk, 0x0002B508, 0x0002B51A }, { lolCharDefsAkshel, 0x0002B51A, 0x0002B52C }, { lolExpRequirements, 0x0002B830, 0x0002B85C }, + { lolMonsterModifiers, 0x0002B85C, 0x0002B874 }, + { lolMonsterLevelOffsets, 0x00031FDF, 0x00031FFF }, + { lolMonsterDirFlags, 0x00031FFF, 0x0003200F }, + { lolMonsterScaleY, 0x00031BC0, 0x00031BDE }, + { lolMonsterScaleX, 0x00031BDE, 0x00031BFE }, + { lolMonsterScaleWH, 0x000285C0, 0x00028638 }, { lolInventoryDesc, 0x00032706, 0x0003271C }, { lolLevelShpList, 0x00032826, 0x000328A5 }, diff --git a/tools/create_kyradat/misc.h b/tools/create_kyradat/misc.h index 2b865b34a4..fbdaff9e91 100644 --- a/tools/create_kyradat/misc.h +++ b/tools/create_kyradat/misc.h @@ -499,6 +499,12 @@ const int lolCDFile2Need[] = { //lolCharDefsUnk, lolCharDefsAkshel, lolExpRequirements, + lolMonsterModifiers, + lolMonsterLevelOffsets, + lolMonsterDirFlags, + lolMonsterScaleY, + lolMonsterScaleX, + lolMonsterScaleWH, lolInventoryDesc, lolLevelShpList, -- cgit v1.2.3