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