aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorFlorian Kagerer2009-03-01 14:45:30 +0000
committerFlorian Kagerer2009-03-01 14:45:30 +0000
commit7ea5cefef4fb1ef9db52cbf5df7f884770113684 (patch)
tree7ad307cd465c99268b7adc8a8054467df4e6e581 /engines
parent40c4733124a43fb2e921efd07a782ed1688cbc90 (diff)
downloadscummvm-rg350-7ea5cefef4fb1ef9db52cbf5df7f884770113684.tar.gz
scummvm-rg350-7ea5cefef4fb1ef9db52cbf5df7f884770113684.tar.bz2
scummvm-rg350-7ea5cefef4fb1ef9db52cbf5df7f884770113684.zip
LOL: implemented some monster related code (monsters now get placed in the maze, but they still don't do anything)
svn-id: r39039
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/gui_lol.cpp10
-rw-r--r--engines/kyra/items_lol.cpp34
-rw-r--r--engines/kyra/lol.cpp40
-rw-r--r--engines/kyra/lol.h149
-rw-r--r--engines/kyra/module.mk1
-rw-r--r--engines/kyra/resource.h6
-rw-r--r--engines/kyra/scene_lol.cpp433
-rw-r--r--engines/kyra/screen.cpp21
-rw-r--r--engines/kyra/screen.h2
-rw-r--r--engines/kyra/script_lol.cpp141
-rw-r--r--engines/kyra/sprites_lol.cpp942
-rw-r--r--engines/kyra/staticres.cpp18
-rw-r--r--engines/kyra/timer_lol.cpp10
13 files changed, 1308 insertions, 499 deletions
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<const TIMOpcode*>::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) {