diff options
| author | Johannes Schickel | 2008-04-23 22:53:19 +0000 | 
|---|---|---|
| committer | Johannes Schickel | 2008-04-23 22:53:19 +0000 | 
| commit | 6562a7cd8abae364b1ca481e4cbdab8f422feaf9 (patch) | |
| tree | 835cb0300738946d6b3f723b543a996b3720b6a0 | |
| parent | bed4037abf90ebc8a8d696488f40da2513647823 (diff) | |
| download | scummvm-rg350-6562a7cd8abae364b1ca481e4cbdab8f422feaf9.tar.gz scummvm-rg350-6562a7cd8abae364b1ca481e4cbdab8f422feaf9.tar.bz2 scummvm-rg350-6562a7cd8abae364b1ca481e4cbdab8f422feaf9.zip | |
Implemented parts of item drop down code for Kyra3.
svn-id: r31681
| -rw-r--r-- | engines/kyra/animator_v3.cpp | 31 | ||||
| -rw-r--r-- | engines/kyra/items_v3.cpp | 270 | ||||
| -rw-r--r-- | engines/kyra/kyra_v3.cpp | 20 | ||||
| -rw-r--r-- | engines/kyra/kyra_v3.h | 19 | ||||
| -rw-r--r-- | engines/kyra/screen.h | 8 | ||||
| -rw-r--r-- | engines/kyra/screen_v3.cpp | 63 | ||||
| -rw-r--r-- | engines/kyra/screen_v3.h | 6 | ||||
| -rw-r--r-- | engines/kyra/staticres.cpp | 6 | 
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 | 
