aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/items_lol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra/items_lol.cpp')
-rw-r--r--engines/kyra/items_lol.cpp200
1 files changed, 186 insertions, 14 deletions
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);