aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/kyra/animator_v3.cpp31
-rw-r--r--engines/kyra/items_v3.cpp270
-rw-r--r--engines/kyra/kyra_v3.cpp20
-rw-r--r--engines/kyra/kyra_v3.h19
-rw-r--r--engines/kyra/screen.h8
-rw-r--r--engines/kyra/screen_v3.cpp63
-rw-r--r--engines/kyra/screen_v3.h6
-rw-r--r--engines/kyra/staticres.cpp6
8 files changed, 417 insertions, 6 deletions
diff --git a/engines/kyra/animator_v3.cpp b/engines/kyra/animator_v3.cpp
index 31212e631a..5acfb76196 100644
--- a/engines/kyra/animator_v3.cpp
+++ b/engines/kyra/animator_v3.cpp
@@ -605,5 +605,36 @@ void KyraEngine_v3::resetNewShapes(int count, uint8 *filedata) {
setNextIdleAnimTimer();
}
+void KyraEngine_v3::addItemToAnimList(int item) {
+ debugC(9, kDebugLevelAnimator, "KyraEngine_v3::addItemToAnimList(%d)", item);
+ restorePage3();
+
+ AnimObj *animObj = &_animObjects[17+item];
+
+ animObj->enabled = 1;
+ animObj->needRefresh = 1;
+
+ int itemId = _itemList[item].id;
+
+ animObj->xPos2 = animObj->xPos1 = _itemList[item].x;
+ animObj->yPos2 = animObj->yPos1 = _itemList[item].y;
+
+ animObj->shapePtr = getShapePtr(248+itemId);
+ animSetupPaletteEntry(animObj);
+ animObj->shapeIndex2 = animObj->shapeIndex = 248+itemId;
+
+ int scaleY, scaleX;
+ scaleY = scaleX = getScale(animObj->xPos1, animObj->yPos1);
+
+ uint8 *shapePtr = getShapePtr(248+itemId);
+ animObj->xPos3 = (animObj->xPos2 -= (_screen->getShapeScaledWidth(shapePtr, scaleX) >> 1));
+ animObj->yPos3 = (animObj->yPos2 -= _screen->getShapeScaledHeight(shapePtr, scaleY));
+
+ animObj->width2 = animObj->height2 = 0;
+
+ _animList = addToAnimListSorted(_animList, animObj);
+ animObj->needRefresh = 1;
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/items_v3.cpp b/engines/kyra/items_v3.cpp
index 38359de446..8cb3980356 100644
--- a/engines/kyra/items_v3.cpp
+++ b/engines/kyra/items_v3.cpp
@@ -42,6 +42,18 @@ void KyraEngine_v3::resetItemList() {
resetItem(i);
}
+void KyraEngine_v3::removeTrashItems() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::removeTrashItems()");
+ for (int i = 0; _trashItemList[i] != 0xFF; ++i) {
+ for (int item = findItem(_trashItemList[i]); item != -1; item = findItem(_trashItemList[i])) {
+ if (_itemList[item].sceneId != _mainCharacter.sceneId)
+ resetItem(item);
+ else
+ break;
+ }
+ }
+}
+
int KyraEngine_v3::findFreeItem() {
debugC(9, kDebugLevelMain, "KyraEngine_v3::findFreeItem()");
for (int i = 0; i < 50; ++i) {
@@ -60,6 +72,27 @@ int KyraEngine_v3::findItem(uint16 sceneId, uint16 id) {
return -1;
}
+int KyraEngine_v3::findItem(uint16 item) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::findItem(%u)", item);
+ for (int i = 0; i < 50; ++i) {
+ if (_itemList[i].id == item)
+ return i;
+ }
+ return -1;
+}
+
+int KyraEngine_v3::countAllItems() {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::countAllItems()");
+ int count = 0;
+
+ for (int i = 0; i < 50; ++i) {
+ if (_itemList[i].id != 0xFFFF)
+ ++count;
+ }
+
+ return count;
+}
+
int KyraEngine_v3::checkItemCollision(int x, int y) {
debugC(9, kDebugLevelMain, "KyraEngine_v3::checkItemCollision(%d, %d)", x, y);
int itemIndex = -1;
@@ -138,5 +171,242 @@ void KyraEngine_v3::removeHandItem() {
_screen->showMouse();
}
+bool KyraEngine_v3::dropItem(int unk1, uint16 item, int x, int y, int unk2) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::dropItem(%d, %d, %d, %d, %d)", unk1, item, x, y, unk2);
+
+ if (_handItemSet <= -1)
+ return false;
+
+ if (processItemDrop(_mainCharacter.sceneId, item, x, y, unk1, unk2))
+ return true;
+
+ playSoundEffect(13, 200);
+
+ if (countAllItems() >= 50) {
+ removeTrashItems();
+ if (processItemDrop(_mainCharacter.sceneId, item, x, y, unk1, unk2))
+ return true;
+
+ //if (countAllItems() >= 50)
+ //showMessageFromCCode(14, 0xB3, 0);
+ }
+
+ if (!_chatText)
+ playSoundEffect(13, 200);
+ return false;
+}
+
+bool KyraEngine_v3::processItemDrop(uint16 sceneId, uint16 item, int x, int y, int unk1, int unk2) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::processItemDrop(%d, %d, %d, %d, %d, %d)", sceneId, item, x, y, unk1, unk2);
+
+ int itemPos = checkItemCollision(x, y);
+
+ if (unk1)
+ itemPos = -1;
+
+ if (itemPos >= 0) {
+ exchangeMouseItem(itemPos, 1);
+ return true;
+ }
+
+ int freeItemSlot = -1;
+
+ if (unk2 != 3) {
+ for (int i = 0; i < 50; ++i) {
+ if (_itemList[i].id == 0xFFFF) {
+ freeItemSlot = i;
+ break;
+ }
+ }
+ }
+
+ if (freeItemSlot < 0)
+ return false;
+
+ if (_mainCharacter.sceneId != sceneId) {
+ _itemList[freeItemSlot].x = x;
+ _itemList[freeItemSlot].y = y;
+ _itemList[freeItemSlot].id = item;
+ _itemList[freeItemSlot].unk8 = 1;
+ _itemList[freeItemSlot].sceneId = sceneId;
+ return true;
+ }
+
+ int itemHeight = _itemBuffer1[item];
+
+ // no idea why it's '&&' here and not single checks for x and y
+ if (x == -1 && y == -1) {
+ x = _rnd.getRandomNumberRng(0x18, 0x128);
+ y = _rnd.getRandomNumberRng(0x14, 0x87);
+ }
+
+ int posX = x, posY = y;
+ int itemX = -1, itemY = -1;
+ bool needRepositioning = true;
+
+ while (needRepositioning) {
+ if ((_screen->getDrawLayer(posX, posY) <= 1 && _screen->getDrawLayer2(posX, posY, itemHeight) <= 1 && isDropable(posX, posY)) || posY == 187) {
+ int posX2 = posX, posX3 = posX;
+ bool repositioning = true;
+
+ while (repositioning) {
+ if (isDropable(posX3, posY) && _screen->getDrawLayer2(posX3, posY, itemHeight) < 7 && checkItemCollision(posX3, posY) == -1) {
+ itemX = posX3;
+ itemY = posY;
+ needRepositioning = false;
+ repositioning = false;
+ }
+
+ if (isDropable(posX2, posY) && _screen->getDrawLayer2(posX2, posY, itemHeight) < 7 && checkItemCollision(posX2, posY) == -1) {
+ itemX = posX2;
+ itemY = posY;
+ needRepositioning = false;
+ repositioning = false;
+ }
+
+ if (repositioning) {
+ posX3 = MAX(posX3 - 2, 24);
+ posX2 = MIN(posX2 + 2, 296);
+
+ if (posX3 <= 24 && posX2 >= 296)
+ repositioning = false;
+ }
+ }
+ }
+
+ if (posY == 187)
+ needRepositioning = false;
+ else
+ posY = MIN(posY + 2, 187);
+ }
+
+ if (itemX == -1 || itemY == -1)
+ return false;
+
+ if (unk1 == 3) {
+ _itemList[freeItemSlot].x = itemX;
+ _itemList[freeItemSlot].y = itemY;
+ return true;
+ } else if (unk1 == 2) {
+ itemDropDown(x, y, itemX, itemY, freeItemSlot, item, 0);
+ }
+
+ itemDropDown(x, y, itemX, itemY, freeItemSlot, item, (unk1 == 0) ? 1 : 0);
+
+ if (!unk1 && unk2) {
+ //int itemStr = 1;
+ //if (_lang == 1)
+ // itemStr = getItemCommandStringDrop(item);
+ //updateCommandLineEx(item+54, itemStr, 0xD6);
+ }
+
+ return true;
+}
+
+void KyraEngine_v3::itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, uint16 item, int remove) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v2::itemDropDown(%d, %d, %d, %d, %d, %u, %d)", startX, startY, dstX, dstY, itemSlot, item, remove);
+ if (startX == dstX && startY == dstY) {
+ _itemList[itemSlot].x = dstX;
+ _itemList[itemSlot].y = dstY;
+ _itemList[itemSlot].id = item;
+ _itemList[itemSlot].sceneId = _mainCharacter.sceneId;
+ playSoundEffect(0x0C, 0xC8);
+ addItemToAnimList(itemSlot);
+ } else {
+ uint8 *itemShape = getShapePtr(item + 248);
+ _screen->hideMouse();
+
+ if (startY <= dstY) {
+ int speed = 2;
+ int curY = startY;
+ int curX = startX - 12;
+
+ backUpGfxRect32x32(curX, curY-16);
+ while (curY < dstY) {
+ restoreGfxRect32x32(curX, curY-16);
+
+ curY = MIN(curY + speed, dstY);
+ ++speed;
+
+ backUpGfxRect32x32(curX, curY-16);
+ uint32 endDelay = _system->getMillis() + _tickLength;
+
+ _screen->drawShape(0, itemShape, curX, curY-16, 0, 0);
+ _screen->updateScreen();
+
+ delayUntil(endDelay);
+ }
+ restoreGfxRect32x32(curX, curY-16);
+
+ if (dstX != dstY || (dstY - startY > 16)) {
+ playSoundEffect(0x11, 0xC8);
+ speed = MAX(speed, 6);
+ int speedX = ((dstX - startX) << 4) / speed;
+ int origSpeed = speed;
+ speed >>= 1;
+
+ if (dstY - startY <= 8)
+ speed >>= 1;
+
+ speed = -speed;
+
+ curX = startX << 4;
+
+ int x = 0, y = 0;
+ while (--origSpeed) {
+ curY = MIN(curY + speed, dstY);
+ curX += speedX;
+ ++speed;
+
+ x = (curX >> 4) - 8;
+ y = curY - 16;
+ backUpGfxRect32x32(x, y);
+
+ uint16 endDelay = _system->getMillis() + _tickLength;
+ _screen->drawShape(0, itemShape, x, y, 0, 0);
+ _screen->updateScreen();
+
+ restoreGfxRect32x32(x, y);
+
+ delayUntil(endDelay);
+ }
+
+ restoreGfxRect32x32(x, y);
+ }
+ }
+
+ _itemList[itemSlot].x = dstX;
+ _itemList[itemSlot].y = dstY;
+ _itemList[itemSlot].id = item;
+ _itemList[itemSlot].sceneId = _mainCharacter.sceneId;
+ playSoundEffect(0x0C, 0xC8);
+ addItemToAnimList(itemSlot);
+ _screen->showMouse();
+ }
+
+ if (remove)
+ removeHandItem();
+}
+
+void KyraEngine_v3::exchangeMouseItem(int itemPos, int runScript) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::exchangeMouseItem(%d, %d)", itemPos, runScript);
+ //XXX
+}
+
+bool KyraEngine_v3::isDropable(int x, int y) {
+ debugC(9, kDebugLevelMain, "KyraEngine_v3::isDropable(%d, %d)", x, y);
+ if (y < 14 || y > 187)
+ return false;
+
+ x -= 12;
+
+ for (int xpos = x; xpos < x + 24; ++xpos) {
+ if (_screen->getShapeFlag1(xpos, y) == 0)
+ return false;
+ }
+
+ return true;
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/kyra_v3.cpp b/engines/kyra/kyra_v3.cpp
index 0c0b5e2415..6f12cb0fa4 100644
--- a/engines/kyra/kyra_v3.cpp
+++ b/engines/kyra/kyra_v3.cpp
@@ -1054,7 +1054,14 @@ void KyraEngine_v3::handleInput(int x, int y) {
if (runSceneScript2())
return;
} else if (_itemInHand >= 0 && _unk3 >= 0) {
- //XXX
+ if (_itemInHand == 27) {
+ makeCharFacingMouse();
+ } else if (y <= 187) {
+ if (_itemInHand == 43)
+ removeHandItem();
+ else
+ dropItem(0, _itemInHand, x, y, 1);
+ }
return;
} else if (_unk3 == -3) {
return;
@@ -1422,6 +1429,17 @@ void KyraEngine_v3::resetSkipFlag(bool removeEvent) {
}
}
+void KyraEngine_v3::makeCharFacingMouse() {
+ debugC(9, kDebugLevelAnimator, "KyraEngine_v3::makeCharFacingMouse()");
+ if (_mainCharacter.x1 > _mouseX)
+ _mainCharacter.facing = 5;
+ else
+ _mainCharacter.facing = 3;
+ _mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+ updateCharacterAnim(0);
+ refreshAnimObjectsIfNeed();
+}
+
#pragma mark -
int KyraEngine_v3::getDrawLayer(int x, int y) {
diff --git a/engines/kyra/kyra_v3.h b/engines/kyra/kyra_v3.h
index e9036a61a4..dd7164a668 100644
--- a/engines/kyra/kyra_v3.h
+++ b/engines/kyra/kyra_v3.h
@@ -236,6 +236,8 @@ private:
bool _nextIdleType;
void showIdleAnim();
+ void addItemToAnimList(int item);
+
// interface
uint8 *_interface;
uint8 *_interfaceCommandLine;
@@ -297,17 +299,30 @@ private:
void resetItem(int index);
void resetItemList();
+ static const uint8 _trashItemList[];
+ void removeTrashItems();
int findFreeItem();
int findItem(uint16 item, uint16 scene);
+ int findItem(uint16 item);
+
+ int countAllItems();
void initItems();
int checkItemCollision(int x, int y);
- void setMouseCursor(uint16 item);
+ bool dropItem(int unk1, uint16 item, int x, int y, int unk2);
+ bool processItemDrop(uint16 sceneId, uint16 item, int x, int y, int unk1, int unk2);
+ void itemDropDown(int startX, int startY, int dstX, int dstY, int itemSlot, uint16 item, int remove);
+ void exchangeMouseItem(int itemPos, int runScript);
+ bool pickUpItem(int x, int y);
+
+ bool isDropable(int x, int y);
// -> hand item
+ void setMouseCursor(uint16 item);
+
void setHandItem(uint16 item);
void removeHandItem();
void setItemMouseCursor();
@@ -480,6 +495,8 @@ private:
int _malcolmsMood;
+ void makeCharFacingMouse();
+
// talk object
struct TalkObject {
char filename[13];
diff --git a/engines/kyra/screen.h b/engines/kyra/screen.h
index 4516d4f907..ed69e9260e 100644
--- a/engines/kyra/screen.h
+++ b/engines/kyra/screen.h
@@ -201,11 +201,11 @@ public:
void setShapePages(int page1, int page2, int minY = -1, int maxY = 201);
- byte getShapeFlag1(int x, int y);
- byte getShapeFlag2(int x, int y);
+ virtual byte getShapeFlag1(int x, int y);
+ virtual byte getShapeFlag2(int x, int y);
- int getDrawLayer(int x, int y);
- int getDrawLayer2(int x, int y, int height);
+ virtual int getDrawLayer(int x, int y);
+ virtual int getDrawLayer2(int x, int y, int height);
void blockInRegion(int x, int y, int width, int height);
void blockOutRegion(int x, int y, int width, int height);
diff --git a/engines/kyra/screen_v3.cpp b/engines/kyra/screen_v3.cpp
index 7e152e055c..938307b774 100644
--- a/engines/kyra/screen_v3.cpp
+++ b/engines/kyra/screen_v3.cpp
@@ -72,4 +72,67 @@ int Screen_v3::getLayer(int x, int y) {
return pixel;
}
+byte Screen_v3::getShapeFlag1(int x, int y) {
+ debugC(9, kDebugLevelScreen, "Screen_v3::getShapeFlag1(%d, %d)", x, y);
+ if (y < _maskMinY || y > _maskMaxY)
+ return 0;
+
+ uint8 color = _shapePages[0][y * SCREEN_W + x];
+ color &= 0x80;
+ color ^= 0x80;
+
+ if (color & 0x80)
+ return 1;
+ return 0;
+}
+
+byte Screen_v3::getShapeFlag2(int x, int y) {
+ debugC(9, kDebugLevelScreen, "Screen_v3::getShapeFlag2(%d, %d)", x, y);
+ if (y < _maskMinY || y > _maskMaxY)
+ return 0;
+
+ uint8 color = _shapePages[0][y * SCREEN_W + x];
+ color &= 0x7F;
+ color &= 0x87;
+ return color;
+}
+
+int Screen_v3::getDrawLayer(int x, int y) {
+ debugC(9, kDebugLevelScreen, "Screen_v3::getDrawLayer(%d, %d)", x, y);
+ int xpos = x - 8;
+ int ypos = y;
+ int layer = 1;
+
+ for (int curX = xpos; curX < xpos + 24; ++curX) {
+ int tempLayer = getShapeFlag2(curX, ypos);
+
+ if (layer < tempLayer)
+ layer = tempLayer;
+
+ if (layer >= 7)
+ return 7;
+ }
+ return layer;
+}
+
+int Screen_v3::getDrawLayer2(int x, int y, int height) {
+ debugC(9, kDebugLevelScreen, "Screen_v3::getDrawLayer2(%d, %d, %d)", x, y, height);
+ int xpos = x - 8;
+ int ypos = y;
+ int layer = 1;
+
+ for (int useX = xpos; useX < xpos + 24; ++useX) {
+ for (int useY = ypos - height; useY < ypos; ++useY) {
+ int tempLayer = getShapeFlag2(useX, useY);
+
+ if (tempLayer > layer)
+ layer = tempLayer;
+
+ if (tempLayer >= 7)
+ return 7;
+ }
+ }
+ return layer;
+}
+
} // end of namespace Kyra
diff --git a/engines/kyra/screen_v3.h b/engines/kyra/screen_v3.h
index 0a91b04c0c..dc49268ad6 100644
--- a/engines/kyra/screen_v3.h
+++ b/engines/kyra/screen_v3.h
@@ -41,6 +41,12 @@ public:
virtual const ScreenDim *getScreenDim(int dim);
int getLayer(int x, int y);
+
+ byte getShapeFlag1(int x, int y);
+ byte getShapeFlag2(int x, int y);
+
+ int getDrawLayer(int x, int y);
+ int getDrawLayer2(int x, int y, int height);
private:
static const ScreenDim _screenDimTable[];
static const int _screenDimTableCount;
diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp
index c80284531d..2d564393ef 100644
--- a/engines/kyra/staticres.cpp
+++ b/engines/kyra/staticres.cpp
@@ -2336,6 +2336,12 @@ const uint8 KyraEngine_v3::_inventoryY[] = {
0xB2, 0xB2, 0xB2, 0xB2, 0xB2
};
+const uint8 KyraEngine_v3::_trashItemList[] = {
+ 0x1E, 0x1D, 0x1C, 0x1F, 0x0F, 0x05, 0x04, 0x00,
+ 0x03, 0x22, 0x0B, 0x20, 0x21, 0x10, 0x11, 0x3A,
+ 0x39, 0x40, 0x3E, 0x3D, 0x3C, 0x3F, 0xFF
+};
+
} // End of namespace Kyra