[Scummvm-git-logs] scummvm master -> 097b9192959b0c109309777fd70edf9aa0a41e5d

mgerhardy martin.gerhardy at gmail.com
Thu Feb 25 18:36:03 UTC 2021


This automated email contains information about 34 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
1b4bffe1ad TWINE: drawBubble only updates the screen if the sprite wasn't culled
323ca6e8e4 TWINE: check for invalid clip rect in drawBrickSprite
c8108fbff1 TWINE: use the clipped rect in drawTransparentBox
ba92c33d81 TWINE: the scummvm rect is exclusive the right and bottom position
f4f82c2b35 TWINE: extracted drawInfoMenu into single methods
b34d716baf TWINE: reduced code duplication for drawBox
7779b3e6e1 TWINE: center the info and behaviour menu
8eae73031c TWINE: doxygen
8a34640538 TWINE: use color constants
99783c08a9 TWINE: render the inventory menu centered on the screen in high-res mode
55e0f3afea TWINE: introduced new angle constant
c5df2813e6 TWINE: moved defines
e342415d31 TWINE: reduced itemAngle array size
89f81a020d TWINE: reduced magic numbers in inventory menu
86131a3fb6 TWINE: center the on-screen keyboard for high resolution mode
d53f163e67 TWINE: extract to local variables
ee7ac5572a TWINE: added centerOnActor method
e79b109a61 TWINE: converted to Vec3
1b14ab2919 TWINE: moved centerScreenOnActor into Grid class
a819f61e8c TWINE: moved actor position into Vec3 struct
63a27de46f TWINE: converted lastPos to Vec3 struct
91e34e1307 TWINE: convertged collision position to Vec3 struct
eaf9de0bf0 TWINE: converted shadow coordinates to Vec3 struct
fda3ccc4df TWINE: converted more positions to Vec3
ec34077906 TWINE: converted more positions to Vec3
87893749b5 TWINE: new color constant
290b5de7e4 TWINE: converted hero position to Vec3 struct
baadba59a8 TWINE: use Vec3 copy
2d3bd0bfb9 TWINE: converted scene hero positions to Vec3 struct
010dccc785 TWINE: added projectPositionOnScreen Vec3 variant
e3d413d2fe TWINE: added debug command set_life
ca3375e7b4 TWINE: don't close the debug console for invalid parameters
2f62076720 TWINE: re-added constants for original window dimensions
097b919295 TWINE: fixed position of game-over animation in high-res mode


Commit: 1b4bffe1adec81e31cc368819df02d1eda236651
    https://github.com/scummvm/scummvm/commit/1b4bffe1adec81e31cc368819df02d1eda236651
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: drawBubble only updates the screen if the sprite wasn't culled

Changed paths:
    engines/twine/renderer/redraw.cpp
    engines/twine/scene/grid.cpp
    engines/twine/scene/grid.h


diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index 25096685c6..551280bc19 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -771,9 +771,7 @@ void Redraw::drawBubble(int32 actorIdx) {
 
 	_engine->_interface->setClip(renderRect);
 
-	_engine->_grid->drawSprite(renderRect.left, renderRect.top, spritePtr);
-	// TODO: shouldn't we check for renderRect here?
-	if (_engine->_interface->textWindow.left <= _engine->_interface->textWindow.right && _engine->_interface->textWindow.top <= _engine->_interface->textWindow.bottom) {
+	if (_engine->_grid->drawSprite(renderRect.left, renderRect.top, spritePtr)) {
 		_engine->copyBlockPhys(renderRect, true);
 	}
 
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index 19168b6186..b4884cfc3d 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -292,18 +292,18 @@ void Grid::loadGridBricks() {
 
 	// for all bits under the 32bytes (256bits)
 	for (uint32 i = 1; i < 256; i++) {
-		uint8 currentBitByte = *(ptrToBllBits + (i / 8));
-		uint8 currentBitMask = 1 << (7 - (i & 7));
+		const uint8 currentBitByte = *(ptrToBllBits + (i / 8));
+		const uint8 currentBitMask = 1 << (7 - (i & 7));
 
 		if (currentBitByte & currentBitMask) {
 			uint32 currentBllOffset = READ_LE_UINT32(currentBll + currentBllEntryIdx);
 			const uint8 *currentBllPtr = currentBll + currentBllOffset;
 
-			uint32 bllSizeX = *currentBllPtr++;
-			uint32 bllSizeY = *currentBllPtr++;
-			uint32 bllSizeZ = *currentBllPtr++;
+			const uint32 bllSizeX = *currentBllPtr++;
+			const uint32 bllSizeY = *currentBllPtr++;
+			const uint32 bllSizeZ = *currentBllPtr++;
 
-			uint32 bllSize = bllSizeX * bllSizeY * bllSizeZ;
+			const uint32 bllSize = bllSizeX * bllSizeY * bllSizeZ;
 
 			for (uint32 j = 0; j < bllSize; j++) {
 				/* const uint8 type = * */currentBllPtr++;
@@ -476,53 +476,54 @@ bool Grid::initCellingGrid(int32 index) {
 	return true;
 }
 
-void Grid::drawBrick(int32 index, int32 posX, int32 posY) {
-	drawBrickSprite(index, posX, posY, brickTable[index], false);
+bool Grid::drawBrick(int32 index, int32 posX, int32 posY) {
+	return drawBrickSprite(index, posX, posY, brickTable[index], false);
 }
 
-void Grid::drawSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr) {
+bool Grid::drawSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr) {
 	ptr = ptr + READ_LE_INT32(ptr + index * 4);
-	drawBrickSprite(index, posX, posY, ptr, true);
+	return drawBrickSprite(index, posX, posY, ptr, true);
 }
 
-void Grid::drawSprite(int32 posX, int32 posY, const SpriteData &ptr) {
+bool Grid::drawSprite(int32 posX, int32 posY, const SpriteData &ptr) {
 	const int32 left = posX + ptr.offsetX();
 	if (left > _engine->_interface->textWindow.right) {
-		return;
+		return false;
 	}
 	const int32 right = ptr.surface().w + left;
 	if (right < _engine->_interface->textWindow.left) {
-		return;
+		return false;
 	}
 	const int32 top = posY + ptr.offsetY();
 	if (top > _engine->_interface->textWindow.bottom) {
-		return;
+		return false;
 	}
 	const int32 bottom = ptr.surface().h + top;
 	if (bottom < _engine->_interface->textWindow.top) {
-		return;
+		return false;
 	}
 
 	_engine->frontVideoBuffer.transBlitFrom(ptr.surface(), Common::Point(left, top));
+	return true;
 }
 
 // WARNING: Rewrite this function to have better performance
-void Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr, bool isSprite) {
+bool Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr, bool isSprite) {
 	const int32 left = posX + *(ptr + 2);
 	if (left > _engine->_interface->textWindow.right) {
-		return;
+		return false;
 	}
 	const int32 right = *ptr + left;
 	if (right < _engine->_interface->textWindow.left) {
-		return;
+		return false;
 	}
 	const int32 top = posY + *(ptr + 3);
 	if (top > _engine->_interface->textWindow.bottom) {
-		return;
+		return false;
 	}
 	const int32 bottom = (int32)*(ptr + 1) + top;
 	if (bottom < _engine->_interface->textWindow.top) {
-		return;
+		return false;
 	}
 	const int32 maxY = MIN(bottom, (int32)_engine->_interface->textWindow.bottom);
 
@@ -578,6 +579,7 @@ void Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr
 			x = left;
 		}
 	}
+	return true;
 }
 
 uint8 *Grid::getBlockBuffer(int32 x, int32 y, int32 z) {
diff --git a/engines/twine/scene/grid.h b/engines/twine/scene/grid.h
index a6a0f9c4ae..f1539f4ebe 100644
--- a/engines/twine/scene/grid.h
+++ b/engines/twine/scene/grid.h
@@ -246,7 +246,7 @@ public:
 	 * @param posX brick X position to draw
 	 * @param posY brick Y position to draw
 	 */
-	void drawBrick(int32 index, int32 posX, int32 posY);
+	bool drawBrick(int32 index, int32 posX, int32 posY);
 
 	/**
 	 * Draw sprite in the screen
@@ -255,8 +255,8 @@ public:
 	 * @param posY sprite Y position to draw
 	 * @param ptr sprite buffer pointer to draw
 	 */
-	void drawSprite(int32 index, int32 posX, int32 posY, const uint8 *spritePtr);
-	void drawSprite(int32 posX, int32 posY, const SpriteData &ptr);
+	bool drawSprite(int32 index, int32 posX, int32 posY, const uint8 *spritePtr);
+	bool drawSprite(int32 posX, int32 posY, const SpriteData &ptr);
 
 	/**
 	 * Draw sprite or bricks in the screen according with the type
@@ -266,7 +266,7 @@ public:
 	 * @param ptr sprite buffer pointer to draw
 	 * @param isSprite allows to identify if the sprite to display is brick or a single sprite
 	 */
-	void drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *spritePtr, bool isSprite);
+	bool drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *spritePtr, bool isSprite);
 
 	/**
 	 * Get block library


Commit: 323ca6e8e4a315599c3d04d0ae77fea74fee1194
    https://github.com/scummvm/scummvm/commit/323ca6e8e4a315599c3d04d0ae77fea74fee1194
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: check for invalid clip rect in drawBrickSprite

Changed paths:
    engines/twine/renderer/redraw.cpp
    engines/twine/scene/grid.cpp


diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index 551280bc19..626554f52b 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -326,9 +326,7 @@ void Redraw::processDrawListShadows(const DrawListStruct &drawCmd) {
 
 	_engine->_interface->setClip(renderRect);
 
-	if (_engine->_interface->textWindow.left <= _engine->_interface->textWindow.right && _engine->_interface->textWindow.top <= _engine->_interface->textWindow.bottom) {
-		_engine->_grid->drawSprite(drawCmd.offset, renderRect.left, renderRect.top, _engine->_resources->spriteShadowPtr);
-	}
+	_engine->_grid->drawSprite(drawCmd.offset, renderRect.left, renderRect.top, _engine->_resources->spriteShadowPtr);
 
 	const int32 tmpX = (drawCmd.x + BRICK_HEIGHT) / BRICK_SIZE;
 	const int32 tmpY = drawCmd.y / BRICK_HEIGHT;
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index b4884cfc3d..14a97d9422 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -509,6 +509,10 @@ bool Grid::drawSprite(int32 posX, int32 posY, const SpriteData &ptr) {
 
 // WARNING: Rewrite this function to have better performance
 bool Grid::drawBrickSprite(int32 index, int32 posX, int32 posY, const uint8 *ptr, bool isSprite) {
+	if (_engine->_interface->textWindow.left > _engine->_interface->textWindow.right || _engine->_interface->textWindow.top > _engine->_interface->textWindow.bottom) {
+		return false;
+	}
+
 	const int32 left = posX + *(ptr + 2);
 	if (left > _engine->_interface->textWindow.right) {
 		return false;


Commit: c8108fbff164c50f044a2b1c09bdeace10498668
    https://github.com/scummvm/scummvm/commit/c8108fbff164c50f044a2b1c09bdeace10498668
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: use the clipped rect in drawTransparentBox

Changed paths:
    engines/twine/menu/interface.cpp


diff --git a/engines/twine/menu/interface.cpp b/engines/twine/menu/interface.cpp
index ed39dac0b3..ec53582ab4 100644
--- a/engines/twine/menu/interface.cpp
+++ b/engines/twine/menu/interface.cpp
@@ -153,10 +153,10 @@ void Interface::drawTransparentBox(const Common::Rect &rect, int32 colorAdj) {
 		return;
 	}
 
-	uint8 *pos = (uint8*)_engine->frontVideoBuffer.getBasePtr(0, rect.top);
+	uint8 *pos = (uint8*)_engine->frontVideoBuffer.getBasePtr(0, r.top);
 
-	for (int32 y = rect.top; y < rect.bottom; ++y) {
-		for (int32 x = rect.left; x < rect.right; ++x) {
+	for (int32 y = r.top; y < r.bottom; ++y) {
+		for (int32 x = r.left; x < r.right; ++x) {
 			const int8 color = (pos[x] & 0x0F) - colorAdj;
 			const int8 color2 = pos[x] & 0xF0;
 			if (color < 0) {


Commit: ba92c33d812cac0e598bb7ca124c9d16ed3ce6d3
    https://github.com/scummvm/scummvm/commit/ba92c33d812cac0e598bb7ca124c9d16ed3ce6d3
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: the scummvm rect is exclusive the right and bottom position

the original game treats this as inclusive. This should fix missing last lines
in the ui

Changed paths:
    engines/twine/menu/interface.cpp


diff --git a/engines/twine/menu/interface.cpp b/engines/twine/menu/interface.cpp
index ec53582ab4..cca553247c 100644
--- a/engines/twine/menu/interface.cpp
+++ b/engines/twine/menu/interface.cpp
@@ -155,8 +155,8 @@ void Interface::drawTransparentBox(const Common::Rect &rect, int32 colorAdj) {
 
 	uint8 *pos = (uint8*)_engine->frontVideoBuffer.getBasePtr(0, r.top);
 
-	for (int32 y = r.top; y < r.bottom; ++y) {
-		for (int32 x = r.left; x < r.right; ++x) {
+	for (int32 y = r.top; y <= r.bottom; ++y) {
+		for (int32 x = r.left; x <= r.right; ++x) {
 			const int8 color = (pos[x] & 0x0F) - colorAdj;
 			const int8 color2 = pos[x] & 0xF0;
 			if (color < 0) {
@@ -170,7 +170,7 @@ void Interface::drawTransparentBox(const Common::Rect &rect, int32 colorAdj) {
 }
 
 void Interface::drawFilledRect(const Common::Rect &rect, uint8 colorIndex) {
-	_engine->frontVideoBuffer.fillRect(rect, colorIndex);
+	_engine->frontVideoBuffer.fillRect(Common::Rect(rect.left, rect.top, rect.right + 1, rect.bottom + 1), colorIndex);
 }
 
 void Interface::setClip(const Common::Rect &rect) {


Commit: f4f82c2b35cf0237cc2ae668dfe695ed7d4be239
    https://github.com/scummvm/scummvm/commit/f4f82c2b35cf0237cc2ae668dfe695ed7d4be239
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: extracted drawInfoMenu into single methods

should make implementing the hud ui easier

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/menu/menu.h


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index fbe9a75d87..5df12a773d 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -808,52 +808,16 @@ int32 Menu::giveupMenu() {
 	return 0;
 }
 
-void Menu::drawInfoMenu(int16 left, int16 top, int16 width) {
-	_engine->_interface->resetClip();
-	const int16 height = 80;
-	const Common::Rect rect(left, top, left + width, top + height);
-	drawBox(rect);
-	Common::Rect splittedBoxRect(rect);
-	splittedBoxRect.grow(-1);
-	_engine->_interface->drawFilledRect(splittedBoxRect, COLOR_BLACK);
-
-	const int32 newBoxLeft2 = left + 9;
-
-	_engine->_grid->drawSprite(newBoxLeft2, top + 13, _engine->_resources->spriteData[SPRITEHQR_LIFEPOINTS]);
-
-	const int32 boxRight = left + 325;
-	const int32 newBoxLeft = left + 25;
-	int32 boxLeft = _engine->_screens->crossDot(newBoxLeft, boxRight, 50, _engine->_scene->sceneHero->life);
-
-	const int32 boxTop = top + 10;
-	const int32 boxBottom = top + 25;
-	_engine->_interface->drawFilledRect(Common::Rect(newBoxLeft, boxTop, boxLeft, boxBottom), COLOR_91);
-	drawBox(newBoxLeft, boxTop, left + 324, boxTop + 14);
-
-	if (!_engine->_gameState->inventoryDisabled() && _engine->_gameState->hasItem(InventoryItems::kiTunic)) {
-		_engine->_grid->drawSprite(newBoxLeft2, top + 36, _engine->_resources->spriteData[SPRITEHQR_MAGICPOINTS]);
-		if (_engine->_gameState->magicLevelIdx > 0) {
-			const int32 pointBoxRight = _engine->_screens->crossDot(newBoxLeft, boxRight, 80, _engine->_gameState->inventoryMagicPoints);
-			const Common::Rect pointsRect(newBoxLeft, top + 35, pointBoxRight, top + 50);
-			_engine->_interface->drawFilledRect(pointsRect, COLOR_75);
-			drawBox(newBoxLeft, top + 35, newBoxLeft + _engine->_gameState->magicLevelIdx * 80, top + 35 + 15);
-		}
-	}
-
-	boxLeft = left + 340;
-
-	/** draw coin sprite */
-	_engine->_grid->drawSprite(boxLeft, top + 15, _engine->_resources->spriteData[SPRITEHQR_KASHES]);
-	_engine->_text->setFontColor(COLOR_GOLD);
-	Common::String inventoryNumKashes = Common::String::format("%d", _engine->_gameState->inventoryNumKashes);
-	_engine->_text->drawText(left + 370, top + 5, inventoryNumKashes.c_str());
-
-	/** draw key sprite */
-	_engine->_grid->drawSprite(boxLeft, top + 55, _engine->_resources->spriteData[SPRITEHQR_KEY]);
-	_engine->_text->setFontColor(COLOR_GOLD);
-	Common::String inventoryNumKeys = Common::String::format("%d", _engine->_gameState->inventoryNumKeys);
-	_engine->_text->drawText(left + 370, top + 40, inventoryNumKeys.c_str());
+void Menu::drawHealthBar(int32 left, int32 right, int32 top, int32 barLeftPadding, int32 barHeight) {
+	_engine->_grid->drawSprite(left, top + 3, _engine->_resources->spriteData[SPRITEHQR_LIFEPOINTS]);
+	const int32 barLeft = left + barLeftPadding;
+	const int32 healthBarRight = _engine->_screens->crossDot(barLeft, right, 50, _engine->_scene->sceneHero->life);
+	const int32 barBottom = top + barHeight;
+	_engine->_interface->drawFilledRect(Common::Rect(barLeft, top, healthBarRight, barBottom), COLOR_91);
+	drawBox(Common::Rect(barLeft, top, right, barBottom));
+}
 
+void Menu::drawCloverLeafs(int32 newBoxLeft, int32 boxRight, int32 top) {
 	// prevent
 	if (_engine->_gameState->inventoryNumLeafs > _engine->_gameState->inventoryNumLeafsBox) {
 		_engine->_gameState->inventoryNumLeafs = _engine->_gameState->inventoryNumLeafsBox;
@@ -861,13 +825,73 @@ void Menu::drawInfoMenu(int16 left, int16 top, int16 width) {
 
 	// Clover leaf boxes
 	for (int32 i = 0; i < _engine->_gameState->inventoryNumLeafsBox; i++) {
-		_engine->_grid->drawSprite(_engine->_screens->crossDot(left + 25, left + 325, 10, i), top + 58, _engine->_resources->spriteData[SPRITEHQR_CLOVERLEAFBOX]);
+		const int32 leftSpritePos = _engine->_screens->crossDot(newBoxLeft, boxRight, 10, i);
+		_engine->_grid->drawSprite(leftSpritePos, top + 58, _engine->_resources->spriteData[SPRITEHQR_CLOVERLEAFBOX]);
 	}
 
 	// Clover leafs
 	for (int32 i = 0; i < _engine->_gameState->inventoryNumLeafs; i++) {
-		_engine->_grid->drawSprite(_engine->_screens->crossDot(left + 25, left + 325, 10, i) + 2, top + 60, _engine->_resources->spriteData[SPRITEHQR_CLOVERLEAF]);
+		const int32 leftSpritePos = _engine->_screens->crossDot(newBoxLeft, boxRight, 10, i);
+		_engine->_grid->drawSprite(leftSpritePos + 2, top + 60, _engine->_resources->spriteData[SPRITEHQR_CLOVERLEAF]);
+	}
+}
+
+void Menu::drawMagicPointsBar(int32 left, int32 right, int32 top, int32 barLeftPadding, int32 barHeight) {
+	if (_engine->_gameState->inventoryDisabled()) {
+		return;
+	}
+	if (!_engine->_gameState->hasItem(InventoryItems::kiTunic)) {
+		return;
+	}
+	_engine->_grid->drawSprite(left, top + 1, _engine->_resources->spriteData[SPRITEHQR_MAGICPOINTS]);
+	if (_engine->_gameState->magicLevelIdx <= 0) {
+		return;
 	}
+	const int32 barLeft = left + barLeftPadding;
+	const int32 barBottom = top + barHeight;
+	const int32 barRight = _engine->_screens->crossDot(barLeft, right, 80, _engine->_gameState->inventoryMagicPoints);
+	const Common::Rect pointsRect(barLeft, top, barRight, barBottom);
+	_engine->_interface->drawFilledRect(pointsRect, COLOR_75);
+	drawBox(barLeft, top, barLeft + _engine->_gameState->magicLevelIdx * 80, barBottom);
+}
+
+void Menu::drawSpriteAndString(int32 left, int32 top, const SpriteData &spriteData, const Common::String &str, int32 color) {
+	_engine->_grid->drawSprite(left, top + 15, spriteData);
+	_engine->_text->setFontColor(color);
+	_engine->_text->drawText(left + 30, top + 5, str.c_str());
+}
+
+void Menu::drawCoins(int32 left, int32 top) {
+	const Common::String &inventoryNumKashes = Common::String::format("%d", _engine->_gameState->inventoryNumKashes);
+	drawSpriteAndString(left, top, _engine->_resources->spriteData[SPRITEHQR_KASHES], inventoryNumKashes);
+}
+
+void Menu::drawKeys(int32 left, int32 top) {
+	const Common::String &inventoryNumKeys = Common::String::format("%d", _engine->_gameState->inventoryNumKeys);
+	drawSpriteAndString(left, top, _engine->_resources->spriteData[SPRITEHQR_KEY], inventoryNumKeys);
+}
+
+void Menu::drawInfoMenu(int16 left, int16 top, int16 width) {
+	_engine->_interface->resetClip();
+	const int16 height = 80;
+	const Common::Rect rect(left, top, left + width, top + height);
+	drawBox(rect);
+	Common::Rect filledRect(rect);
+	filledRect.grow(-1);
+	_engine->_interface->drawFilledRect(filledRect, COLOR_BLACK);
+
+	const int32 boxLeft = left + 9;
+	const int32 boxRight = left + 325;
+	const int32 barPadding = 25;
+	const int32 boxTop = top + 10;
+	const int32 barHeight = 14;
+	drawHealthBar(boxLeft, boxRight, boxTop, barPadding, barHeight);
+	drawMagicPointsBar(boxLeft, boxRight, boxTop + 25, barPadding, barHeight);
+
+	const int32 posLeft = left + 340;
+	drawCoins(posLeft, top);
+	drawKeys(posLeft, top + 35);
+	drawCloverLeafs(left + barPadding, boxRight, top);
 
 	_engine->copyBlockPhys(left, top, left + width, top + 135);
 }
diff --git a/engines/twine/menu/menu.h b/engines/twine/menu/menu.h
index 85e76e214b..50dd321d3b 100644
--- a/engines/twine/menu/menu.h
+++ b/engines/twine/menu/menu.h
@@ -34,6 +34,8 @@ namespace TwinE {
 #define PLASMA_HEIGHT 50
 #define kQuitEngine 9998
 
+class SpriteData;
+
 class MenuSettings {
 private:
 	enum MenuSettingsType {
@@ -189,6 +191,8 @@ private:
 	MenuSettings advOptionsMenuState;
 	MenuSettings optionsMenuState;
 
+	void drawSpriteAndString(int32 left, int32 top, const SpriteData &spriteData, const Common::String &str, int32 color = COLOR_GOLD);
+
 public:
 	Menu(TwinEEngine *engine);
 	~Menu();
@@ -207,6 +211,12 @@ public:
 	 */
 	void processPlasmaEffect(const Common::Rect &rect, int32 color);
 
+	void drawHealthBar(int32 left, int32 right, int32 top, int32 barLeftPadding, int32 barHeight);
+	void drawCloverLeafs(int32 newBoxLeft, int32 boxRight, int32 top);
+	void drawMagicPointsBar(int32 left, int32 right, int32 top, int32 barLeftPadding, int32 barHeight);
+	void drawCoins(int32 left, int32 top);
+	void drawKeys(int32 left, int32 top);
+
 	/**
 	 * Draw the entire button box
 	 * @param left start width to draw the button


Commit: b34d716baf1d1b9c5e2e626159dfc654c76e7ab3
    https://github.com/scummvm/scummvm/commit/b34d716baf1d1b9c5e2e626159dfc654c76e7ab3
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: reduced code duplication for drawBox

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/menu/menu.h


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index 5df12a773d..d69ffefa96 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -236,15 +236,15 @@ void Menu::processPlasmaEffect(const Common::Rect &rect, int32 color) {
 	_engine->frontVideoBuffer.blitFrom(_engine->imageBuffer, prect, rect);
 }
 
-void Menu::drawBox(const Common::Rect &rect) {
-	_engine->_interface->drawLine(rect.left, rect.top, rect.right, rect.top, COLOR_79);           // top line
-	_engine->_interface->drawLine(rect.left, rect.top, rect.left, rect.bottom, COLOR_79);         // left line
-	_engine->_interface->drawLine(rect.right, rect.top + 1, rect.right, rect.bottom, COLOR_73);   // right line
-	_engine->_interface->drawLine(rect.left + 1, rect.bottom, rect.right, rect.bottom, COLOR_73); // bottom line
+void Menu::drawBox(const Common::Rect &rect, int32 colorLeftTop, int32 colorRightBottom) {
+	_engine->_interface->drawLine(rect.left, rect.top, rect.right, rect.top, colorLeftTop);           // top line
+	_engine->_interface->drawLine(rect.left, rect.top, rect.left, rect.bottom, colorLeftTop);         // left line
+	_engine->_interface->drawLine(rect.right, rect.top + 1, rect.right, rect.bottom, colorRightBottom);   // right line
+	_engine->_interface->drawLine(rect.left + 1, rect.bottom, rect.right, rect.bottom, colorRightBottom); // bottom line
 }
 
-void Menu::drawBox(int32 left, int32 top, int32 right, int32 bottom) {
-	drawBox(Common::Rect(left, top, right, bottom));
+void Menu::drawBox(int32 left, int32 top, int32 right, int32 bottom, int32 colorLeftTop, int32 colorRightBottom) {
+	drawBox(Common::Rect(left, top, right, bottom), colorLeftTop, colorLeftTop);
 }
 
 void Menu::drawButtonGfx(const MenuSettings *menuSettings, const Common::Rect &rect, int32 buttonId, const char *dialText, bool hover) {
@@ -1095,13 +1095,6 @@ void Menu::processBehaviourMenu() {
 	_engine->_text->initSceneTextBank();
 }
 
-void Menu::drawMagicItemsBox(int32 left, int32 top, int32 right, int32 bottom, int32 color) { // Rect
-	_engine->_interface->drawLine(left, top, right, top, color);                              // top line
-	_engine->_interface->drawLine(left, top, left, bottom, color);                            // left line
-	_engine->_interface->drawLine(right, ++top, right, bottom, color);                        // right line
-	_engine->_interface->drawLine(++left, bottom, right, bottom, color);                      // bottom line
-}
-
 void Menu::drawItem(int32 item, Common::Rect &dirtyRect) {
 	const int32 itemX = (item / 4) * 85 + 64;
 	const int32 itemY = (item & 3) * 75 + 52;
@@ -1134,10 +1127,11 @@ void Menu::drawItem(int32 item, Common::Rect &dirtyRect) {
 }
 
 void Menu::drawInventoryItems() {
-	const Common::Rect rect(17, 10, 622, 320);
+	const int32 padding = 17;
+	const Common::Rect rect(padding, 10, _engine->width() - padding - 1, _engine->height() / 2);
 	_engine->_interface->drawTransparentBox(rect, 4);
 	drawBox(rect);
-	drawMagicItemsBox(110, 18, 188, 311, 75);
+	drawBox(110, 18, 188, 311, COLOR_75, COLOR_75);
 	_engine->copyBlockPhys(rect);
 
 	Common::Rect dirtyRect;
diff --git a/engines/twine/menu/menu.h b/engines/twine/menu/menu.h
index 50dd321d3b..aece791bdf 100644
--- a/engines/twine/menu/menu.h
+++ b/engines/twine/menu/menu.h
@@ -174,14 +174,6 @@ private:
 	void prepareAndDrawBehaviour(int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect);
 	void drawBehaviourMenu(int32 angle);
 	void drawItem(int32 item, Common::Rect &dirtyRect);
-	/**
-	 * Draw the entire button box
-	 * @param left start width to draw the button
-	 * @param top start height to draw the button
-	 * @param right end width to draw the button
-	 * @param bottom end height to draw the button
-	 */
-	void drawMagicItemsBox(int32 left, int32 top, int32 right, int32 bottom, int32 color);
 
 	MenuSettings giveUpMenuWithSaveState;
 	MenuSettings volumeMenuState;
@@ -224,8 +216,8 @@ public:
 	 * @param right end width to draw the button
 	 * @param bottom end height to draw the button
 	 */
-	void drawBox(int32 left, int32 top, int32 right, int32 bottom);
-	void drawBox(const Common::Rect &rect);
+	void drawBox(int32 left, int32 top, int32 right, int32 bottom, int32 colorLeftTop = COLOR_79, int32 colorRightBottom = COLOR_73);
+	void drawBox(const Common::Rect &rect, int32 colorLeftTop = COLOR_79, int32 colorRightBottom = COLOR_73);
 	/**
 	 * Where the main menu options are processed
 	 * @param menuSettings menu settings array with the information to build the menu options


Commit: 7779b3e6e1c4e40fe71c62ef06be718a2e0c3b52
    https://github.com/scummvm/scummvm/commit/7779b3e6e1c4e40fe71c62ef06be718a2e0c3b52
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: center the info and behaviour menu

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/menu/menu.h


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index d69ffefa96..91105f6b19 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -896,26 +896,26 @@ void Menu::drawInfoMenu(int16 left, int16 top, int16 width) {
 	_engine->copyBlockPhys(left, top, left + width, top + 135);
 }
 
-Common::Rect Menu::calcBehaviourRect(HeroBehaviourType behaviour) const {
-	const int border = 110;
+Common::Rect Menu::calcBehaviourRect(int32 left, int32 top, HeroBehaviourType behaviour) const {
+	const int border = 10;
 	const int32 padding = 11;
 	const int32 width = 99;
 	const int height = 119;
 
-	const int32 boxLeft = (int32)behaviour * (width + padding) + border;
+	const int32 boxLeft = (int32)behaviour * (width + padding) + left + border;
 	const int32 boxRight = boxLeft + width;
-	const int32 boxTop = border;
+	const int32 boxTop = top + border;
 	const int32 boxBottom = boxTop + height;
 	return Common::Rect(boxLeft, boxTop, boxRight, boxBottom);
 }
 
-bool Menu::isBehaviourHovered(HeroBehaviourType behaviour) const {
-	const Common::Rect &boxRect = calcBehaviourRect(behaviour);
+bool Menu::isBehaviourHovered(int32 left, int32 top, HeroBehaviourType behaviour) const {
+	const Common::Rect &boxRect = calcBehaviourRect(left, top, behaviour);
 	return _engine->_input->isMouseHovering(boxRect);
 }
 
-void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, bool cantDrawBox, Common::Rect &dirtyRect) {
-	const Common::Rect &boxRect = calcBehaviourRect(behaviour);
+void Menu::drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int32 angle, bool cantDrawBox, Common::Rect &dirtyRect) {
+	const Common::Rect &boxRect = calcBehaviourRect(left, top, behaviour);
 
 	const int animIdx = _engine->_actor->heroAnimIdx[(byte)behaviour];
 	const uint8 *currentAnim = _engine->_resources->animTable[animIdx];
@@ -943,7 +943,7 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, bool cantDraw
 	if (behaviour == _engine->_actor->heroBehaviour) {
 		const int titleOffset = 10;
 		const int titleHeight = 40;
-		const int32 titleBoxLeft = 110;
+		const int32 titleBoxLeft = left + 10;
 		const int32 titleBoxWidth = 430;
 		const int32 titleBoxCenter = titleBoxLeft + titleBoxWidth / 2;
 		const int32 titleBoxRight = titleBoxLeft + titleBoxWidth;
@@ -979,13 +979,18 @@ void Menu::drawBehaviour(HeroBehaviourType behaviour, int32 angle, bool cantDraw
 	_engine->_interface->loadClip();
 }
 
-void Menu::prepareAndDrawBehaviour(int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect) {
+void Menu::prepareAndDrawBehaviour(int32 left, int32 top, int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect) {
 	_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)behaviour], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[(byte)behaviour]], behaviourEntity, &behaviourAnimData[(byte)behaviour]);
-	drawBehaviour(behaviour, angle, false, dirtyRect);
+	drawBehaviour(left, top, behaviour, angle, false, dirtyRect);
 }
 
-void Menu::drawBehaviourMenu(int32 angle) {
-	const Common::Rect titleRect(100, 100, 550, 290);
+void Menu::drawBehaviourMenu(int32 left, int32 top, int32 angle) {
+	const int32 width = 450;
+	const int32 height = 190;
+	const int32 right = left + width;
+	const int32 bottom = top + height;
+
+	const Common::Rect titleRect(left, top, right, bottom);
 	drawBox(titleRect);
 
 	Common::Rect boxRect(titleRect);
@@ -993,10 +998,10 @@ void Menu::drawBehaviourMenu(int32 angle) {
 	_engine->_interface->drawTransparentBox(boxRect, 2);
 
 	Common::Rect ignoreRect;
-	prepareAndDrawBehaviour(angle, HeroBehaviourType::kNormal, ignoreRect);
-	prepareAndDrawBehaviour(angle, HeroBehaviourType::kAthletic, ignoreRect);
-	prepareAndDrawBehaviour(angle, HeroBehaviourType::kAggressive, ignoreRect);
-	prepareAndDrawBehaviour(angle, HeroBehaviourType::kDiscrete, ignoreRect);
+	prepareAndDrawBehaviour(left, top, angle, HeroBehaviourType::kNormal, ignoreRect);
+	prepareAndDrawBehaviour(left, top, angle, HeroBehaviourType::kAthletic, ignoreRect);
+	prepareAndDrawBehaviour(left, top, angle, HeroBehaviourType::kAggressive, ignoreRect);
+	prepareAndDrawBehaviour(left, top, angle, HeroBehaviourType::kDiscrete, ignoreRect);
 
 	_engine->copyBlockPhys(titleRect);
 
@@ -1026,7 +1031,9 @@ void Menu::processBehaviourMenu() {
 
 	_engine->_text->initTextBank(TextBankId::Options_and_menus);
 
-	drawBehaviourMenu(_engine->_scene->sceneHero->angle);
+	const int32 left = _engine->width() / 2 - 220;
+	const int32 top = _engine->height() / 2 - 140;
+	drawBehaviourMenu(left, top, _engine->_scene->sceneHero->angle);
 
 	HeroBehaviourType tmpHeroBehaviour = _engine->_actor->heroBehaviour;
 
@@ -1072,13 +1079,13 @@ void Menu::processBehaviourMenu() {
 
 		Common::Rect dirtyRect;
 		if (tmpHeroBehaviour != _engine->_actor->heroBehaviour) {
-			drawBehaviour(tmpHeroBehaviour, _engine->_scene->sceneHero->angle, true, dirtyRect);
+			drawBehaviour(left, top, tmpHeroBehaviour, _engine->_scene->sceneHero->angle, true, dirtyRect);
 			tmpHeroBehaviour = _engine->_actor->heroBehaviour;
 			_engine->_movements->setActorAngleSafe(_engine->_scene->sceneHero->angle, _engine->_scene->sceneHero->angle - ANGLE_90, ANGLE_17, &moveMenu);
 			_engine->_animations->setAnimAtKeyframe(behaviourAnimState[(byte)_engine->_actor->heroBehaviour], _engine->_resources->animTable[_engine->_actor->heroAnimIdx[(byte)_engine->_actor->heroBehaviour]], behaviourEntity, &behaviourAnimData[(byte)_engine->_actor->heroBehaviour]);
 		}
 
-		drawBehaviour(_engine->_actor->heroBehaviour, -1, true, dirtyRect);
+		drawBehaviour(left, top, _engine->_actor->heroBehaviour, -1, true, dirtyRect);
 		if (!dirtyRect.isEmpty()) {
 			_engine->copyBlockPhys(dirtyRect);
 		}
diff --git a/engines/twine/menu/menu.h b/engines/twine/menu/menu.h
index aece791bdf..04e7022668 100644
--- a/engines/twine/menu/menu.h
+++ b/engines/twine/menu/menu.h
@@ -167,12 +167,12 @@ private:
 	/** Used to run the save game management menu */
 	int32 savemanageMenu();
 	void drawInfoMenu(int16 left, int16 top, int16 width);
-	Common::Rect calcBehaviourRect(HeroBehaviourType behaviour) const;
-	bool isBehaviourHovered(HeroBehaviourType behaviour) const;
-	void drawBehaviour(HeroBehaviourType behaviour, int32 angle, bool cantDrawBox, Common::Rect &dirtyRect);
+	Common::Rect calcBehaviourRect(int32 left, int32 top, HeroBehaviourType behaviour) const;
+	bool isBehaviourHovered(int32 left, int32 top, HeroBehaviourType behaviour) const;
+	void drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int32 angle, bool cantDrawBox, Common::Rect &dirtyRect);
 	void drawInventoryItems();
-	void prepareAndDrawBehaviour(int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect);
-	void drawBehaviourMenu(int32 angle);
+	void prepareAndDrawBehaviour(int32 left, int32 top, int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect);
+	void drawBehaviourMenu(int32 left, int32 top, int32 angle);
 	void drawItem(int32 item, Common::Rect &dirtyRect);
 
 	MenuSettings giveUpMenuWithSaveState;


Commit: 8eae73031c0c0ecd1f266790d69efcb862fff63b
    https://github.com/scummvm/scummvm/commit/8eae73031c0c0ecd1f266790d69efcb862fff63b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: doxygen

Changed paths:
    engines/twine/renderer/renderer.h


diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 477e2f0241..3dc3b1a8fa 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -430,7 +430,13 @@ public:
 
 	bool renderIsoModel(int32 x, int32 y, int32 z, int32 angleX, int32 angleY, int32 angleZ, const uint8 *bodyPtr);
 
+	/**
+	 * @param angle A value of @c -1 means that the model is automatically rotated
+	 */
 	void renderBehaviourModel(int32 boxLeft, int32 boxTop, int32 boxRight, int32 boxBottom, int32 y, int32 angle, const uint8 *bodyPtr);
+	/**
+	 * @param angle A value of @c -1 means that the model is automatically rotated
+	 */
 	void renderBehaviourModel(const Common::Rect &rect, int32 y, int32 angle, const uint8 *bodyPtr);
 
 	void renderInventoryItem(int32 x, int32 y, const uint8 *bodyPtr, int32 angle, int32 param);


Commit: 8a34640538fa772da103b54a21cf248fb79680d1
    https://github.com/scummvm/scummvm/commit/8a34640538fa772da103b54a21cf248fb79680d1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: use color constants

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/menu/menu.h


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index 91105f6b19..cf268d993c 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -1158,7 +1158,7 @@ void Menu::processInventoryMenu() {
 
 	_engine->_renderer->setLightVector(ANGLE_315, ANGLE_334, ANGLE_0);
 
-	inventorySelectedColor = 68;
+	inventorySelectedColor = COLOR_RED;
 
 	if (_engine->_gameState->inventoryNumLeafs > 0) {
 		_engine->_gameState->giveItem(InventoryItems::kiCloverLeaf);
@@ -1176,9 +1176,7 @@ void Menu::processInventoryMenu() {
 	ProgressiveTextState textState = ProgressiveTextState::ContinueRunning;
 	bool updateItemText = true;
 
-#if 0
-	ScopedCursor scopedCursor(_engine);
-#endif
+	//ScopedCursor scopedCursor(_engine);
 	ScopedKeyMap scopedKeyMap(_engine, uiKeyMapId);
 	for (;;) {
 		FrameMarker frame;
@@ -1258,7 +1256,7 @@ void Menu::processInventoryMenu() {
 
 		if (inventorySelectedItem < NUM_INVENTORY_ITEMS && _engine->_input->toggleActionIfActive(TwinEActionType::UIEnter) && _engine->_gameState->hasItem((InventoryItems)inventorySelectedItem) && !_engine->_gameState->inventoryDisabled()) {
 			_engine->loopInventoryItem = inventorySelectedItem;
-			inventorySelectedColor = 91;
+			inventorySelectedColor = COLOR_91;
 			drawItem(inventorySelectedItem, dirtyRect);
 			if (!dirtyRect.isEmpty()) {
 				_engine->copyBlockPhys(dirtyRect);
diff --git a/engines/twine/menu/menu.h b/engines/twine/menu/menu.h
index 04e7022668..a3d9f929ea 100644
--- a/engines/twine/menu/menu.h
+++ b/engines/twine/menu/menu.h
@@ -143,7 +143,7 @@ private:
 	/** Behaviour menu anim data pointer */
 	AnimTimerDataStruct behaviourAnimData[4];
 
-	int32 inventorySelectedColor = 0;
+	int32 inventorySelectedColor = COLOR_BLACK;
 	int32 inventorySelectedItem = 0; // currentSelectedObjectInInventory
 
 	/**


Commit: 99783c08a9ca76e735851f2c52874acd8b8bdcac
    https://github.com/scummvm/scummvm/commit/99783c08a9ca76e735851f2c52874acd8b8bdcac
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: render the inventory menu centered on the screen in high-res mode

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/menu/menu.h


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index cf268d993c..2569d03c9d 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -1102,9 +1102,9 @@ void Menu::processBehaviourMenu() {
 	_engine->_text->initSceneTextBank();
 }
 
-void Menu::drawItem(int32 item, Common::Rect &dirtyRect) {
-	const int32 itemX = (item / 4) * 85 + 64;
-	const int32 itemY = (item & 3) * 75 + 52;
+void Menu::drawItem(int32 left2, int32 top2, int32 item, Common::Rect &dirtyRect) {
+	const int32 itemX = (item / 4) * 85 + left2 + 47;
+	const int32 itemY = (item & 3) * 75 + top2 + 42;
 
 	const int32 left = itemX - 37;
 	const int32 right = itemX + 37;
@@ -1133,17 +1133,16 @@ void Menu::drawItem(int32 item, Common::Rect &dirtyRect) {
 	}
 }
 
-void Menu::drawInventoryItems() {
-	const int32 padding = 17;
-	const Common::Rect rect(padding, 10, _engine->width() - padding - 1, _engine->height() / 2);
+void Menu::drawInventoryItems(int32 left, int32 top) {
+	const Common::Rect rect(left, top, left + 605, top + 310);
 	_engine->_interface->drawTransparentBox(rect, 4);
 	drawBox(rect);
-	drawBox(110, 18, 188, 311, COLOR_75, COLOR_75);
+	drawBox(left + 93, top + 8, left + 93 + 78, top + 8 + 293, COLOR_75, COLOR_75);
 	_engine->copyBlockPhys(rect);
 
 	Common::Rect dirtyRect;
 	for (int32 item = 0; item < NUM_INVENTORY_ITEMS; item++) {
-		drawItem(item, dirtyRect);
+		drawItem(left, top, item, dirtyRect);
 	}
 	if (!dirtyRect.isEmpty()) {
 		_engine->copyBlockPhys(dirtyRect);
@@ -1166,7 +1165,9 @@ void Menu::processInventoryMenu() {
 		//	_engine->_gameState->removeItem(InventoryItems::kiCloverLeaf);
 	}
 
-	drawInventoryItems();
+	const int32 left = _engine->width() / 2 - 303;
+	const int32 top = _engine->height() / 2 - 210;
+	drawInventoryItems(left, top);
 
 	_engine->_text->initTextBank(TextBankId::Inventory_Intro_and_Holomap);
 
@@ -1199,28 +1200,28 @@ void Menu::processInventoryMenu() {
 			if (inventorySelectedItem >= NUM_INVENTORY_ITEMS) {
 				inventorySelectedItem = 0;
 			}
-			drawItem(prevSelectedItem, dirtyRect);
+			drawItem(left, top, prevSelectedItem, dirtyRect);
 			updateItemText = true;
 		} else if (cursorUp) {
 			inventorySelectedItem--;
 			if (inventorySelectedItem < 0) {
 				inventorySelectedItem = NUM_INVENTORY_ITEMS - 1;
 			}
-			drawItem(prevSelectedItem, dirtyRect);
+			drawItem(left, top, prevSelectedItem, dirtyRect);
 			updateItemText = true;
 		} else if (cursorLeft) {
 			inventorySelectedItem -= 4;
 			if (inventorySelectedItem < 0) {
 				inventorySelectedItem += NUM_INVENTORY_ITEMS;
 			}
-			drawItem(prevSelectedItem, dirtyRect);
+			drawItem(left, top, prevSelectedItem, dirtyRect);
 			updateItemText = true;
 		} else if (cursorRight) {
 			inventorySelectedItem += 4;
 			if (inventorySelectedItem >= NUM_INVENTORY_ITEMS) {
 				inventorySelectedItem -= NUM_INVENTORY_ITEMS;
 			}
-			drawItem(prevSelectedItem, dirtyRect);
+			drawItem(left, top, prevSelectedItem, dirtyRect);
 			updateItemText = true;
 		}
 
@@ -1252,12 +1253,12 @@ void Menu::processInventoryMenu() {
 			}
 		}
 
-		drawItem(inventorySelectedItem, dirtyRect);
+		drawItem(left, top, inventorySelectedItem, dirtyRect);
 
 		if (inventorySelectedItem < NUM_INVENTORY_ITEMS && _engine->_input->toggleActionIfActive(TwinEActionType::UIEnter) && _engine->_gameState->hasItem((InventoryItems)inventorySelectedItem) && !_engine->_gameState->inventoryDisabled()) {
 			_engine->loopInventoryItem = inventorySelectedItem;
 			inventorySelectedColor = COLOR_91;
-			drawItem(inventorySelectedItem, dirtyRect);
+			drawItem(left, top, inventorySelectedItem, dirtyRect);
 			if (!dirtyRect.isEmpty()) {
 				_engine->copyBlockPhys(dirtyRect);
 			}
diff --git a/engines/twine/menu/menu.h b/engines/twine/menu/menu.h
index a3d9f929ea..c6da34aacd 100644
--- a/engines/twine/menu/menu.h
+++ b/engines/twine/menu/menu.h
@@ -170,10 +170,10 @@ private:
 	Common::Rect calcBehaviourRect(int32 left, int32 top, HeroBehaviourType behaviour) const;
 	bool isBehaviourHovered(int32 left, int32 top, HeroBehaviourType behaviour) const;
 	void drawBehaviour(int32 left, int32 top, HeroBehaviourType behaviour, int32 angle, bool cantDrawBox, Common::Rect &dirtyRect);
-	void drawInventoryItems();
+	void drawInventoryItems(int32 left, int32 top);
 	void prepareAndDrawBehaviour(int32 left, int32 top, int32 angle, HeroBehaviourType behaviour, Common::Rect &dirtyRect);
 	void drawBehaviourMenu(int32 left, int32 top, int32 angle);
-	void drawItem(int32 item, Common::Rect &dirtyRect);
+	void drawItem(int32 left, int32 top, int32 item, Common::Rect &dirtyRect);
 
 	MenuSettings giveUpMenuWithSaveState;
 	MenuSettings volumeMenuState;


Commit: 55e0f3afeadb9221e0412938f73394f6cd2652fc
    https://github.com/scummvm/scummvm/commit/55e0f3afeadb9221e0412938f73394f6cd2652fc
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: introduced new angle constant

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/shared.h


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index 2569d03c9d..d5720f20a3 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -47,6 +47,7 @@
 #include "twine/renderer/screens.h"
 #include "twine/resources/resources.h"
 #include "twine/scene/scene.h"
+#include "twine/shared.h"
 #include "twine/text.h"
 #include "twine/twine.h"
 
@@ -1114,11 +1115,11 @@ void Menu::drawItem(int32 left2, int32 top2, int32 item, Common::Rect &dirtyRect
 	_engine->_interface->drawFilledRect(rect, inventorySelectedItem == item ? inventorySelectedColor : COLOR_BLACK);
 
 	if (item < NUM_INVENTORY_ITEMS && _engine->_gameState->hasItem((InventoryItems)item) && (!_engine->_gameState->inventoryDisabled() || item == InventoryItems::kiCloverLeaf)) {
-		itemAngle[item] += 8;
+		itemAngle[item] += ANGLE_2;
 		_engine->_interface->setClip(rect);
 		_engine->_renderer->renderInventoryItem(itemX, itemY, _engine->_resources->inventoryTable[item], itemAngle[item], 15000);
 		_engine->_interface->resetClip();
-		if (item == InventoryItems::kGasItem) { // has GAS
+		if (item == InventoryItems::kGasItem) {
 			_engine->_text->setFontColor(COLOR_WHITE);
 			Common::String inventoryNumGas = Common::String::format("%d", _engine->_gameState->inventoryNumGas);
 			_engine->_text->drawText(left + 3, top + 32, inventoryNumGas.c_str());
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 198d85ad3e..dbc7d7e3f8 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -208,6 +208,7 @@ enum class ExtraSpecialType {
 #define ANGLE_22_5 64
 #define ANGLE_17 50
 #define ANGLE_11_25 32
+#define ANGLE_2 8 // 1.67
 #define ANGLE_1 5 // 1.75
 #define ANGLE_0 0
 


Commit: c5df2813e6ef6bb2369f7a05a0b24e38499c1fa9
    https://github.com/scummvm/scummvm/commit/c5df2813e6ef6bb2369f7a05a0b24e38499c1fa9
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: moved defines

Changed paths:
    engines/twine/scene/gamestate.h
    engines/twine/shared.h


diff --git a/engines/twine/scene/gamestate.h b/engines/twine/scene/gamestate.h
index 1f621789f1..ae5e6b48cb 100644
--- a/engines/twine/scene/gamestate.h
+++ b/engines/twine/scene/gamestate.h
@@ -32,9 +32,6 @@
 
 namespace TwinE {
 
-#define NUM_GAME_FLAGS 255
-#define NUM_INVENTORY_ITEMS 28
-
 /**
  * This gameflag indicates that the inventory items are taken from Twinson because he went to jail
  */
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index dbc7d7e3f8..111b25d29e 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -25,6 +25,9 @@
 
 #include "common/scummsys.h"
 
+#define NUM_GAME_FLAGS 255
+#define NUM_INVENTORY_ITEMS 28
+
 namespace TwinE {
 
 struct Vec3 {


Commit: e342415d316e34034147e6e0a67c48e1e42d5875
    https://github.com/scummvm/scummvm/commit/e342415d316e34034147e6e0a67c48e1e42d5875
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:34+01:00

Commit Message:
TWINE: reduced itemAngle array size

Changed paths:
    engines/twine/menu/menu.cpp
    engines/twine/menu/menu.h
    engines/twine/scene/gamestate.cpp
    engines/twine/twine.cpp


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index d5720f20a3..e09a528254 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -167,7 +167,7 @@ Menu::Menu(TwinEEngine *engine) {
 	advOptionsMenuState = _priv::createAdvancedOptionsMenu();
 
 	Common::fill(&behaviourAnimState[0], &behaviourAnimState[4], 0);
-	Common::fill(&itemAngle[0], &itemAngle[255], 0);
+	Common::fill(&itemAngle[0], &itemAngle[NUM_INVENTORY_ITEMS], 0);
 }
 
 Menu::~Menu() {
diff --git a/engines/twine/menu/menu.h b/engines/twine/menu/menu.h
index c6da34aacd..675abcae7d 100644
--- a/engines/twine/menu/menu.h
+++ b/engines/twine/menu/menu.h
@@ -189,7 +189,7 @@ public:
 	Menu(TwinEEngine *engine);
 	~Menu();
 
-	int16 itemAngle[255]; // objectRotation
+	int16 itemAngle[NUM_INVENTORY_ITEMS]; // objectRotation
 
 	/** Behaviour menu move pointer */
 	ActorMoveStruct moveMenu;
diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index 1407e5a989..22bd35b5da 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -380,7 +380,7 @@ void GameState::processFoundItem(int32 item) {
 
 		_engine->_interface->setClip(boxRect);
 
-		_engine->_menu->itemAngle[item] += 8;
+		_engine->_menu->itemAngle[item] += ANGLE_2;
 
 		_engine->_renderer->renderInventoryItem(_engine->_renderer->projPosX, _engine->_renderer->projPosY, _engine->_resources->inventoryTable[item], _engine->_menu->itemAngle[item], 10000);
 
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 7e0be17bf3..b0d1995306 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -509,7 +509,7 @@ void TwinEEngine::exitSceneryView() {
 }
 
 void TwinEEngine::initAll() {
-	memset(_menu->itemAngle, 0, sizeof(_menu->itemAngle)); // reset inventory items angles
+	Common::fill(&_menu->itemAngle[0], &_menu->itemAngle[NUM_INVENTORY_ITEMS], 0);
 
 	_redraw->bubbleSpriteIndex = SPRITEHQR_DIAG_BUBBLE_LEFT;
 


Commit: 89f81a020dddad6cc50460753803570ea319b998
    https://github.com/scummvm/scummvm/commit/89f81a020dddad6cc50460753803570ea319b998
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:35+01:00

Commit Message:
TWINE: reduced magic numbers in inventory menu

Changed paths:
    engines/twine/menu/menu.cpp


diff --git a/engines/twine/menu/menu.cpp b/engines/twine/menu/menu.cpp
index e09a528254..b0f1172d2c 100644
--- a/engines/twine/menu/menu.cpp
+++ b/engines/twine/menu/menu.cpp
@@ -1103,16 +1103,18 @@ void Menu::processBehaviourMenu() {
 	_engine->_text->initSceneTextBank();
 }
 
-void Menu::drawItem(int32 left2, int32 top2, int32 item, Common::Rect &dirtyRect) {
-	const int32 itemX = (item / 4) * 85 + left2 + 47;
-	const int32 itemY = (item & 3) * 75 + top2 + 42;
-
-	const int32 left = itemX - 37;
-	const int32 right = itemX + 37;
-	const int32 top = itemY - 32;
-	const int32 bottom = itemY + 32;
-	const Common::Rect rect(left, top, right, bottom);
-	_engine->_interface->drawFilledRect(rect, inventorySelectedItem == item ? inventorySelectedColor : COLOR_BLACK);
+void Menu::drawItem(int32 left, int32 top, int32 item, Common::Rect &dirtyRect) {
+	const int32 itemWidth = 74;
+	const int32 itemHeight = 64;
+	const int32 itemPadding = 11;
+	const int32 itemWidthHalf = itemWidth / 2;
+	const int32 itemHeightHalf = itemHeight / 2;
+	const int32 itemX = (item / 4) * (itemWidth + itemPadding) + left + itemWidthHalf + itemPadding - 1;
+	const int32 itemY = (item % 4) * (itemHeight + itemPadding) + top + itemHeightHalf + itemPadding - 1;
+	const Common::Rect rect(itemX - itemWidthHalf, itemY - itemHeightHalf, itemX + itemWidthHalf, itemY + itemHeightHalf);
+	const int32 color = inventorySelectedItem == item ? inventorySelectedColor : COLOR_BLACK;
+
+	_engine->_interface->drawFilledRect(rect, color);
 
 	if (item < NUM_INVENTORY_ITEMS && _engine->_gameState->hasItem((InventoryItems)item) && (!_engine->_gameState->inventoryDisabled() || item == InventoryItems::kiCloverLeaf)) {
 		itemAngle[item] += ANGLE_2;
@@ -1121,8 +1123,8 @@ void Menu::drawItem(int32 left2, int32 top2, int32 item, Common::Rect &dirtyRect
 		_engine->_interface->resetClip();
 		if (item == InventoryItems::kGasItem) {
 			_engine->_text->setFontColor(COLOR_WHITE);
-			Common::String inventoryNumGas = Common::String::format("%d", _engine->_gameState->inventoryNumGas);
-			_engine->_text->drawText(left + 3, top + 32, inventoryNumGas.c_str());
+			const Common::String &inventoryNumGas = Common::String::format("%d", _engine->_gameState->inventoryNumGas);
+			_engine->_text->drawText(rect.left + 3, rect.bottom - 32, inventoryNumGas.c_str());
 		}
 	}
 


Commit: 86131a3fb61133d7c7b9abdca0329fb65ade559f
    https://github.com/scummvm/scummvm/commit/86131a3fb61133d7c7b9abdca0329fb65ade559f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T12:50:35+01:00

Commit Message:
TWINE: center the on-screen keyboard for high resolution mode

Changed paths:
    engines/twine/menu/menuoptions.cpp


diff --git a/engines/twine/menu/menuoptions.cpp b/engines/twine/menu/menuoptions.cpp
index 0ac6ffc8aa..58d87b7a4a 100644
--- a/engines/twine/menu/menuoptions.cpp
+++ b/engines/twine/menu/menuoptions.cpp
@@ -126,7 +126,7 @@ void MenuOptions::showEndSequence() {
 
 void MenuOptions::drawSelectableCharacter(int32 x, int32 y, Common::Rect &dirtyRect) {
 	const int32 borderTop = 200;
-	const int32 borderLeft = 25;
+	const int32 borderLeft = _engine->width() / 2 - 270;
 	const int32 halfButtonHeight = 25;
 	const int32 halfButtonWidth = 20;
 	const int32 buttonDistanceX = halfButtonWidth * 2 + 5;


Commit: d53f163e67fd175da12e343ac8c721681366ac2b
    https://github.com/scummvm/scummvm/commit/d53f163e67fd175da12e343ac8c721681366ac2b
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T13:51:55+01:00

Commit Message:
TWINE: extract to local variables

Changed paths:
    engines/twine/scene/gamestate.cpp
    engines/twine/script/script_life_v1.cpp


diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index 22bd35b5da..c6329e31b7 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -306,6 +306,7 @@ void GameState::setGameFlag(uint8 index, uint8 value) {
 }
 
 void GameState::processFoundItem(int32 item) {
+	ScopedEngineFreeze freeze(_engine);
 	_engine->_grid->newCameraX = (_engine->_scene->sceneHero->x + BRICK_HEIGHT) / BRICK_SIZE;
 	_engine->_grid->newCameraY = (_engine->_scene->sceneHero->y + BRICK_HEIGHT) / BRICK_HEIGHT;
 	_engine->_grid->newCameraZ = (_engine->_scene->sceneHero->z + BRICK_HEIGHT) / BRICK_SIZE;
@@ -322,7 +323,11 @@ void GameState::processFoundItem(int32 item) {
 	const int32 itemCameraY = _engine->_grid->newCameraY * BRICK_HEIGHT;
 	const int32 itemCameraZ = _engine->_grid->newCameraZ * BRICK_SIZE;
 
-	_engine->_renderer->renderIsoModel(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ, ANGLE_0, ANGLE_45, ANGLE_0, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity]);
+	uint8 *bodyPtr = _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity];
+	const int32 bodyX = _engine->_scene->sceneHero->x - itemCameraX;
+	const int32 bodyY = _engine->_scene->sceneHero->y - itemCameraY;
+	const int32 bodyZ = _engine->_scene->sceneHero->z - itemCameraZ;
+	_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyPtr);
 	_engine->_interface->setClip(_engine->_redraw->renderRect);
 
 	const int32 itemX = (_engine->_scene->sceneHero->x + BRICK_HEIGHT) / BRICK_SIZE;
@@ -335,7 +340,7 @@ void GameState::processFoundItem(int32 item) {
 	_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
 	_engine->flip();
 
-	_engine->_renderer->projectPositionOnScreen(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ);
+	_engine->_renderer->projectPositionOnScreen(bodyX, bodyY, bodyZ);
 	_engine->_renderer->projPosY -= 150;
 
 	const int32 boxTopLeftX = _engine->_renderer->projPosX - 65;
@@ -363,7 +368,7 @@ void GameState::processFoundItem(int32 item) {
 
 	AnimTimerDataStruct tmpAnimTimer = _engine->_scene->sceneHero->animTimerData;
 
-	_engine->_animations->stockAnimation(_engine->_actor->bodyTable[_engine->_scene->sceneHero->entity], &_engine->_scene->sceneHero->animTimerData);
+	_engine->_animations->stockAnimation(bodyPtr, &_engine->_scene->sceneHero->animTimerData);
 
 	int32 currentAnimState = 0;
 
@@ -389,14 +394,14 @@ void GameState::processFoundItem(int32 item) {
 		_engine->_interface->resetClip();
 		initEngineProjections();
 
-		if (_engine->_animations->setModelAnimation(currentAnimState, currentAnimData, currentAnim, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity], &_engine->_scene->sceneHero->animTimerData)) {
+		if (_engine->_animations->setModelAnimation(currentAnimState, currentAnimData, currentAnim, bodyPtr, &_engine->_scene->sceneHero->animTimerData)) {
 			currentAnimState++; // keyframe
 			if (currentAnimState >= _engine->_animations->getNumKeyframes(currentAnim)) {
 				currentAnimState = _engine->_animations->getStartKeyframe(currentAnim);
 			}
 		}
 
-		_engine->_renderer->renderIsoModel(_engine->_scene->sceneHero->x - itemCameraX, _engine->_scene->sceneHero->y - itemCameraY, _engine->_scene->sceneHero->z - itemCameraZ, ANGLE_0, ANGLE_45, ANGLE_0, _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity]);
+		_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyPtr);
 		_engine->_interface->setClip(_engine->_redraw->renderRect);
 		_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
 		_engine->_redraw->addRedrawArea(_engine->_redraw->renderRect);
diff --git a/engines/twine/script/script_life_v1.cpp b/engines/twine/script/script_life_v1.cpp
index fe1d5c466d..0c57aba17b 100644
--- a/engines/twine/script/script_life_v1.cpp
+++ b/engines/twine/script/script_life_v1.cpp
@@ -942,9 +942,7 @@ static int32 lINC_CHAPTER(TwinEEngine *engine, LifeScriptContext &ctx) {
 static int32 lFOUND_OBJECT(TwinEEngine *engine, LifeScriptContext &ctx) {
 	const int32 item = ctx.stream.readByte();
 
-	engine->freezeTime();
 	engine->_gameState->processFoundItem(item);
-	engine->unfreezeTime();
 	engine->_redraw->redrawEngineActions(true);
 
 	return 0;


Commit: ee7ac5572aabbddd07df0f4167bb4008efaba7c1
    https://github.com/scummvm/scummvm/commit/ee7ac5572aabbddd07df0f4167bb4008efaba7c1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T15:04:40+01:00

Commit Message:
TWINE: added centerOnActor method

Changed paths:
    engines/twine/scene/gamestate.cpp
    engines/twine/scene/grid.cpp
    engines/twine/scene/grid.h
    engines/twine/scene/scene.cpp
    engines/twine/script/script_life_v1.cpp
    engines/twine/shared.h
    engines/twine/twine.cpp


diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index c6329e31b7..cdcbdc31b3 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -307,9 +307,7 @@ void GameState::setGameFlag(uint8 index, uint8 value) {
 
 void GameState::processFoundItem(int32 item) {
 	ScopedEngineFreeze freeze(_engine);
-	_engine->_grid->newCameraX = (_engine->_scene->sceneHero->x + BRICK_HEIGHT) / BRICK_SIZE;
-	_engine->_grid->newCameraY = (_engine->_scene->sceneHero->y + BRICK_HEIGHT) / BRICK_HEIGHT;
-	_engine->_grid->newCameraZ = (_engine->_scene->sceneHero->z + BRICK_HEIGHT) / BRICK_SIZE;
+	_engine->_grid->centerOnActor(_engine->_scene->sceneHero);
 
 	_engine->exitSceneryView();
 	// Hide hero in scene
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index 14a97d9422..3c2518f509 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -593,8 +593,8 @@ uint8 *Grid::getBlockBuffer(int32 x, int32 y, int32 z) {
 	return blockBuffer + tempY * 2 + tempX * GRID_SIZE_Y * 2 + (tempZ * GRID_SIZE_X) * GRID_SIZE_Y * 2;
 }
 
-const uint8 *Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground) const {
-	_engine->_grid->updateCollisionCoordinates(x, y, z);
+const uint8 *Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground) {
+	updateCollisionCoordinates(x, y, z);
 	const int32 tempX = _engine->_collision->collisionX;
 	int32 tempY = _engine->_collision->collisionY;
 	const int32 tempZ = _engine->_collision->collisionZ;
@@ -855,4 +855,12 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 	return 240;
 }
 
+void Grid::centerOnActor(const ActorStruct* actor) {
+	newCameraX = (actor->x + BRICK_HEIGHT) / BRICK_SIZE;
+	newCameraY = (actor->y + BRICK_HEIGHT) / BRICK_HEIGHT;
+	newCameraZ = (actor->z + BRICK_HEIGHT) / BRICK_SIZE;
+	_engine->_redraw->reqBgRedraw = true;
+}
+
+
 } // namespace TwinE
diff --git a/engines/twine/scene/grid.h b/engines/twine/scene/grid.h
index f1539f4ebe..f5d7d9aa21 100644
--- a/engines/twine/scene/grid.h
+++ b/engines/twine/scene/grid.h
@@ -194,7 +194,7 @@ public:
 	/**
 	 * search down until either ground is found or lower border of the cube is reached
 	 */
-	const uint8 *getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground) const;
+	const uint8 *getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground);
 
 	/** New grid camera X coordinates */
 	int32 newCameraX = 0;
@@ -240,6 +240,8 @@ public:
 	 */
 	void getSpriteSize(int32 offset, int32 *width, int32 *height, const uint8 *spritePtr);
 
+	void centerOnActor(const ActorStruct* actor);
+
 	/**
 	 * Draw brick sprite in the screen
 	 * @param index brick index to draw
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index f40847a920..8a05a91e8a 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -534,9 +534,7 @@ void Scene::changeScene() {
 	_sampleAmbienceTime = 0;
 
 	ActorStruct *followedActor = getActor(currentlyFollowedActor);
-	_engine->_grid->newCameraX = followedActor->x / BRICK_SIZE;
-	_engine->_grid->newCameraY = followedActor->y / BRICK_HEIGHT;
-	_engine->_grid->newCameraZ = followedActor->z / BRICK_SIZE;
+	_engine->_grid->centerOnActor(followedActor);
 
 	_engine->_gameState->magicBallIdx = -1;
 	_engine->_movements->heroMoved = true;
diff --git a/engines/twine/script/script_life_v1.cpp b/engines/twine/script/script_life_v1.cpp
index 0c57aba17b..b18928d0cb 100644
--- a/engines/twine/script/script_life_v1.cpp
+++ b/engines/twine/script/script_life_v1.cpp
@@ -712,12 +712,8 @@ static int32 lCAM_FOLLOW(TwinEEngine *engine, LifeScriptContext &ctx) {
 
 	if (engine->_scene->currentlyFollowedActor != followedActorIdx) {
 		const ActorStruct *followedActor = engine->_scene->getActor(followedActorIdx);
-		engine->_grid->newCameraX = followedActor->x / BRICK_SIZE;
-		engine->_grid->newCameraY = followedActor->y / BRICK_HEIGHT;
-		engine->_grid->newCameraZ = followedActor->z / BRICK_SIZE;
-
+		engine->_grid->centerOnActor(followedActor);
 		engine->_scene->currentlyFollowedActor = followedActorIdx;
-		engine->_redraw->reqBgRedraw = true;
 	}
 
 	return 0;
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 111b25d29e..3716e98002 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -194,6 +194,9 @@ enum class ExtraSpecialType {
 	kExplodeCloud = 1
 };
 
+// lba2 does from 0 to 0x1000
+// lba1 angles
+// TODO: wrap in a class to be able to handle lba1 and lba2
 #define ANGLE_360 1024
 #define ANGLE_351 1000
 #define ANGLE_334 950
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index b0d1995306..8b2ad469e9 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -816,10 +816,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		// Recenter Screen
 		if (_input->toggleActionIfActive(TwinEActionType::RecenterScreenOnTwinsen) && !disableScreenRecenter) {
 			const ActorStruct *currentlyFollowedActor = _scene->getActor(_scene->currentlyFollowedActor);
-			_grid->newCameraX = currentlyFollowedActor->x / BRICK_SIZE;
-			_grid->newCameraY = currentlyFollowedActor->y / BRICK_HEIGHT;
-			_grid->newCameraZ = currentlyFollowedActor->z / BRICK_SIZE;
-			_redraw->reqBgRedraw = true;
+			_grid->centerOnActor(currentlyFollowedActor);
 		}
 
 		// Draw holomap
@@ -968,9 +965,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 						_scene->needChangeScene = _scene->currentSceneIdx;
 						_gameState->inventoryMagicPoints = _gameState->magicLevelIdx * 20;
 
-						_grid->newCameraX = (_scene->sceneHero->x / BRICK_SIZE);
-						_grid->newCameraY = (_scene->sceneHero->y / BRICK_HEIGHT);
-						_grid->newCameraZ = (_scene->sceneHero->z / BRICK_SIZE);
+						_grid->centerOnActor(_scene->sceneHero);
 
 						_scene->heroPositionType = ScenePositionType::kReborn;
 


Commit: e79b109a612cc1f31709832bb5324dbd203a71d5
    https://github.com/scummvm/scummvm/commit/e79b109a612cc1f31709832bb5324dbd203a71d5
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T15:45:25+01:00

Commit Message:
TWINE: converted to Vec3

Changed paths:
    engines/twine/audio/sound.cpp
    engines/twine/debugger/debug_grid.cpp
    engines/twine/debugger/debug_scene.cpp
    engines/twine/renderer/redraw.cpp
    engines/twine/scene/extra.cpp
    engines/twine/scene/gamestate.cpp
    engines/twine/scene/grid.cpp
    engines/twine/scene/grid.h
    engines/twine/scene/scene.cpp
    engines/twine/shared.h
    engines/twine/twine.cpp


diff --git a/engines/twine/audio/sound.cpp b/engines/twine/audio/sound.cpp
index 06efbee06b..16c0ba9a94 100644
--- a/engines/twine/audio/sound.cpp
+++ b/engines/twine/audio/sound.cpp
@@ -49,9 +49,9 @@ void Sound::setSamplePosition(int32 channelIdx, int32 x, int32 y, int32 z) {
 	if (channelIdx < 0 || channelIdx >= NUM_CHANNELS) {
 		return;
 	}
-	const int32 camX = _engine->_grid->newCameraX * BRICK_SIZE;
-	const int32 camY = _engine->_grid->newCameraY * BRICK_HEIGHT;
-	const int32 camZ = _engine->_grid->newCameraZ * BRICK_SIZE;
+	const int32 camX = _engine->_grid->newCamera.x * BRICK_SIZE;
+	const int32 camY = _engine->_grid->newCamera.y * BRICK_HEIGHT;
+	const int32 camZ = _engine->_grid->newCamera.z * BRICK_SIZE;
 	int32 distance = _engine->_movements->getDistance3D(camX, camY, camZ, x, y, z);
 	distance = _engine->_collision->getAverageValue(0, distance, 10000, 255);
 	const byte targetVolume = CLIP<byte>(255 - distance, 0, 255);
diff --git a/engines/twine/debugger/debug_grid.cpp b/engines/twine/debugger/debug_grid.cpp
index 0fd1e062ed..6bb10f12b7 100644
--- a/engines/twine/debugger/debug_grid.cpp
+++ b/engines/twine/debugger/debug_grid.cpp
@@ -40,17 +40,17 @@ void DebugGrid::changeGridCamera() {
 	}
 
 	if (_engine->_input->isActionActive(TwinEActionType::DebugGridCameraPressUp)) {
-		_engine->_grid->newCameraZ--;
+		_engine->_grid->newCamera.z--;
 		_engine->_redraw->reqBgRedraw = true;
 	} else if (_engine->_input->isActionActive(TwinEActionType::DebugGridCameraPressDown)) {
-		_engine->_grid->newCameraZ++;
+		_engine->_grid->newCamera.z++;
 		_engine->_redraw->reqBgRedraw = true;
 	}
 	if (_engine->_input->isActionActive(TwinEActionType::DebugGridCameraPressLeft)) {
-		_engine->_grid->newCameraX--;
+		_engine->_grid->newCamera.x--;
 		_engine->_redraw->reqBgRedraw = true;
 	} else if (_engine->_input->isActionActive(TwinEActionType::DebugGridCameraPressRight)) {
-		_engine->_grid->newCameraX++;
+		_engine->_grid->newCamera.x++;
 		_engine->_redraw->reqBgRedraw = true;
 	}
 }
diff --git a/engines/twine/debugger/debug_scene.cpp b/engines/twine/debugger/debug_scene.cpp
index 4fd596b945..aee4924d04 100644
--- a/engines/twine/debugger/debug_scene.cpp
+++ b/engines/twine/debugger/debug_scene.cpp
@@ -137,37 +137,37 @@ void DebugScene::displayZones() {
 
 		// compute the points in 3D
 
-		frontBottomLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->cameraX;
-		frontBottomLeftPoint.y = zonePtr->bottomLeft.y - _engine->_grid->cameraY;
-		frontBottomLeftPoint.z = zonePtr->topRight.z - _engine->_grid->cameraZ;
+		frontBottomLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->camera.x;
+		frontBottomLeftPoint.y = zonePtr->bottomLeft.y - _engine->_grid->camera.y;
+		frontBottomLeftPoint.z = zonePtr->topRight.z - _engine->_grid->camera.z;
 
-		frontBottomRightPoint.x = zonePtr->topRight.x - _engine->_grid->cameraX;
-		frontBottomRightPoint.y = zonePtr->bottomLeft.y - _engine->_grid->cameraY;
-		frontBottomRightPoint.z = zonePtr->topRight.z - _engine->_grid->cameraZ;
+		frontBottomRightPoint.x = zonePtr->topRight.x - _engine->_grid->camera.x;
+		frontBottomRightPoint.y = zonePtr->bottomLeft.y - _engine->_grid->camera.y;
+		frontBottomRightPoint.z = zonePtr->topRight.z - _engine->_grid->camera.z;
 
-		frontTopLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->cameraX;
-		frontTopLeftPoint.y = zonePtr->topRight.y - _engine->_grid->cameraY;
-		frontTopLeftPoint.z = zonePtr->topRight.z - _engine->_grid->cameraZ;
+		frontTopLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->camera.x;
+		frontTopLeftPoint.y = zonePtr->topRight.y - _engine->_grid->camera.y;
+		frontTopLeftPoint.z = zonePtr->topRight.z - _engine->_grid->camera.z;
 
-		frontTopRightPoint.x = zonePtr->topRight.x - _engine->_grid->cameraX;
-		frontTopRightPoint.y = zonePtr->topRight.y - _engine->_grid->cameraY;
-		frontTopRightPoint.z = zonePtr->topRight.z - _engine->_grid->cameraZ;
+		frontTopRightPoint.x = zonePtr->topRight.x - _engine->_grid->camera.x;
+		frontTopRightPoint.y = zonePtr->topRight.y - _engine->_grid->camera.y;
+		frontTopRightPoint.z = zonePtr->topRight.z - _engine->_grid->camera.z;
 
-		backBottomLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->cameraX;
-		backBottomLeftPoint.y = zonePtr->bottomLeft.y - _engine->_grid->cameraY;
-		backBottomLeftPoint.z = zonePtr->bottomLeft.z - _engine->_grid->cameraZ;
+		backBottomLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->camera.x;
+		backBottomLeftPoint.y = zonePtr->bottomLeft.y - _engine->_grid->camera.y;
+		backBottomLeftPoint.z = zonePtr->bottomLeft.z - _engine->_grid->camera.z;
 
-		backBottomRightPoint.x = zonePtr->topRight.x - _engine->_grid->cameraX;
-		backBottomRightPoint.y = zonePtr->bottomLeft.y - _engine->_grid->cameraY;
-		backBottomRightPoint.z = zonePtr->bottomLeft.z - _engine->_grid->cameraZ;
+		backBottomRightPoint.x = zonePtr->topRight.x - _engine->_grid->camera.x;
+		backBottomRightPoint.y = zonePtr->bottomLeft.y - _engine->_grid->camera.y;
+		backBottomRightPoint.z = zonePtr->bottomLeft.z - _engine->_grid->camera.z;
 
-		backTopLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->cameraX;
-		backTopLeftPoint.y = zonePtr->topRight.y - _engine->_grid->cameraY;
-		backTopLeftPoint.z = zonePtr->bottomLeft.z - _engine->_grid->cameraZ;
+		backTopLeftPoint.x = zonePtr->bottomLeft.x - _engine->_grid->camera.x;
+		backTopLeftPoint.y = zonePtr->topRight.y - _engine->_grid->camera.y;
+		backTopLeftPoint.z = zonePtr->bottomLeft.z - _engine->_grid->camera.z;
 
-		backTopRightPoint.x = zonePtr->topRight.x - _engine->_grid->cameraX;
-		backTopRightPoint.y = zonePtr->topRight.y - _engine->_grid->cameraY;
-		backTopRightPoint.z = zonePtr->bottomLeft.z - _engine->_grid->cameraZ;
+		backTopRightPoint.x = zonePtr->topRight.x - _engine->_grid->camera.x;
+		backTopRightPoint.y = zonePtr->topRight.y - _engine->_grid->camera.y;
+		backTopRightPoint.z = zonePtr->bottomLeft.z - _engine->_grid->camera.z;
 
 		// project all points
 
diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index 626554f52b..154ee9388f 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -200,7 +200,7 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 		// no redraw required
 		if (actor->staticFlags.bIsBackgrounded && !bgRedraw) {
 			// get actor position on screen
-			_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->cameraX, actor->y - _engine->_grid->cameraY, actor->z - _engine->_grid->cameraZ);
+			_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
 
 			// check if actor is visible on screen, otherwise don't display it
 			if (_engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100) {
@@ -213,24 +213,24 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 			continue;
 		}
 		// get actor position on screen
-		_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->cameraX, actor->y - _engine->_grid->cameraY, actor->z - _engine->_grid->cameraZ);
+		_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
 
 		if ((actor->staticFlags.bUsesClipping && _engine->_renderer->projPosX > -112 && _engine->_renderer->projPosX < _engine->width() + 112 && _engine->_renderer->projPosY > -50 && _engine->_renderer->projPosY < _engine->height() + 171) ||
 		    ((!actor->staticFlags.bUsesClipping) && _engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100)) {
 
-			int32 tmpVal = actor->z + actor->x - _engine->_grid->cameraX - _engine->_grid->cameraZ;
+			int32 tmpVal = actor->z + actor->x - _engine->_grid->camera.x - _engine->_grid->camera.z;
 
 			// if actor is above another actor
 			if (actor->standOn != -1) {
 				const ActorStruct *standOnActor = _engine->_scene->getActor(actor->standOn);
-				tmpVal = standOnActor->x - _engine->_grid->cameraX + standOnActor->z - _engine->_grid->cameraZ + 2;
+				tmpVal = standOnActor->x - _engine->_grid->camera.x + standOnActor->z - _engine->_grid->camera.z + 2;
 			}
 
 			if (actor->staticFlags.bIsSpriteActor) {
 				drawList[drawListPos].type = DrawListType::DrawActorSprites;
 				drawList[drawListPos].actorIdx = modelActorPos;
 				if (actor->staticFlags.bUsesClipping) {
-					tmpVal = actor->lastX - _engine->_grid->cameraX + actor->lastZ - _engine->_grid->cameraZ;
+					tmpVal = actor->lastX - _engine->_grid->camera.x + actor->lastZ - _engine->_grid->camera.z;
 				}
 			} else {
 				drawList[drawListPos].type = 0;
@@ -285,10 +285,10 @@ int32 Redraw::fillExtraDrawingList(int32 drawListPos) {
 			continue;
 		}
 		if ((extra->type & ExtraType::TIME_OUT) || (extra->type & ExtraType::FLASH) || (extra->payload.lifeTime + extra->spawnTime - 150 < _engine->lbaTime) || (!((_engine->lbaTime + extra->spawnTime) & 8))) {
-			_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->cameraX, extra->y - _engine->_grid->cameraY, extra->z - _engine->_grid->cameraZ);
+			_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->camera.x, extra->y - _engine->_grid->camera.y, extra->z - _engine->_grid->camera.z);
 
 			if (_engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100) {
-				drawList[drawListPos].posValue = extra->x - _engine->_grid->cameraX + extra->z - _engine->_grid->cameraZ;
+				drawList[drawListPos].posValue = extra->x - _engine->_grid->camera.x + extra->z - _engine->_grid->camera.z;
 				drawList[drawListPos].actorIdx = i;
 				drawList[drawListPos].type = DrawListType::DrawExtras;
 				drawListPos++;
@@ -296,7 +296,7 @@ int32 Redraw::fillExtraDrawingList(int32 drawListPos) {
 				if (_engine->cfgfile.ShadowMode == 2 && !(extra->info0 & 0x8000)) {
 					_engine->_movements->getShadowPosition(extra->x, extra->y, extra->z);
 
-					drawList[drawListPos].posValue = extra->x - _engine->_grid->cameraX + extra->z - _engine->_grid->cameraZ - 1;
+					drawList[drawListPos].posValue = extra->x - _engine->_grid->camera.x + extra->z - _engine->_grid->camera.z - 1;
 					drawList[drawListPos].actorIdx = 0;
 					drawList[drawListPos].type = DrawListType::DrawShadows;
 					drawList[drawListPos].x = _engine->_actor->shadowX;
@@ -313,7 +313,7 @@ int32 Redraw::fillExtraDrawingList(int32 drawListPos) {
 
 void Redraw::processDrawListShadows(const DrawListStruct &drawCmd) {
 	// get actor position on screen
-	_engine->_renderer->projectPositionOnScreen(drawCmd.x - _engine->_grid->cameraX, drawCmd.y - _engine->_grid->cameraY, drawCmd.z - _engine->_grid->cameraZ);
+	_engine->_renderer->projectPositionOnScreen(drawCmd.x - _engine->_grid->camera.x, drawCmd.y - _engine->_grid->camera.y, drawCmd.z - _engine->_grid->camera.z);
 
 	int32 spriteWidth, spriteHeight;
 	_engine->_grid->getSpriteSize(drawCmd.offset, &spriteWidth, &spriteHeight, _engine->_resources->spriteShadowPtr);
@@ -347,9 +347,9 @@ void Redraw::processDrawListActors(const DrawListStruct &drawCmd, bool bgRedraw)
 	const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
 	_engine->_animations->setModelAnimation(actor->animPosition, animData, animPtr, _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 
-	const int32 x = actor->x - _engine->_grid->cameraX;
-	const int32 y = actor->y - _engine->_grid->cameraY;
-	const int32 z = actor->z - _engine->_grid->cameraZ;
+	const int32 x = actor->x - _engine->_grid->camera.x;
+	const int32 y = actor->y - _engine->_grid->camera.y;
+	const int32 z = actor->z - _engine->_grid->camera.z;
 	if (!_engine->_renderer->renderIsoModel(x, y, z, ANGLE_0, actor->angle, ANGLE_0, _engine->_actor->bodyTable[actor->entity])) {
 		return;
 	}
@@ -406,7 +406,7 @@ void Redraw::processDrawListActorSprites(const DrawListStruct &drawCmd, bool bgR
 	const uint8 *spritePtr = _engine->_resources->spriteTable[actor->entity];
 
 	// get actor position on screen
-	_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->cameraX, actor->y - _engine->_grid->cameraY, actor->z - _engine->_grid->cameraZ);
+	_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
 
 	const int32 spriteWidth = spriteData.surface().w;
 	const int32 spriteHeight = spriteData.surface().h;
@@ -461,7 +461,7 @@ void Redraw::processDrawListExtras(const DrawListStruct &drawCmd) {
 	int32 actorIdx = drawCmd.actorIdx;
 	ExtraListStruct *extra = &_engine->_extra->extraList[actorIdx];
 
-	_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->cameraX, extra->y - _engine->_grid->cameraY, extra->z - _engine->_grid->cameraZ);
+	_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->camera.x, extra->y - _engine->_grid->camera.y, extra->z - _engine->_grid->camera.z);
 
 	if (extra->info0 & 0x8000) {
 		_engine->_extra->drawExtraSpecial(actorIdx, _engine->_renderer->projPosX, _engine->_renderer->projPosY);
@@ -542,7 +542,7 @@ void Redraw::renderOverlays() {
 			case OverlayPosType::koFollowActor: {
 				ActorStruct *actor2 = _engine->_scene->getActor(overlay->info1);
 
-				_engine->_renderer->projectPositionOnScreen(actor2->x - _engine->_grid->cameraX, actor2->y + actor2->boudingBox.y.topRight - _engine->_grid->cameraY, actor2->z - _engine->_grid->cameraZ);
+				_engine->_renderer->projectPositionOnScreen(actor2->x - _engine->_grid->camera.x, actor2->y + actor2->boudingBox.y.topRight - _engine->_grid->camera.y, actor2->z - _engine->_grid->camera.z);
 
 				overlay->x = _engine->_renderer->projPosX;
 				overlay->y = _engine->_renderer->projPosY;
@@ -746,7 +746,7 @@ void Redraw::drawBubble(int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 
 	// get actor position on screen
-	_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->cameraX, actor->y + actor->boudingBox.y.topRight - _engine->_grid->cameraY, actor->z - _engine->_grid->cameraZ);
+	_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y + actor->boudingBox.y.topRight - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
 
 	if (actorIdx != bubbleActor) {
 		bubbleSpriteIndex = bubbleSpriteIndex ^ 1;
diff --git a/engines/twine/scene/extra.cpp b/engines/twine/scene/extra.cpp
index 95527d8348..134ddbfb8f 100644
--- a/engines/twine/scene/extra.cpp
+++ b/engines/twine/scene/extra.cpp
@@ -692,7 +692,7 @@ void Extra::processExtras() {
 				_engine->_sound->playSample(Samples::ItemFound, 1, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->y, _engine->_scene->sceneHero->z, OWN_ACTOR_SCENE_INDEX);
 
 				if (extraKey->info1 > 1) {
-					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->cameraX, extraKey->y - _engine->_grid->cameraY, extraKey->z - _engine->_grid->cameraZ);
+					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->camera.x, extraKey->y - _engine->_grid->camera.y, extraKey->z - _engine->_grid->camera.z);
 					_engine->_redraw->addOverlay(OverlayType::koNumber, extraKey->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, 0, OverlayPosType::koNormal, 2);
 				}
 
@@ -725,7 +725,7 @@ void Extra::processExtras() {
 				_engine->_sound->playSample(Samples::ItemFound, 1, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->y, _engine->_scene->sceneHero->z, OWN_ACTOR_SCENE_INDEX);
 
 				if (extraKey->info1 > 1) {
-					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->cameraX, extraKey->y - _engine->_grid->cameraY, extraKey->z - _engine->_grid->cameraZ);
+					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->camera.x, extraKey->y - _engine->_grid->camera.y, extraKey->z - _engine->_grid->camera.z);
 					_engine->_redraw->addOverlay(OverlayType::koNumber, extraKey->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, 0, OverlayPosType::koNormal, 2);
 				}
 
@@ -871,7 +871,7 @@ void Extra::processExtras() {
 				_engine->_sound->playSample(Samples::ItemFound, 1, extra->x, extra->y, extra->z);
 
 				if (extra->info1 > 1 && !_engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
-					_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->cameraX, extra->y - _engine->_grid->cameraY, extra->z - _engine->_grid->cameraZ);
+					_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->camera.x, extra->y - _engine->_grid->camera.y, extra->z - _engine->_grid->camera.z);
 					const int16 fontColor = 158;
 					_engine->_redraw->addOverlay(OverlayType::koNumber, extra->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, fontColor, OverlayPosType::koNormal, 2);
 				}
diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index cdcbdc31b3..959aed9bf3 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -317,9 +317,9 @@ void GameState::processFoundItem(int32 item) {
 
 	_engine->_screens->copyScreen(_engine->frontVideoBuffer, _engine->workVideoBuffer);
 
-	const int32 itemCameraX = _engine->_grid->newCameraX * BRICK_SIZE;
-	const int32 itemCameraY = _engine->_grid->newCameraY * BRICK_HEIGHT;
-	const int32 itemCameraZ = _engine->_grid->newCameraZ * BRICK_SIZE;
+	const int32 itemCameraX = _engine->_grid->newCamera.x * BRICK_SIZE;
+	const int32 itemCameraY = _engine->_grid->newCamera.y * BRICK_HEIGHT;
+	const int32 itemCameraZ = _engine->_grid->newCamera.z * BRICK_SIZE;
 
 	uint8 *bodyPtr = _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity];
 	const int32 bodyX = _engine->_scene->sceneHero->x - itemCameraX;
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index 3c2518f509..300f15dc8a 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -634,7 +634,7 @@ void Grid::drawColumnGrid(int32 blockIdx, int32 brickBlockIdx, int32 x, int32 y,
 		return;
 	}
 
-	getBrickPos(x - newCameraX, y - newCameraY, z - newCameraZ);
+	getBrickPos(x - newCamera.x, y - newCamera.y, z - newCamera.z);
 
 	if (brickPixelPosX < -24) {
 		return;
@@ -676,11 +676,11 @@ void Grid::drawColumnGrid(int32 blockIdx, int32 brickBlockIdx, int32 x, int32 y,
 void Grid::redrawGrid() {
 	blockMap *map = (blockMap *)blockBuffer;
 
-	cameraX = newCameraX * BRICK_SIZE;
-	cameraY = newCameraY * BRICK_HEIGHT;
-	cameraZ = newCameraZ * BRICK_SIZE;
+	camera.x = newCamera.x * BRICK_SIZE;
+	camera.y = newCamera.y * BRICK_HEIGHT;
+	camera.z = newCamera.z * BRICK_SIZE;
 
-	_engine->_renderer->projectPositionOnScreen(-cameraX, -cameraY, -cameraZ);
+	_engine->_renderer->projectPositionOnScreen(-camera.x, -camera.y, -camera.z);
 
 	_engine->_renderer->projPosXScreen = _engine->_renderer->projPosX;
 	_engine->_renderer->projPosYScreen = _engine->_renderer->projPosY;
@@ -856,9 +856,9 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 }
 
 void Grid::centerOnActor(const ActorStruct* actor) {
-	newCameraX = (actor->x + BRICK_HEIGHT) / BRICK_SIZE;
-	newCameraY = (actor->y + BRICK_HEIGHT) / BRICK_HEIGHT;
-	newCameraZ = (actor->z + BRICK_HEIGHT) / BRICK_SIZE;
+	newCamera.x = (actor->x + BRICK_HEIGHT) / BRICK_SIZE;
+	newCamera.y = (actor->y + BRICK_HEIGHT) / BRICK_HEIGHT;
+	newCamera.z = (actor->z + BRICK_HEIGHT) / BRICK_SIZE;
 	_engine->_redraw->reqBgRedraw = true;
 }
 
diff --git a/engines/twine/scene/grid.h b/engines/twine/scene/grid.h
index f5d7d9aa21..b5d2ca17af 100644
--- a/engines/twine/scene/grid.h
+++ b/engines/twine/scene/grid.h
@@ -196,19 +196,11 @@ public:
 	 */
 	const uint8 *getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground);
 
-	/** New grid camera X coordinates */
-	int32 newCameraX = 0;
-	/** New grid camera Y coordinates */
-	int32 newCameraY = 0;
-	/** New grid camera Z coordinates */
-	int32 newCameraZ = 0;
-
-	/** Current grid camera X coordinates */
-	int32 cameraX = 0;
-	/** Current grid camera Y coordinates */
-	int32 cameraY = 0;
-	/** Current grid camera Z coordinates */
-	int32 cameraZ = 0;
+	/** New grid camera x, y and z coordinates */
+	Vec3 newCamera;
+
+	/** Current grid camera x, y and z coordinates */
+	Vec3 camera;
 
 	/** Flag to know if the engine is using celling grids */
 	int16 useCellingGrid = 0; // useAnotherGrm
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index 8a05a91e8a..6d64eaab37 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -674,10 +674,10 @@ void Scene::processActorZones(int32 actorIdx) {
 			case ZoneType::kCamera:
 				if (currentlyFollowedActor == actorIdx && !_engine->_debugGrid->useFreeCamera) {
 					_engine->disableScreenRecenter = true;
-					if (_engine->_grid->newCameraX != zone->infoData.CameraView.x || _engine->_grid->newCameraY != zone->infoData.CameraView.y || _engine->_grid->newCameraZ != zone->infoData.CameraView.z) {
-						_engine->_grid->newCameraX = zone->infoData.CameraView.x;
-						_engine->_grid->newCameraY = zone->infoData.CameraView.y;
-						_engine->_grid->newCameraZ = zone->infoData.CameraView.z;
+					if (_engine->_grid->newCamera.x != zone->infoData.CameraView.x || _engine->_grid->newCamera.y != zone->infoData.CameraView.y || _engine->_grid->newCamera.z != zone->infoData.CameraView.z) {
+						_engine->_grid->newCamera.x = zone->infoData.CameraView.x;
+						_engine->_grid->newCamera.y = zone->infoData.CameraView.y;
+						_engine->_grid->newCamera.z = zone->infoData.CameraView.z;
 						_engine->_redraw->reqBgRedraw = true;
 					}
 				}
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 3716e98002..9d96fb619a 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -31,9 +31,11 @@
 namespace TwinE {
 
 struct Vec3 {
-	int32 x = 0;
-	int32 y = 0;
-	int32 z = 0;
+	Vec3() : x(0), y(0), z(0) {}
+	Vec3(int32 _x, int32 _y, int32 _z) : x(_x), y(_y), z(_z) {}
+	int32 x;
+	int32 y;
+	int32 z;
 };
 
 struct BoundingBox {
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 8b2ad469e9..642d617445 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -693,20 +693,20 @@ void TwinEEngine::centerScreenOnActor() {
 	}
 
 	ActorStruct *actor = _scene->getActor(_scene->currentlyFollowedActor);
-	_renderer->projectPositionOnScreen(actor->x - (_grid->newCameraX * BRICK_SIZE),
-	                                   actor->y - (_grid->newCameraY * BRICK_HEIGHT),
-	                                   actor->z - (_grid->newCameraZ * BRICK_SIZE));
+	_renderer->projectPositionOnScreen(actor->x - (_grid->newCamera.x * BRICK_SIZE),
+	                                   actor->y - (_grid->newCamera.y * BRICK_HEIGHT),
+	                                   actor->z - (_grid->newCamera.z * BRICK_SIZE));
 	if (_renderer->projPosX < 80 || _renderer->projPosX >= width() - 60 || _renderer->projPosY < 80 || _renderer->projPosY >= height() - 50) {
-		_grid->newCameraX = ((actor->x + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->x + BRICK_HEIGHT) / BRICK_SIZE) - _grid->newCameraX) / 2;
-		_grid->newCameraY = actor->y / BRICK_HEIGHT;
-		_grid->newCameraZ = ((actor->z + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->z + BRICK_HEIGHT) / BRICK_SIZE) - _grid->newCameraZ) / 2;
+		_grid->newCamera.x = ((actor->x + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->x + BRICK_HEIGHT) / BRICK_SIZE) - _grid->newCamera.x) / 2;
+		_grid->newCamera.y = actor->y / BRICK_HEIGHT;
+		_grid->newCamera.z = ((actor->z + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->z + BRICK_HEIGHT) / BRICK_SIZE) - _grid->newCamera.z) / 2;
 
-		if (_grid->newCameraX >= GRID_SIZE_X) {
-			_grid->newCameraX = GRID_SIZE_X - 1;
+		if (_grid->newCamera.x >= GRID_SIZE_X) {
+			_grid->newCamera.x = GRID_SIZE_X - 1;
 		}
 
-		if (_grid->newCameraZ >= GRID_SIZE_Z) {
-			_grid->newCameraZ = GRID_SIZE_Z - 1;
+		if (_grid->newCamera.z >= GRID_SIZE_Z) {
+			_grid->newCamera.z = GRID_SIZE_Z - 1;
 		}
 
 		_redraw->reqBgRedraw = true;
@@ -932,10 +932,10 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 						if (_actor->heroBehaviour != HeroBehaviourType::kProtoPack || actor->anim != AnimationTypes::kForward) {
 							if (!_actor->cropBottomScreen) {
 								_animations->initAnim(AnimationTypes::kDrawn, kAnimationType_4, AnimationTypes::kStanding, 0);
-								_renderer->projectPositionOnScreen(actor->x - _grid->cameraX, actor->y - _grid->cameraY, actor->z - _grid->cameraZ);
+								_renderer->projectPositionOnScreen(actor->x - _grid->camera.x, actor->y - _grid->camera.y, actor->z - _grid->camera.z);
 								_actor->cropBottomScreen = _renderer->projPosY;
 							}
-							_renderer->projectPositionOnScreen(actor->x - _grid->cameraX, actor->y - _grid->cameraY, actor->z - _grid->cameraZ);
+							_renderer->projectPositionOnScreen(actor->x - _grid->camera.x, actor->y - _grid->camera.y, actor->z - _grid->camera.z);
 							actor->controlMode = ControlMode::kNoMove;
 							actor->life = -1;
 							_actor->cropBottomScreen = _renderer->projPosY;


Commit: 1b14ab291949319db86c4a5575eea5841116f5d3
    https://github.com/scummvm/scummvm/commit/1b14ab291949319db86c4a5575eea5841116f5d3
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T16:43:28+01:00

Commit Message:
TWINE: moved centerScreenOnActor into Grid class

Changed paths:
    engines/twine/scene/grid.cpp
    engines/twine/scene/grid.h
    engines/twine/twine.cpp
    engines/twine/twine.h


diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index 300f15dc8a..fbe53197ee 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -24,6 +24,7 @@
 #include "common/endian.h"
 #include "common/memstream.h"
 #include "common/textconsole.h"
+#include "twine/debugger/debug_grid.h"
 #include "twine/menu/interface.h"
 #include "twine/renderer/redraw.h"
 #include "twine/renderer/renderer.h"
@@ -862,5 +863,33 @@ void Grid::centerOnActor(const ActorStruct* actor) {
 	_engine->_redraw->reqBgRedraw = true;
 }
 
+void Grid::centerScreenOnActor() {
+	if (_engine->disableScreenRecenter) {
+		return;
+	}
+	if (_engine->_debugGrid->useFreeCamera) {
+		return;
+	}
+
+	ActorStruct *actor = _engine->_scene->getActor(_engine->_scene->currentlyFollowedActor);
+	_engine->_renderer->projectPositionOnScreen(actor->x - (newCamera.x * BRICK_SIZE),
+	                                   actor->y - (newCamera.y * BRICK_HEIGHT),
+	                                   actor->z - (newCamera.z * BRICK_SIZE));
+	if (_engine->_renderer->projPosX < 80 || _engine->_renderer->projPosX >= _engine->width() - 60 || _engine->_renderer->projPosY < 80 || _engine->_renderer->projPosY >= _engine->height() - 50) {
+		newCamera.x = ((actor->x + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->x + BRICK_HEIGHT) / BRICK_SIZE) - newCamera.x) / 2;
+		newCamera.y = actor->y / BRICK_HEIGHT;
+		newCamera.z = ((actor->z + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->z + BRICK_HEIGHT) / BRICK_SIZE) - newCamera.z) / 2;
+
+		if (newCamera.x >= GRID_SIZE_X) {
+			newCamera.x = GRID_SIZE_X - 1;
+		}
+
+		if (newCamera.z >= GRID_SIZE_Z) {
+			newCamera.z = GRID_SIZE_Z - 1;
+		}
+
+		_engine->_redraw->reqBgRedraw = true;
+	}
+}
 
 } // namespace TwinE
diff --git a/engines/twine/scene/grid.h b/engines/twine/scene/grid.h
index b5d2ca17af..2cc1f9be87 100644
--- a/engines/twine/scene/grid.h
+++ b/engines/twine/scene/grid.h
@@ -232,6 +232,8 @@ public:
 	 */
 	void getSpriteSize(int32 offset, int32 *width, int32 *height, const uint8 *spritePtr);
 
+	/** recenter screen on followed actor automatically */
+	void centerScreenOnActor();
 	void centerOnActor(const ActorStruct* actor);
 
 	/**
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 642d617445..b1e16b1096 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -684,35 +684,6 @@ void TwinEEngine::processOptionsMenu() {
 	_redraw->redrawEngineActions(true);
 }
 
-void TwinEEngine::centerScreenOnActor() {
-	if (disableScreenRecenter) {
-		return;
-	}
-	if (_debugGrid->useFreeCamera) {
-		return;
-	}
-
-	ActorStruct *actor = _scene->getActor(_scene->currentlyFollowedActor);
-	_renderer->projectPositionOnScreen(actor->x - (_grid->newCamera.x * BRICK_SIZE),
-	                                   actor->y - (_grid->newCamera.y * BRICK_HEIGHT),
-	                                   actor->z - (_grid->newCamera.z * BRICK_SIZE));
-	if (_renderer->projPosX < 80 || _renderer->projPosX >= width() - 60 || _renderer->projPosY < 80 || _renderer->projPosY >= height() - 50) {
-		_grid->newCamera.x = ((actor->x + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->x + BRICK_HEIGHT) / BRICK_SIZE) - _grid->newCamera.x) / 2;
-		_grid->newCamera.y = actor->y / BRICK_HEIGHT;
-		_grid->newCamera.z = ((actor->z + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->z + BRICK_HEIGHT) / BRICK_SIZE) - _grid->newCamera.z) / 2;
-
-		if (_grid->newCamera.x >= GRID_SIZE_X) {
-			_grid->newCamera.x = GRID_SIZE_X - 1;
-		}
-
-		if (_grid->newCamera.z >= GRID_SIZE_Z) {
-			_grid->newCamera.z = GRID_SIZE_Z - 1;
-		}
-
-		_redraw->reqBgRedraw = true;
-	}
-}
-
 int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 	FrameMarker frame;
 	_input->enableKeyMap(mainKeyMapId);
@@ -1009,7 +980,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		}
 	}
 
-	centerScreenOnActor();
+	_grid->centerScreenOnActor();
 
 	_redraw->redrawEngineActions(_redraw->reqBgRedraw);
 
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 81b35f01c2..bdb6e6391a 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -193,8 +193,6 @@ private:
 	void processBonusList();
 	void processInventoryAction();
 	void processOptionsMenu();
-	/** recenter screen on followed actor automatically */
-	void centerScreenOnActor();
 
 	void initConfigurations();
 	/** Initialize all needed stuffs at first time running engine */


Commit: a819f61e8c932e6b698d5a41b446ae3501188719
    https://github.com/scummvm/scummvm/commit/a819f61e8c932e6b698d5a41b446ae3501188719
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:06:23+01:00

Commit Message:
TWINE: moved actor position into Vec3 struct

Changed paths:
    engines/twine/audio/sound.h
    engines/twine/debugger/console.cpp
    engines/twine/renderer/redraw.cpp
    engines/twine/scene/actor.cpp
    engines/twine/scene/actor.h
    engines/twine/scene/animations.cpp
    engines/twine/scene/collision.cpp
    engines/twine/scene/extra.cpp
    engines/twine/scene/gamestate.cpp
    engines/twine/scene/grid.cpp
    engines/twine/scene/movements.cpp
    engines/twine/scene/movements.h
    engines/twine/scene/scene.cpp
    engines/twine/script/script_life_v1.cpp
    engines/twine/script/script_move_v1.cpp
    engines/twine/twine.cpp


diff --git a/engines/twine/audio/sound.h b/engines/twine/audio/sound.h
index c17a80e5e7..9289eea8ea 100644
--- a/engines/twine/audio/sound.h
+++ b/engines/twine/audio/sound.h
@@ -26,6 +26,7 @@
 #include "audio/mixer.h"
 #include "common/scummsys.h"
 #include "common/types.h"
+#include "twine/shared.h"
 
 namespace TwinE {
 
@@ -95,6 +96,9 @@ public:
 	 * @param actorIdx
 	 */
 	void playSample(int32 index, int32 repeat = 1, int32 x = 128, int32 y = 128, int32 z = 128, int32 actorIdx = -1);
+	void playSample(int32 index, int32 repeat, const Vec3 &pos, int32 actorIdx = -1) {
+		playSample(index, repeat, pos.x, pos.y, pos.z, actorIdx);
+	}
 
 	/** Pause samples */
 	void pauseSamples();
diff --git a/engines/twine/debugger/console.cpp b/engines/twine/debugger/console.cpp
index 032b2091b5..f7e42609a1 100644
--- a/engines/twine/debugger/console.cpp
+++ b/engines/twine/debugger/console.cpp
@@ -288,15 +288,15 @@ bool TwinEConsole::doListMenuText(int argc, const char **argv) {
 
 bool TwinEConsole::doSetHeroPosition(int argc, const char **argv) {
 	if (argc < 4) {
-		debugPrintf("Current hero position: %i:%i:%i\n", _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->y, _engine->_scene->sceneHero->z);
+		debugPrintf("Current hero position: %i:%i:%i\n", _engine->_scene->sceneHero->pos.x, _engine->_scene->sceneHero->pos.y, _engine->_scene->sceneHero->pos.z);
 		return true;
 	}
 	const int16 x = atoi(argv[1]);
 	const int16 y = atoi(argv[2]);
 	const int16 z = atoi(argv[3]);
-	_engine->_scene->sceneHero->x = x;
-	_engine->_scene->sceneHero->y = y;
-	_engine->_scene->sceneHero->z = z;
+	_engine->_scene->sceneHero->pos.x = x;
+	_engine->_scene->sceneHero->pos.y = y;
+	_engine->_scene->sceneHero->pos.z = z;
 	return true;
 }
 
diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index 154ee9388f..f861c7e984 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -194,13 +194,13 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 		ActorStruct *actor = _engine->_scene->getActor(modelActorPos);
 		actor->dynamicFlags.bIsVisible = 0; // reset visible state
 
-		if (_engine->_grid->useCellingGrid != -1 && actor->y > _engine->_scene->sceneZones[_engine->_grid->cellingGridIdx].topRight.y) {
+		if (_engine->_grid->useCellingGrid != -1 && actor->pos.y > _engine->_scene->sceneZones[_engine->_grid->cellingGridIdx].topRight.y) {
 			continue;
 		}
 		// no redraw required
 		if (actor->staticFlags.bIsBackgrounded && !bgRedraw) {
 			// get actor position on screen
-			_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
+			_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
 
 			// check if actor is visible on screen, otherwise don't display it
 			if (_engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100) {
@@ -213,17 +213,17 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 			continue;
 		}
 		// get actor position on screen
-		_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
+		_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
 
 		if ((actor->staticFlags.bUsesClipping && _engine->_renderer->projPosX > -112 && _engine->_renderer->projPosX < _engine->width() + 112 && _engine->_renderer->projPosY > -50 && _engine->_renderer->projPosY < _engine->height() + 171) ||
 		    ((!actor->staticFlags.bUsesClipping) && _engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100)) {
 
-			int32 tmpVal = actor->z + actor->x - _engine->_grid->camera.x - _engine->_grid->camera.z;
+			int32 tmpVal = actor->pos.z + actor->pos.x - _engine->_grid->camera.x - _engine->_grid->camera.z;
 
 			// if actor is above another actor
 			if (actor->standOn != -1) {
 				const ActorStruct *standOnActor = _engine->_scene->getActor(actor->standOn);
-				tmpVal = standOnActor->x - _engine->_grid->camera.x + standOnActor->z - _engine->_grid->camera.z + 2;
+				tmpVal = standOnActor->pos.x - _engine->_grid->camera.x + standOnActor->pos.z - _engine->_grid->camera.z + 2;
 			}
 
 			if (actor->staticFlags.bIsSpriteActor) {
@@ -244,11 +244,11 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 			// if use shadows
 			if (_engine->cfgfile.ShadowMode != 0 && !(actor->staticFlags.bDoesntCastShadow)) {
 				if (actor->standOn != -1) {
-					_engine->_actor->shadowX = actor->x;
-					_engine->_actor->shadowY = actor->y - 1;
-					_engine->_actor->shadowZ = actor->z;
+					_engine->_actor->shadowX = actor->pos.x;
+					_engine->_actor->shadowY = actor->pos.y - 1;
+					_engine->_actor->shadowZ = actor->pos.z;
 				} else {
-					_engine->_movements->getShadowPosition(actor->x, actor->y, actor->z);
+					_engine->_movements->getShadowPosition(actor->pos.x, actor->pos.y, actor->pos.z);
 				}
 
 				tmpVal--;
@@ -347,9 +347,9 @@ void Redraw::processDrawListActors(const DrawListStruct &drawCmd, bool bgRedraw)
 	const AnimData &animData = _engine->_resources->animData[actor->previousAnimIdx];
 	_engine->_animations->setModelAnimation(actor->animPosition, animData, animPtr, _engine->_actor->bodyTable[actor->entity], &actor->animTimerData);
 
-	const int32 x = actor->x - _engine->_grid->camera.x;
-	const int32 y = actor->y - _engine->_grid->camera.y;
-	const int32 z = actor->z - _engine->_grid->camera.z;
+	const int32 x = actor->pos.x - _engine->_grid->camera.x;
+	const int32 y = actor->pos.y - _engine->_grid->camera.y;
+	const int32 z = actor->pos.z - _engine->_grid->camera.z;
 	if (!_engine->_renderer->renderIsoModel(x, y, z, ANGLE_0, actor->angle, ANGLE_0, _engine->_actor->bodyTable[actor->entity])) {
 		return;
 	}
@@ -375,9 +375,9 @@ void Redraw::processDrawListActors(const DrawListStruct &drawCmd, bool bgRedraw)
 	if (_engine->_interface->textWindow.left <= _engine->_interface->textWindow.right && _engine->_interface->textWindow.top <= _engine->_interface->textWindow.bottom) {
 		actor->dynamicFlags.bIsVisible = 1;
 
-		const int32 tempX = (actor->x + BRICK_HEIGHT) / BRICK_SIZE;
-		int32 tempY = actor->y / BRICK_HEIGHT;
-		const int32 tempZ = (actor->z + BRICK_HEIGHT) / BRICK_SIZE;
+		const int32 tempX = (actor->pos.x + BRICK_HEIGHT) / BRICK_SIZE;
+		int32 tempY = actor->pos.y / BRICK_HEIGHT;
+		const int32 tempZ = (actor->pos.z + BRICK_HEIGHT) / BRICK_SIZE;
 		if (actor->brickShape() != ShapeType::kNone) {
 			tempY++;
 		}
@@ -406,7 +406,7 @@ void Redraw::processDrawListActorSprites(const DrawListStruct &drawCmd, bool bgR
 	const uint8 *spritePtr = _engine->_resources->spriteTable[actor->entity];
 
 	// get actor position on screen
-	_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
+	_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
 
 	const int32 spriteWidth = spriteData.surface().w;
 	const int32 spriteHeight = spriteData.surface().h;
@@ -436,9 +436,9 @@ void Redraw::processDrawListActorSprites(const DrawListStruct &drawCmd, bool bgR
 			const int32 tmpZ = (actor->lastZ + BRICK_HEIGHT) / BRICK_SIZE;
 			_engine->_grid->drawOverSpriteActor(tmpX, tmpY, tmpZ);
 		} else {
-			const int32 tmpX = (actor->x + actor->boudingBox.x.topRight + BRICK_HEIGHT) / BRICK_SIZE;
-			int32 tmpY = actor->y / BRICK_HEIGHT;
-			const int32 tmpZ = (actor->z + actor->boudingBox.z.topRight + BRICK_HEIGHT) / BRICK_SIZE;
+			const int32 tmpX = (actor->pos.x + actor->boudingBox.x.topRight + BRICK_HEIGHT) / BRICK_SIZE;
+			int32 tmpY = actor->pos.y / BRICK_HEIGHT;
+			const int32 tmpZ = (actor->pos.z + actor->boudingBox.z.topRight + BRICK_HEIGHT) / BRICK_SIZE;
 			if (actor->brickShape() != ShapeType::kNone) {
 				tmpY++;
 			}
@@ -542,7 +542,7 @@ void Redraw::renderOverlays() {
 			case OverlayPosType::koFollowActor: {
 				ActorStruct *actor2 = _engine->_scene->getActor(overlay->info1);
 
-				_engine->_renderer->projectPositionOnScreen(actor2->x - _engine->_grid->camera.x, actor2->y + actor2->boudingBox.y.topRight - _engine->_grid->camera.y, actor2->z - _engine->_grid->camera.z);
+				_engine->_renderer->projectPositionOnScreen(actor2->pos.x - _engine->_grid->camera.x, actor2->pos.y + actor2->boudingBox.y.topRight - _engine->_grid->camera.y, actor2->pos.z - _engine->_grid->camera.z);
 
 				overlay->x = _engine->_renderer->projPosX;
 				overlay->y = _engine->_renderer->projPosY;
@@ -746,7 +746,7 @@ void Redraw::drawBubble(int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 
 	// get actor position on screen
-	_engine->_renderer->projectPositionOnScreen(actor->x - _engine->_grid->camera.x, actor->y + actor->boudingBox.y.topRight - _engine->_grid->camera.y, actor->z - _engine->_grid->camera.z);
+	_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y + actor->boudingBox.y.topRight - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
 
 	if (actorIdx != bubbleActor) {
 		bubbleSpriteIndex = bubbleSpriteIndex ^ 1;
diff --git a/engines/twine/scene/actor.cpp b/engines/twine/scene/actor.cpp
index 392ba6970e..e18d69e7f2 100644
--- a/engines/twine/scene/actor.cpp
+++ b/engines/twine/scene/actor.cpp
@@ -322,9 +322,9 @@ void Actor::initActor(int16 actorIdx) {
 		_engine->_movements->setActorAngleSafe(ANGLE_0, ANGLE_0, ANGLE_0, &actor->move);
 
 		if (actor->staticFlags.bUsesClipping) {
-			actor->lastX = actor->x;
-			actor->lastY = actor->y;
-			actor->lastZ = actor->z;
+			actor->lastX = actor->pos.x;
+			actor->lastY = actor->pos.y;
+			actor->lastZ = actor->pos.z;
 		}
 	} else {
 		actor->entity = -1;
@@ -353,9 +353,9 @@ void Actor::resetActor(int16 actorIdx) {
 	actor->actorIdx = actorIdx;
 	actor->body = BodyType::btNormal;
 	actor->anim = AnimationTypes::kStanding;
-	actor->x = 0;
-	actor->y = -1;
-	actor->z = 0;
+	actor->pos.x = 0;
+	actor->pos.y = -1;
+	actor->pos.z = 0;
 
 	ZVBox &bbox = actor->boudingBox;
 	bbox.x.bottomLeft = 0;
@@ -429,7 +429,7 @@ void Actor::hitActor(int32 actorIdx, int32 actorIdxAttacked, int32 strengthOfHit
 			}
 		}
 
-		_engine->_extra->addExtraSpecial(actor->x, actor->y + 1000, actor->z, ExtraSpecialType::kHitStars);
+		_engine->_extra->addExtraSpecial(actor->pos.x, actor->pos.y + 1000, actor->pos.z, ExtraSpecialType::kHitStars);
 
 		if (!actorIdxAttacked) {
 			_engine->_movements->heroMoved = true;
@@ -465,13 +465,13 @@ void Actor::processActorExtraBonus(int32 actorIdx) { // GiveExtraBonus
 		return;
 	}
 	if (actor->dynamicFlags.bIsDead) {
-		_engine->_extra->addExtraBonus(actor->x, actor->y, actor->z, ANGLE_90, ANGLE_0, bonusSprite, actor->bonusAmount);
-		_engine->_sound->playSample(Samples::ItemPopup, 1, actor->x, actor->y, actor->z, actorIdx);
+		_engine->_extra->addExtraBonus(actor->pos.x, actor->pos.y, actor->pos.z, ANGLE_90, ANGLE_0, bonusSprite, actor->bonusAmount);
+		_engine->_sound->playSample(Samples::ItemPopup, 1, actor->pos.x, actor->pos.y, actor->pos.z, actorIdx);
 	} else {
 		ActorStruct *sceneHero = _engine->_scene->sceneHero;
-		const int32 angle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, sceneHero->x, sceneHero->z);
-		_engine->_extra->addExtraBonus(actor->x, actor->y + actor->boudingBox.y.topRight, actor->z, ANGLE_70, angle, bonusSprite, actor->bonusAmount);
-		_engine->_sound->playSample(Samples::ItemPopup, 1, actor->x, actor->y + actor->boudingBox.y.topRight, actor->z, actorIdx);
+		const int32 angle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->pos.x, actor->pos.z, sceneHero->pos.x, sceneHero->pos.z);
+		_engine->_extra->addExtraBonus(actor->pos.x, actor->pos.y + actor->boudingBox.y.topRight, actor->pos.z, ANGLE_70, angle, bonusSprite, actor->bonusAmount);
+		_engine->_sound->playSample(Samples::ItemPopup, 1, actor->pos.x, actor->pos.y + actor->boudingBox.y.topRight, actor->pos.z, actorIdx);
 	}
 }
 
diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index 707de2bc1d..f39e6e9885 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -196,9 +196,7 @@ public:
 	bool isJumpAnimationActive() const;
 
 	int16 actorIdx = 0; // own actor index
-	int32 x = 0;
-	int32 y = 0;
-	int32 z = 0;
+	Vec3 pos;
 	int32 strengthOfHit = 0; // field_66
 	int32 hitBy = 0;
 	BonusParameter bonusParameter; // field_10
diff --git a/engines/twine/scene/animations.cpp b/engines/twine/scene/animations.cpp
index 16e7116516..c505948976 100644
--- a/engines/twine/scene/animations.cpp
+++ b/engines/twine/scene/animations.cpp
@@ -337,32 +337,32 @@ void Animations::processAnimActions(int32 actorIdx) {
 		case ActionType::ACTION_SAMPLE:
 		case ActionType::ACTION_SAMPLE_FREQ:
 			if (action.animFrame == actor->animPosition) {
-				_engine->_sound->playSample(action.sampleIndex, 1, actor->x, actor->y, actor->z, actorIdx);
+				_engine->_sound->playSample(action.sampleIndex, 1, actor->pos, actorIdx);
 			}
 			break;
 		case ActionType::ACTION_THROW_EXTRA_BONUS:
 			if (action.animFrame == actor->animPosition) {
-				_engine->_extra->addExtraThrow(actorIdx, actor->x, actor->y + action.yHeight, actor->z, action.spriteIndex, action.xAngle, action.yAngle, action.xRotPoint, action.extraAngle, action.strength);
+				_engine->_extra->addExtraThrow(actorIdx, actor->pos.x, actor->pos.y + action.yHeight, actor->pos.z, action.spriteIndex, action.xAngle, action.yAngle, action.xRotPoint, action.extraAngle, action.strength);
 			}
 			break;
 		case ActionType::ACTION_THROW_MAGIC_BALL:
 			if (_engine->_gameState->magicBallIdx == -1 && action.animFrame == actor->animPosition) {
-				_engine->_extra->addExtraThrowMagicball(actor->x, actor->y + action.yHeight, actor->z, action.xAngle, actor->angle + action.yAngle, action.xRotPoint, action.extraAngle);
+				_engine->_extra->addExtraThrowMagicball(actor->pos.x, actor->pos.y + action.yHeight, actor->pos.z, action.xAngle, actor->angle + action.yAngle, action.xRotPoint, action.extraAngle);
 			}
 			break;
 		case ActionType::ACTION_SAMPLE_REPEAT:
 			if (action.animFrame == actor->animPosition) {
-				_engine->_sound->playSample(action.sampleIndex, action.repeat, actor->x, actor->y, actor->z, actorIdx);
+				_engine->_sound->playSample(action.sampleIndex, action.repeat, actor->pos, actorIdx);
 			}
 			break;
 		case ActionType::ACTION_THROW_SEARCH:
 			if (action.animFrame == actor->animPosition) {
-				_engine->_extra->addExtraAiming(actorIdx, actor->x, actor->y + action.yHeight, actor->z, action.spriteIndex, action.targetActor, action.finalAngle, action.strength);
+				_engine->_extra->addExtraAiming(actorIdx, actor->pos.x, actor->pos.y + action.yHeight, actor->pos.z, action.spriteIndex, action.targetActor, action.finalAngle, action.strength);
 			}
 			break;
 		case ActionType::ACTION_THROW_ALPHA:
 			if (action.animFrame == actor->animPosition) {
-				_engine->_extra->addExtraThrow(actorIdx, actor->x, actor->y + action.yHeight, actor->z, action.spriteIndex, action.xAngle, actor->angle + action.yAngle, action.xRotPoint, action.extraAngle, action.strength);
+				_engine->_extra->addExtraThrow(actorIdx, actor->pos.x, actor->pos.y + action.yHeight, actor->pos.z, action.spriteIndex, action.xAngle, actor->angle + action.yAngle, action.xRotPoint, action.extraAngle, action.strength);
 			}
 			break;
 		case ActionType::ACTION_SAMPLE_STOP:
@@ -374,7 +374,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 		case ActionType::ACTION_RIGHT_STEP:
 			if (action.animFrame == actor->animPosition && (actor->brickSound & 0x0F0) != 0x0F0) {
 				const int16 sampleIdx = (actor->brickSound & 0x0F) + Samples::WalkFloorBegin;
-				_engine->_sound->playSample(sampleIdx, 1, actor->x, actor->y, actor->z, actorIdx);
+				_engine->_sound->playSample(sampleIdx, 1, actor->pos, actorIdx);
 			}
 			break;
 		case ActionType::ACTION_HERO_HITTING:
@@ -387,9 +387,9 @@ void Animations::processAnimActions(int32 actorIdx) {
 			if (action.animFrame == actor->animPosition) {
 				_engine->_movements->rotateActor(action.distanceX, action.distanceZ, actor->angle);
 
-				const int32 throwX = _engine->_renderer->destX + actor->x;
-				const int32 throwY = action.distanceY + actor->y;
-				const int32 throwZ = _engine->_renderer->destZ + actor->z;
+				const int32 throwX = _engine->_renderer->destX + actor->pos.x;
+				const int32 throwY = action.distanceY + actor->pos.y;
+				const int32 throwZ = _engine->_renderer->destZ + actor->pos.z;
 
 				_engine->_extra->addExtraThrow(actorIdx, throwX, throwY, throwZ, action.spriteIndex,
 				                               action.xAngle, action.yAngle + actor->angle, action.xRotPoint, action.extraAngle, action.strength);
@@ -397,13 +397,13 @@ void Animations::processAnimActions(int32 actorIdx) {
 			break;
 		case ActionType::ACTION_THROW_3D_ALPHA:
 			if (action.animFrame == actor->animPosition) {
-				const int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->y, 0, _engine->_scene->sceneHero->y, _engine->_movements->getDistance2D(actor->x, actor->z, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->z));
+				const int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->pos.y, 0, _engine->_scene->sceneHero->pos.y, _engine->_movements->getDistance2D(actor->pos.x, actor->pos.z, _engine->_scene->sceneHero->pos.x, _engine->_scene->sceneHero->pos.z));
 
 				_engine->_movements->rotateActor(action.distanceX, action.distanceZ, actor->angle);
 
-				const int32 throwX = _engine->_renderer->destX + actor->x;
-				const int32 throwY = action.distanceY + actor->y;
-				const int32 throwZ = _engine->_renderer->destZ + actor->z;
+				const int32 throwX = _engine->_renderer->destX + actor->pos.x;
+				const int32 throwY = action.distanceY + actor->pos.y;
+				const int32 throwZ = _engine->_renderer->destZ + actor->pos.z;
 
 				_engine->_extra->addExtraThrow(actorIdx, throwX, throwY, throwZ, action.spriteIndex,
 				                               action.xAngle + newAngle, action.yAngle + actor->angle, action.xRotPoint, action.extraAngle, action.strength);
@@ -412,9 +412,9 @@ void Animations::processAnimActions(int32 actorIdx) {
 		case ActionType::ACTION_THROW_3D_SEARCH:
 			if (action.animFrame == actor->animPosition) {
 				_engine->_movements->rotateActor(action.distanceX, action.distanceZ, actor->angle);
-				const int32 x = actor->x + _engine->_renderer->destX;
-				const int32 y = actor->y + action.distanceY;
-				const int32 z = actor->z + _engine->_renderer->destZ;
+				const int32 x = actor->pos.x + _engine->_renderer->destX;
+				const int32 y = actor->pos.y + action.distanceY;
+				const int32 z = actor->pos.z + _engine->_renderer->destZ;
 				_engine->_extra->addExtraAiming(actorIdx, x, y, z, action.spriteIndex,
 				                                action.targetActor, action.finalAngle, action.strength);
 			}
@@ -422,9 +422,9 @@ void Animations::processAnimActions(int32 actorIdx) {
 		case ActionType::ACTION_UNKNOWN_21:
 			if (_engine->_gameState->magicBallIdx == -1 && action.animFrame == actor->animPosition) {
 				_engine->_movements->rotateActor(action.distanceX, action.distanceZ, actor->angle);
-				const int32 x = actor->x + _engine->_renderer->destX;
-				const int32 y = actor->y + action.distanceY;
-				const int32 z = actor->z + _engine->_renderer->destZ;
+				const int32 x = actor->pos.x + _engine->_renderer->destX;
+				const int32 y = actor->pos.y + action.distanceY;
+				const int32 z = actor->pos.z + _engine->_renderer->destZ;
 				_engine->_extra->addExtraThrowMagicball(x, y, z, action.xAngle, actor->angle, action.yAngle, action.finalAngle);
 			}
 			break;
@@ -525,9 +525,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			actor->dynamicFlags.bIsHitting = 1;
 		}
 
-		_engine->_movements->processActorX = actor->x;
-		_engine->_movements->processActorY = actor->y;
-		_engine->_movements->processActorZ = actor->z;
+		_engine->_movements->processActorX = actor->pos.x;
+		_engine->_movements->processActorY = actor->pos.y;
+		_engine->_movements->processActorZ = actor->pos.z;
 
 		if (!actor->dynamicFlags.bIsFalling) {
 			if (actor->speed) {
@@ -542,12 +542,12 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 				_engine->_movements->rotateActor(xAxisRotation, 0, actor->animType);
 
-				_engine->_movements->processActorY = actor->y - _engine->_renderer->destZ;
+				_engine->_movements->processActorY = actor->pos.y - _engine->_renderer->destZ;
 
 				_engine->_movements->rotateActor(0, _engine->_renderer->destX, actor->angle);
 
-				_engine->_movements->processActorX = actor->x + _engine->_renderer->destX;
-				_engine->_movements->processActorZ = actor->z + _engine->_renderer->destZ;
+				_engine->_movements->processActorX = actor->pos.x + _engine->_renderer->destX;
+				_engine->_movements->processActorZ = actor->pos.z + _engine->_renderer->destZ;
 
 				_engine->_movements->setActorAngle(ANGLE_0, actor->speed, ANGLE_17, &actor->move);
 
@@ -639,9 +639,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			currentStepX = _engine->_renderer->destX;
 			currentStepZ = _engine->_renderer->destZ;
 
-			_engine->_movements->processActorX = actor->x + currentStepX - actor->lastX;
-			_engine->_movements->processActorY = actor->y + currentStepY - actor->lastY;
-			_engine->_movements->processActorZ = actor->z + currentStepZ - actor->lastZ;
+			_engine->_movements->processActorX = actor->pos.x + currentStepX - actor->lastX;
+			_engine->_movements->processActorY = actor->pos.y + currentStepY - actor->lastY;
+			_engine->_movements->processActorZ = actor->pos.z + currentStepZ - actor->lastZ;
 
 			actor->lastX = currentStepX;
 			actor->lastY = currentStepY;
@@ -699,9 +699,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		_engine->_movements->processActorY -= standOnActor->collisionY;
 		_engine->_movements->processActorZ -= standOnActor->collisionZ;
 
-		_engine->_movements->processActorX += standOnActor->x;
-		_engine->_movements->processActorY += standOnActor->y;
-		_engine->_movements->processActorZ += standOnActor->z;
+		_engine->_movements->processActorX += standOnActor->pos.x;
+		_engine->_movements->processActorY += standOnActor->pos.y;
+		_engine->_movements->processActorZ += standOnActor->pos.z;
 
 		if (!_engine->_collision->standingOnActor(actorIdx, actor->standOn)) {
 			actor->standOn = -1; // no longer standing on other actor
@@ -766,7 +766,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 			if (_engine->_renderer->destX >= 0 && _engine->_renderer->destZ >= 0 && _engine->_renderer->destX <= 0x7E00 && _engine->_renderer->destZ <= 0x7E00) {
 				if (_engine->_grid->getBrickShape(_engine->_renderer->destX, _engine->_movements->processActorY + BRICK_HEIGHT, _engine->_renderer->destZ) != ShapeType::kNone && _engine->cfgfile.WallCollision) { // avoid wall hit damage
-					_engine->_extra->addExtraSpecial(actor->x, actor->y + 1000, actor->z, ExtraSpecialType::kHitStars);
+					_engine->_extra->addExtraSpecial(actor->pos.x, actor->pos.y + 1000, actor->pos.z, ExtraSpecialType::kHitStars);
 					initAnim(AnimationTypes::kBigHit, kAnimationType_2, AnimationTypes::kStanding, currentlyProcessedActorIdx);
 
 					if (IS_HERO(currentlyProcessedActorIdx)) {
@@ -788,7 +788,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 					_engine->_movements->processActorY = (_engine->_collision->collisionY * BRICK_HEIGHT) + BRICK_HEIGHT;
 				} else {
 					if (IS_HERO(actorIdx) && _engine->_actor->heroBehaviour == HeroBehaviourType::kAthletic && actor->anim == AnimationTypes::kForward && _engine->cfgfile.WallCollision) { // avoid wall hit damage
-						_engine->_extra->addExtraSpecial(actor->x, actor->y + 1000, actor->z, ExtraSpecialType::kHitStars);
+						_engine->_extra->addExtraSpecial(actor->pos.x, actor->pos.y + 1000, actor->pos.z, ExtraSpecialType::kHitStars);
 						initAnim(AnimationTypes::kBigHit, kAnimationType_2, AnimationTypes::kStanding, currentlyProcessedActorIdx);
 						_engine->_movements->heroMoved = true;
 						actor->life--;
@@ -878,9 +878,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		_engine->_movements->processActorZ = 0x7E00;
 	}
 
-	actor->x = _engine->_movements->processActorX;
-	actor->y = _engine->_movements->processActorY;
-	actor->z = _engine->_movements->processActorZ;
+	actor->pos.x = _engine->_movements->processActorX;
+	actor->pos.y = _engine->_movements->processActorY;
+	actor->pos.z = _engine->_movements->processActorZ;
 }
 
 } // namespace TwinE
diff --git a/engines/twine/scene/collision.cpp b/engines/twine/scene/collision.cpp
index 702a2dadfc..04f631c0a1 100644
--- a/engines/twine/scene/collision.cpp
+++ b/engines/twine/scene/collision.cpp
@@ -55,14 +55,14 @@ bool Collision::standingOnActor(int32 actorIdx1, int32 actorIdx2) {
 	const int32 z1Right = _engine->_movements->processActorZ + actor1->boudingBox.z.topRight;
 
 	// Actor 2
-	const int32 x2Left = actor2->x + actor2->boudingBox.x.bottomLeft;
-	const int32 x2Right = actor2->x + actor2->boudingBox.x.topRight;
+	const int32 x2Left = actor2->pos.x + actor2->boudingBox.x.bottomLeft;
+	const int32 x2Right = actor2->pos.x + actor2->boudingBox.x.topRight;
 
-	const int32 y2Left = actor2->y + actor2->boudingBox.y.bottomLeft;
-	const int32 y2Right = actor2->y + actor2->boudingBox.y.topRight;
+	const int32 y2Left = actor2->pos.y + actor2->boudingBox.y.bottomLeft;
+	const int32 y2Right = actor2->pos.y + actor2->boudingBox.y.topRight;
 
-	const int32 z2Left = actor2->z + actor2->boudingBox.z.bottomLeft;
-	const int32 z2Right = actor2->z + actor2->boudingBox.z.topRight;
+	const int32 z2Left = actor2->pos.z + actor2->boudingBox.z.bottomLeft;
+	const int32 z2Right = actor2->pos.z + actor2->boudingBox.z.topRight;
 
 	if (x1Left >= x2Right) {
 		return false; // not standing
@@ -222,14 +222,14 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 
 		// aviod current processed actor
 		if (a != actorIdx && actorTest->entity != -1 && !actor->staticFlags.bComputeLowCollision && actorTest->standOn != actorIdx) {
-			const int32 xLeftTest = actorTest->x + actorTest->boudingBox.x.bottomLeft;
-			const int32 xRightTest = actorTest->x + actorTest->boudingBox.x.topRight;
+			const int32 xLeftTest = actorTest->pos.x + actorTest->boudingBox.x.bottomLeft;
+			const int32 xRightTest = actorTest->pos.x + actorTest->boudingBox.x.topRight;
 
-			const int32 yLeftTest = actorTest->y + actorTest->boudingBox.y.bottomLeft;
-			const int32 yRightTest = actorTest->y + actorTest->boudingBox.y.topRight;
+			const int32 yLeftTest = actorTest->pos.y + actorTest->boudingBox.y.bottomLeft;
+			const int32 yRightTest = actorTest->pos.y + actorTest->boudingBox.y.topRight;
 
-			const int32 zLeftTest = actorTest->z + actorTest->boudingBox.z.bottomLeft;
-			const int32 zRightTest = actorTest->z + actorTest->boudingBox.z.topRight;
+			const int32 zLeftTest = actorTest->pos.z + actorTest->boudingBox.z.bottomLeft;
+			const int32 zRightTest = actorTest->pos.z + actorTest->boudingBox.z.topRight;
 
 			if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
 				actor->collision = a; // mark as collision with actor a
@@ -243,7 +243,7 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 							_engine->_movements->processActorY = yRightTest - actor->boudingBox.y.bottomLeft + 1;
 							actor->standOn = a;
 						} else {
-							int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->x, actorTest->z);
+							int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->pos.x, actorTest->pos.z);
 
 							if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
 								actorTest->lastY = 0;
@@ -295,7 +295,7 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 						_engine->_actor->hitActor(actorIdx, a, 1, -1);
 					}
 
-					int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->x, actorTest->z);
+					int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->pos.x, actorTest->pos.z);
 
 					if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
 						actorTest->lastY = 0;
@@ -362,14 +362,14 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 
 			// aviod current processed actor
 			if (a != actorIdx && actorTest->entity != -1 && !actorTest->staticFlags.bIsHidden && actorTest->standOn != actorIdx) {
-				const int32 xLeftTest = actorTest->x + actorTest->boudingBox.x.bottomLeft;
-				const int32 xRightTest = actorTest->x + actorTest->boudingBox.x.topRight;
+				const int32 xLeftTest = actorTest->pos.x + actorTest->boudingBox.x.bottomLeft;
+				const int32 xRightTest = actorTest->pos.x + actorTest->boudingBox.x.topRight;
 
-				const int32 yLeftTest = actorTest->y + actorTest->boudingBox.y.bottomLeft;
-				const int32 yRightTest = actorTest->y + actorTest->boudingBox.y.topRight;
+				const int32 yLeftTest = actorTest->pos.y + actorTest->boudingBox.y.bottomLeft;
+				const int32 yRightTest = actorTest->pos.y + actorTest->boudingBox.y.topRight;
 
-				const int32 zLeftTest = actorTest->z + actorTest->boudingBox.z.bottomLeft;
-				const int32 zRightTest = actorTest->z + actorTest->boudingBox.z.topRight;
+				const int32 zLeftTest = actorTest->pos.z + actorTest->boudingBox.z.bottomLeft;
+				const int32 zRightTest = actorTest->pos.z + actorTest->boudingBox.z.topRight;
 
 				if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
 					_engine->_actor->hitActor(actorIdx, a, actor->strengthOfHit, actor->angle + ANGLE_90);
@@ -451,7 +451,7 @@ void Collision::stopFalling() { // ReceptionObj()
 		const int32 fall = _engine->_scene->heroYBeforeFall - _engine->_movements->processActorY;
 
 		if (fall >= BRICK_HEIGHT * 8) {
-			_engine->_extra->addExtraSpecial(_engine->_actor->processActorPtr->x, _engine->_actor->processActorPtr->y + 1000, _engine->_actor->processActorPtr->z, ExtraSpecialType::kHitStars);
+			_engine->_extra->addExtraSpecial(_engine->_actor->processActorPtr->pos.x, _engine->_actor->processActorPtr->pos.y + 1000, _engine->_actor->processActorPtr->pos.z, ExtraSpecialType::kHitStars);
 			_engine->_actor->processActorPtr->life--;
 			_engine->_animations->initAnim(AnimationTypes::kLandingHit, kAnimationType_2, AnimationTypes::kStanding, _engine->_animations->currentlyProcessedActorIdx);
 		} else if (fall > 10) {
@@ -481,12 +481,12 @@ int32 Collision::checkExtraCollisionWithActors(ExtraListStruct *extra, int32 act
 		const ActorStruct *actorTest = _engine->_scene->getActor(a);
 
 		if (a != actorIdx && actorTest->entity != -1) {
-			const int32 xLeftTest = actorTest->x + actorTest->boudingBox.x.bottomLeft;
-			const int32 xRightTest = actorTest->x + actorTest->boudingBox.x.topRight;
-			const int32 yLeftTest = actorTest->y + actorTest->boudingBox.y.bottomLeft;
-			const int32 yRightTest = actorTest->y + actorTest->boudingBox.y.topRight;
-			const int32 zLeftTest = actorTest->z + actorTest->boudingBox.z.bottomLeft;
-			const int32 zRightTest = actorTest->z + actorTest->boudingBox.z.topRight;
+			const int32 xLeftTest = actorTest->pos.x + actorTest->boudingBox.x.bottomLeft;
+			const int32 xRightTest = actorTest->pos.x + actorTest->boudingBox.x.topRight;
+			const int32 yLeftTest = actorTest->pos.y + actorTest->boudingBox.y.bottomLeft;
+			const int32 yRightTest = actorTest->pos.y + actorTest->boudingBox.y.topRight;
+			const int32 zLeftTest = actorTest->pos.z + actorTest->boudingBox.z.bottomLeft;
+			const int32 zRightTest = actorTest->pos.z + actorTest->boudingBox.z.topRight;
 
 			if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
 				if (extra->strengthOfHit != 0) {
diff --git a/engines/twine/scene/extra.cpp b/engines/twine/scene/extra.cpp
index 134ddbfb8f..9304eac910 100644
--- a/engines/twine/scene/extra.cpp
+++ b/engines/twine/scene/extra.cpp
@@ -125,7 +125,7 @@ int32 Extra::addExtra(int32 actorIdx, int32 x, int32 y, int32 z, int32 spriteIdx
 
 		_engine->_movements->setActorAngle(ANGLE_0, maxSpeed, ANGLE_17, &extra->trackActorMove);
 		const ActorStruct *actor = _engine->_scene->getActor(targetActor);
-		extra->angle = _engine->_movements->getAngleAndSetTargetActorDistance(x, z, actor->x, actor->z);
+		extra->angle = _engine->_movements->getAngleAndSetTargetActorDistance(x, z, actor->pos.x, actor->pos.z);
 		return i;
 	}
 	return -1;
@@ -326,7 +326,7 @@ int32 Extra::addExtraAiming(int32 actorIdx, int32 x, int32 y, int32 z, int32 spr
 		extra->strengthOfHit = strengthOfHit;
 		_engine->_movements->setActorAngle(ANGLE_0, finalAngle, ANGLE_17, &extra->trackActorMove);
 		const ActorStruct *actor = _engine->_scene->getActor(targetActorIdx);
-		extra->angle = _engine->_movements->getAngleAndSetTargetActorDistance(x, z, actor->x, actor->z);
+		extra->angle = _engine->_movements->getAngleAndSetTargetActorDistance(x, z, actor->pos.x, actor->pos.z);
 
 		return i;
 	}
@@ -635,9 +635,9 @@ void Extra::processExtras() {
 			int32 actorIdx = extra->payload.actorIdx;
 
 			const ActorStruct *actor = _engine->_scene->getActor(actorIdxAttacked);
-			currentExtraX = actor->x;
-			currentExtraY = actor->y + 1000;
-			currentExtraZ = actor->z;
+			currentExtraX = actor->pos.x;
+			currentExtraY = actor->pos.y + 1000;
+			currentExtraZ = actor->pos.z;
 
 			const int32 tmpAngle = _engine->_movements->getAngleAndSetTargetActorDistance(extra->x, extra->z, currentExtraX, currentExtraZ);
 			const int32 angle = ClampAngle(tmpAngle - extra->angle);
@@ -689,7 +689,7 @@ void Extra::processExtras() {
 			const int32 angle = ClampAngle(tmpAngle - extra->angle);
 
 			if (angle > ANGLE_140 && angle < ANGLE_210) {
-				_engine->_sound->playSample(Samples::ItemFound, 1, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->y, _engine->_scene->sceneHero->z, OWN_ACTOR_SCENE_INDEX);
+				_engine->_sound->playSample(Samples::ItemFound, 1, _engine->_scene->sceneHero->pos, OWN_ACTOR_SCENE_INDEX);
 
 				if (extraKey->info1 > 1) {
 					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->camera.x, extraKey->y - _engine->_grid->camera.y, extraKey->z - _engine->_grid->camera.z);
@@ -722,7 +722,7 @@ void Extra::processExtras() {
 			_engine->_movements->setActorAngle(ANGLE_0, extra->destZ, ANGLE_17, &extra->trackActorMove);
 
 			if (extraIdx == _engine->_collision->checkExtraCollisionWithExtra(extra, _engine->_gameState->magicBallIdx)) {
-				_engine->_sound->playSample(Samples::ItemFound, 1, _engine->_scene->sceneHero->x, _engine->_scene->sceneHero->y, _engine->_scene->sceneHero->z, OWN_ACTOR_SCENE_INDEX);
+				_engine->_sound->playSample(Samples::ItemFound, 1, _engine->_scene->sceneHero->pos, OWN_ACTOR_SCENE_INDEX);
 
 				if (extraKey->info1 > 1) {
 					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->camera.x, extraKey->y - _engine->_grid->camera.y, extraKey->z - _engine->_grid->camera.z);
diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index 959aed9bf3..23f2a60f03 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -322,18 +322,18 @@ void GameState::processFoundItem(int32 item) {
 	const int32 itemCameraZ = _engine->_grid->newCamera.z * BRICK_SIZE;
 
 	uint8 *bodyPtr = _engine->_actor->bodyTable[_engine->_scene->sceneHero->entity];
-	const int32 bodyX = _engine->_scene->sceneHero->x - itemCameraX;
-	const int32 bodyY = _engine->_scene->sceneHero->y - itemCameraY;
-	const int32 bodyZ = _engine->_scene->sceneHero->z - itemCameraZ;
+	const int32 bodyX = _engine->_scene->sceneHero->pos.x - itemCameraX;
+	const int32 bodyY = _engine->_scene->sceneHero->pos.y - itemCameraY;
+	const int32 bodyZ = _engine->_scene->sceneHero->pos.z - itemCameraZ;
 	_engine->_renderer->renderIsoModel(bodyX, bodyY, bodyZ, ANGLE_0, ANGLE_45, ANGLE_0, bodyPtr);
 	_engine->_interface->setClip(_engine->_redraw->renderRect);
 
-	const int32 itemX = (_engine->_scene->sceneHero->x + BRICK_HEIGHT) / BRICK_SIZE;
-	int32 itemY = _engine->_scene->sceneHero->y / BRICK_HEIGHT;
+	const int32 itemX = (_engine->_scene->sceneHero->pos.x + BRICK_HEIGHT) / BRICK_SIZE;
+	int32 itemY = _engine->_scene->sceneHero->pos.y / BRICK_HEIGHT;
 	if (_engine->_scene->sceneHero->brickShape() != ShapeType::kNone) {
 		itemY++;
 	}
-	const int32 itemZ = (_engine->_scene->sceneHero->z + BRICK_HEIGHT) / BRICK_SIZE;
+	const int32 itemZ = (_engine->_scene->sceneHero->pos.z + BRICK_HEIGHT) / BRICK_SIZE;
 
 	_engine->_grid->drawOverModelActor(itemX, itemY, itemZ);
 	_engine->flip();
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index fbe53197ee..fa7e2a1b2c 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -857,9 +857,9 @@ int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 }
 
 void Grid::centerOnActor(const ActorStruct* actor) {
-	newCamera.x = (actor->x + BRICK_HEIGHT) / BRICK_SIZE;
-	newCamera.y = (actor->y + BRICK_HEIGHT) / BRICK_HEIGHT;
-	newCamera.z = (actor->z + BRICK_HEIGHT) / BRICK_SIZE;
+	newCamera.x = (actor->pos.x + BRICK_HEIGHT) / BRICK_SIZE;
+	newCamera.y = (actor->pos.y + BRICK_HEIGHT) / BRICK_HEIGHT;
+	newCamera.z = (actor->pos.z + BRICK_HEIGHT) / BRICK_SIZE;
 	_engine->_redraw->reqBgRedraw = true;
 }
 
@@ -872,13 +872,13 @@ void Grid::centerScreenOnActor() {
 	}
 
 	ActorStruct *actor = _engine->_scene->getActor(_engine->_scene->currentlyFollowedActor);
-	_engine->_renderer->projectPositionOnScreen(actor->x - (newCamera.x * BRICK_SIZE),
-	                                   actor->y - (newCamera.y * BRICK_HEIGHT),
-	                                   actor->z - (newCamera.z * BRICK_SIZE));
+	_engine->_renderer->projectPositionOnScreen(actor->pos.x - (newCamera.x * BRICK_SIZE),
+	                                   actor->pos.y - (newCamera.y * BRICK_HEIGHT),
+	                                   actor->pos.z - (newCamera.z * BRICK_SIZE));
 	if (_engine->_renderer->projPosX < 80 || _engine->_renderer->projPosX >= _engine->width() - 60 || _engine->_renderer->projPosY < 80 || _engine->_renderer->projPosY >= _engine->height() - 50) {
-		newCamera.x = ((actor->x + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->x + BRICK_HEIGHT) / BRICK_SIZE) - newCamera.x) / 2;
-		newCamera.y = actor->y / BRICK_HEIGHT;
-		newCamera.z = ((actor->z + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->z + BRICK_HEIGHT) / BRICK_SIZE) - newCamera.z) / 2;
+		newCamera.x = ((actor->pos.x + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->pos.x + BRICK_HEIGHT) / BRICK_SIZE) - newCamera.x) / 2;
+		newCamera.y = actor->pos.y / BRICK_HEIGHT;
+		newCamera.z = ((actor->pos.z + BRICK_HEIGHT) / BRICK_SIZE) + (((actor->pos.z + BRICK_HEIGHT) / BRICK_SIZE) - newCamera.z) / 2;
 
 		if (newCamera.x >= GRID_SIZE_X) {
 			newCamera.x = GRID_SIZE_X - 1;
diff --git a/engines/twine/scene/movements.cpp b/engines/twine/scene/movements.cpp
index 54c7c3f2a2..50707df4ed 100644
--- a/engines/twine/scene/movements.cpp
+++ b/engines/twine/scene/movements.cpp
@@ -146,14 +146,18 @@ void Movements::rotateActor(int32 x, int32 z, int32 angle) {
 	_engine->_renderer->destZ = (int32)(-x * sin(radians) + z * cos(radians));
 }
 
-int32 Movements::getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2) {
+int32 Movements::getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2) const {
 	return (int32)sqrt((float)((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1)));
 }
 
-int32 Movements::getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2, int32 z2) {
+int32 Movements::getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2, int32 z2) const {
 	return (int32)sqrt((float)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1)));
 }
 
+int32 Movements::getDistance3D(const Vec3 &v1, const Vec3 &v2) const {
+	return (int32)sqrt((float)((v2.x - v1.x) * (v2.x - v1.x) + (v2.y - v1.y) * (v2.y - v1.y) + (v2.z - v1.z) * (v2.z - v1.z)));
+}
+
 void Movements::moveActor(int32 angleFrom, int32 angleTo, int32 speed, ActorMoveStruct *movePtr) { // ManualRealAngle
 	const int16 from = ClampAngle(angleFrom);
 	const int16 to = ClampAngle(angleTo);
@@ -385,7 +389,7 @@ void Movements::processManualAction(int actorIdx) {
 void Movements::processFollowAction(int actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	const ActorStruct *followedActor = _engine->_scene->getActor(actor->followedActor);
-	int32 newAngle = getAngleAndSetTargetActorDistance(actor->x, actor->z, followedActor->x, followedActor->z);
+	int32 newAngle = getAngleAndSetTargetActorDistance(actor->pos.x, actor->pos.z, followedActor->pos.x, followedActor->pos.z);
 	if (actor->staticFlags.bIsSpriteActor) {
 		actor->angle = newAngle;
 	} else {
@@ -424,8 +428,8 @@ void Movements::processTrackAction(int actorIdx) {
 void Movements::processSameXZAction(int actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	const ActorStruct *followedActor = _engine->_scene->getActor(actor->followedActor);
-	actor->x = followedActor->x;
-	actor->z = followedActor->z;
+	actor->pos.x = followedActor->pos.x;
+	actor->pos.z = followedActor->pos.z;
 }
 
 void Movements::processActorMovements(int32 actorIdx) {
diff --git a/engines/twine/scene/movements.h b/engines/twine/scene/movements.h
index 138fcd144c..fca3b0d7f0 100644
--- a/engines/twine/scene/movements.h
+++ b/engines/twine/scene/movements.h
@@ -207,7 +207,7 @@ public:
 	 * @param x2 Actor 2 X coordinate
 	 * @param z2 Actor 2 Z coordinate
 	 */
-	int32 getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2);
+	int32 getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2) const;
 
 	/**
 	 * Get distance value in 3D
@@ -218,8 +218,8 @@ public:
 	 * @param y2 Actor 2 Y coordinate
 	 * @param z2 Actor 2 Z coordinate
 	 */
-	int32 getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2, int32 z2);
-
+	int32 getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2, int32 z2) const;
+	int32 getDistance3D(const Vec3 &v1, const Vec3 &v2) const;
 	/**
 	 * Move actor around the scene
 	 * @param angleFrom Current actor angle
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index 6d64eaab37..2a1479b0a1 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -197,12 +197,12 @@ bool Scene::loadSceneLBA2() {
 		act->body = (BodyType)stream.readSint16LE();
 		act->anim = (AnimationTypes)stream.readByte();
 		act->sprite = stream.readUint16LE();
-		act->x = stream.readUint16LE();
-		act->collisionX = act->x;
-		act->y = stream.readUint16LE();
-		act->collisionY = act->y;
-		act->z = stream.readUint16LE();
-		act->collisionZ = act->z;
+		act->pos.x = stream.readUint16LE();
+		act->collisionX = act->pos.x;
+		act->pos.y = stream.readUint16LE();
+		act->collisionY = act->pos.y;
+		act->pos.z = stream.readUint16LE();
+		act->collisionZ = act->pos.z;
 		act->strengthOfHit = stream.readByte();
 		setBonusParameterFlags(act, stream.readUint16LE());
 		act->angle = stream.readUint16LE();
@@ -330,12 +330,12 @@ bool Scene::loadSceneLBA1() {
 		act->body = (BodyType)stream.readByte();
 		act->anim = (AnimationTypes)stream.readByte();
 		act->sprite = stream.readUint16LE();
-		act->x = stream.readUint16LE();
-		act->collisionX = act->x;
-		act->y = stream.readUint16LE();
-		act->collisionY = act->y;
-		act->z = stream.readUint16LE();
-		act->collisionZ = act->z;
+		act->pos.x = stream.readUint16LE();
+		act->collisionX = act->pos.x;
+		act->pos.y = stream.readUint16LE();
+		act->collisionY = act->pos.y;
+		act->pos.z = stream.readUint16LE();
+		act->collisionZ = act->pos.z;
 		act->strengthOfHit = stream.readByte();
 		setBonusParameterFlags(act, stream.readUint16LE());
 		act->angle = stream.readUint16LE();
@@ -510,9 +510,9 @@ void Scene::changeScene() {
 		newHeroZ = _sceneHeroZ;
 	}
 
-	sceneHero->x = newHeroX;
-	sceneHero->y = heroYBeforeFall = newHeroY;
-	sceneHero->z = newHeroZ;
+	sceneHero->pos.x = newHeroX;
+	sceneHero->pos.y = heroYBeforeFall = newHeroY;
+	sceneHero->pos.z = newHeroZ;
 
 	_engine->_renderer->setLightVector(alphaLight, betaLight, ANGLE_0);
 
@@ -631,7 +631,7 @@ void Scene::processZoneExtraBonus(ZoneStruct *zone) {
 	}
 
 	const int16 amount = zone->infoData.Bonus.amount;
-	const int32 angle = _engine->_movements->getAngleAndSetTargetActorDistance(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, sceneHero->x, sceneHero->z);
+	const int32 angle = _engine->_movements->getAngleAndSetTargetActorDistance(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, sceneHero->pos.x, sceneHero->pos.z);
 	const int32 index = _engine->_extra->addExtraBonus(ABS(zone->topRight.x + zone->bottomLeft.x) / 2, zone->topRight.y, ABS(zone->topRight.z + zone->bottomLeft.z) / 2, ANGLE_63, angle, bonusSprite, amount);
 
 	if (index != -1) {
@@ -643,9 +643,9 @@ void Scene::processZoneExtraBonus(ZoneStruct *zone) {
 void Scene::processActorZones(int32 actorIdx) {
 	ActorStruct *actor = &_sceneActors[actorIdx];
 
-	int32 currentX = actor->x;
-	int32 currentY = actor->y;
-	int32 currentZ = actor->z;
+	int32 currentX = actor->pos.x;
+	int32 currentY = actor->pos.y;
+	int32 currentZ = actor->pos.z;
 
 	actor->zone = -1;
 	int32 tmpCellingGrid = 0;
@@ -665,9 +665,9 @@ void Scene::processActorZones(int32 actorIdx) {
 			case ZoneType::kCube:
 				if (IS_HERO(actorIdx) && actor->life > 0) {
 					needChangeScene = zone->infoData.ChangeScene.newSceneIdx;
-					_zoneHeroX = actor->x - zone->bottomLeft.x + zone->infoData.ChangeScene.x;
-					_zoneHeroY = actor->y - zone->bottomLeft.y + zone->infoData.ChangeScene.y;
-					_zoneHeroZ = actor->z - zone->bottomLeft.z + zone->infoData.ChangeScene.z;
+					_zoneHeroX = actor->pos.x - zone->bottomLeft.x + zone->infoData.ChangeScene.x;
+					_zoneHeroY = actor->pos.y - zone->bottomLeft.y + zone->infoData.ChangeScene.y;
+					_zoneHeroZ = actor->pos.z - zone->bottomLeft.z + zone->infoData.ChangeScene.z;
 					heroPositionType = ScenePositionType::kZone;
 				}
 				break;
@@ -723,9 +723,9 @@ void Scene::processActorZones(int32 actorIdx) {
 					_engine->_renderer->destZ += _engine->_movements->processActorZ;
 
 					if (_engine->_renderer->destX >= 0 && _engine->_renderer->destZ >= 0 && _engine->_renderer->destX <= 0x7E00 && _engine->_renderer->destZ <= 0x7E00) {
-						if (_engine->_grid->getBrickShape(_engine->_renderer->destX, actor->y + ANGLE_90, _engine->_renderer->destZ) != ShapeType::kNone) {
+						if (_engine->_grid->getBrickShape(_engine->_renderer->destX, actor->pos.y + ANGLE_90, _engine->_renderer->destZ) != ShapeType::kNone) {
 							currentActorInZone = true;
-							if (actor->y >= ABS(zone->bottomLeft.y + zone->topRight.y) / 2) {
+							if (actor->pos.y >= ABS(zone->bottomLeft.y + zone->topRight.y) / 2) {
 								_engine->_animations->initAnim(AnimationTypes::kTopLadder, kAnimationType_2, AnimationTypes::kStanding, actorIdx); // reached end of ladder
 							} else {
 								_engine->_animations->initAnim(AnimationTypes::kClimbLadder, kAnimationTypeLoop, AnimationTypes::kAnimInvalid, actorIdx); // go up in ladder
diff --git a/engines/twine/script/script_life_v1.cpp b/engines/twine/script/script_life_v1.cpp
index b18928d0cb..db6d53cbf0 100644
--- a/engines/twine/script/script_life_v1.cpp
+++ b/engines/twine/script/script_life_v1.cpp
@@ -157,11 +157,11 @@ static int32 processLifeConditions(TwinEEngine *engine, LifeScriptContext &ctx)
 		conditionValueSize = 2;
 		ActorStruct *otherActor = engine->_scene->getActor(actorIdx);
 		if (!otherActor->dynamicFlags.bIsDead) {
-			if (ABS(ctx.actor->y - otherActor->y) >= 1500) {
+			if (ABS(ctx.actor->pos.y - otherActor->pos.y) >= 1500) {
 				engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
 			} else {
 				// Returns int32, so we check for integer overflow
-				int32 distance = engine->_movements->getDistance2D(ctx.actor->x, ctx.actor->z, otherActor->x, otherActor->z);
+				int32 distance = engine->_movements->getDistance2D(ctx.actor->pos.x, ctx.actor->pos.z, otherActor->pos.x, otherActor->pos.z);
 				if (ABS(distance) > MAX_TARGET_ACTOR_DISTANCE) {
 					engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
 				} else {
@@ -218,8 +218,8 @@ static int32 processLifeConditions(TwinEEngine *engine, LifeScriptContext &ctx)
 		conditionValueSize = 2;
 
 		if (!targetActor->dynamicFlags.bIsDead) {
-			if (ABS(targetActor->y - ctx.actor->y) < 1500) {
-				newAngle = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->x, ctx.actor->z, targetActor->x, targetActor->z);
+			if (ABS(targetActor->pos.y - ctx.actor->pos.y) < 1500) {
+				newAngle = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->pos.x, ctx.actor->pos.z, targetActor->pos.x, targetActor->pos.z);
 				if (ABS(engine->_movements->targetActorDistance) > MAX_TARGET_ACTOR_DISTANCE) {
 					engine->_movements->targetActorDistance = MAX_TARGET_ACTOR_DISTANCE;
 				}
@@ -306,7 +306,7 @@ static int32 processLifeConditions(TwinEEngine *engine, LifeScriptContext &ctx)
 
 		if (!targetActor->dynamicFlags.bIsDead) {
 			// Returns int32, so we check for integer overflow
-			int32 distance = engine->_movements->getDistance3D(ctx.actor->x, ctx.actor->y, ctx.actor->z, targetActor->x, targetActor->y, targetActor->z);
+			int32 distance = engine->_movements->getDistance3D(ctx.actor->pos, targetActor->pos);
 			if (ABS(distance) > MAX_TARGET_ACTOR_DISTANCE) {
 				engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
 			} else {
@@ -952,7 +952,7 @@ static int32 lSET_DOOR_LEFT(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_270;
-	ctx.actor->x = ctx.actor->lastX - distance;
+	ctx.actor->pos.x = ctx.actor->lastX - distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -967,7 +967,7 @@ static int32 lSET_DOOR_RIGHT(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_90;
-	ctx.actor->x = ctx.actor->lastX + distance;
+	ctx.actor->pos.x = ctx.actor->lastX + distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -982,7 +982,7 @@ static int32 lSET_DOOR_UP(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_180;
-	ctx.actor->z = ctx.actor->lastZ - distance;
+	ctx.actor->pos.z = ctx.actor->lastZ - distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -997,7 +997,7 @@ static int32 lSET_DOOR_DOWN(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_0;
-	ctx.actor->z = ctx.actor->lastZ + distance;
+	ctx.actor->pos.z = ctx.actor->lastZ + distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -1125,9 +1125,9 @@ static int32 lPOS_POINT(TwinEEngine *engine, LifeScriptContext &ctx) {
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
 
-	ctx.actor->x = sp.x;
-	ctx.actor->y = sp.y;
-	ctx.actor->z = sp.z;
+	ctx.actor->pos.x = sp.x;
+	ctx.actor->pos.y = sp.y;
+	ctx.actor->pos.z = sp.z;
 
 	return 0;
 }
@@ -1527,7 +1527,7 @@ static int32 lEXPLODE_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 otherActorIdx = ctx.stream.readByte();
 	ActorStruct *otherActor = engine->_scene->getActor(otherActorIdx);
 
-	engine->_extra->addExtraExplode(otherActor->x, otherActor->y, otherActor->z); // RECHECK this
+	engine->_extra->addExtraExplode(otherActor->pos.x, otherActor->pos.y, otherActor->pos.z); // RECHECK this
 
 	return 0;
 }
diff --git a/engines/twine/script/script_move_v1.cpp b/engines/twine/script/script_move_v1.cpp
index a0003c917e..b5e9de589f 100644
--- a/engines/twine/script/script_move_v1.cpp
+++ b/engines/twine/script/script_move_v1.cpp
@@ -121,7 +121,7 @@ static int32 mGOTO_POINT(TwinEEngine *engine, MoveScriptContext &ctx) {
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
 
-	const int32 newAngle = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->x, ctx.actor->z, sp.x, sp.z);
+	const int32 newAngle = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->pos.x, ctx.actor->pos.z, sp.x, sp.z);
 
 	if (ctx.actor->staticFlags.bIsSpriteActor) {
 		ctx.actor->angle = newAngle;
@@ -197,9 +197,9 @@ static int32 mPOS_POINT(TwinEEngine *engine, MoveScriptContext &ctx) {
 		ctx.actor->speed = 0;
 	}
 
-	ctx.actor->x = sp.x;
-	ctx.actor->y = sp.y;
-	ctx.actor->z = sp.z;
+	ctx.actor->pos.x = sp.x;
+	ctx.actor->pos.y = sp.y;
+	ctx.actor->pos.z = sp.z;
 
 	return 0;
 }
@@ -253,7 +253,7 @@ static int32 mGOTO_SYM_POINT(TwinEEngine *engine, MoveScriptContext &ctx) {
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
 
-	const int32 newAngle = ANGLE_180 + engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->x, ctx.actor->z, sp.x, sp.z);
+	const int32 newAngle = ANGLE_180 + engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->pos.x, ctx.actor->pos.z, sp.x, sp.z);
 
 	if (ctx.actor->staticFlags.bIsSpriteActor) {
 		ctx.actor->angle = newAngle;
@@ -305,7 +305,7 @@ static int32 mWAIT_NUM_ANIM(TwinEEngine *engine, MoveScriptContext &ctx) {
  */
 static int32 mSAMPLE(TwinEEngine *engine, MoveScriptContext &ctx) {
 	int32 sampleIdx = ctx.stream.readSint16LE();
-	engine->_sound->playSample(sampleIdx, 1, ctx.actor->x, ctx.actor->y, ctx.actor->z, ctx.actorIdx);
+	engine->_sound->playSample(sampleIdx, 1, ctx.actor->pos, ctx.actorIdx);
 	return 0;
 }
 
@@ -326,17 +326,17 @@ static int32 mGOTO_POINT_3D(TwinEEngine *engine, MoveScriptContext &ctx) {
 	engine->_renderer->destY = sp.y;
 	engine->_renderer->destZ = sp.z;
 
-	ctx.actor->angle = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->x, ctx.actor->z, sp.x, sp.z);
+	ctx.actor->angle = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->pos.x, ctx.actor->pos.z, sp.x, sp.z);
 	// TODO: this adds an angle to the animType value
-	ctx.actor->animType = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->y, 0, sp.y, engine->_movements->targetActorDistance);
+	ctx.actor->animType = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->pos.y, 0, sp.y, engine->_movements->targetActorDistance);
 
 	if (engine->_movements->targetActorDistance > 100) {
 		ctx.undo(1);
 		return 1;
 	}
-	ctx.actor->x = sp.x;
-	ctx.actor->y = sp.y;
-	ctx.actor->z = sp.z;
+	ctx.actor->pos.x = sp.x;
+	ctx.actor->pos.y = sp.y;
+	ctx.actor->pos.z = sp.z;
 
 	return 0;
 }
@@ -539,7 +539,7 @@ static int32 mWAIT_DOOR(TwinEEngine *engine, MoveScriptContext &ctx) {
  */
 static int32 mSAMPLE_RND(TwinEEngine *engine, MoveScriptContext &ctx) {
 	int32 sampleIdx = ctx.stream.readSint16LE();
-	engine->_sound->playSample(sampleIdx, 1, ctx.actor->x, ctx.actor->y, ctx.actor->z, ctx.actorIdx);
+	engine->_sound->playSample(sampleIdx, 1, ctx.actor->pos, ctx.actorIdx);
 	return 0;
 }
 
@@ -550,7 +550,7 @@ static int32 mSAMPLE_RND(TwinEEngine *engine, MoveScriptContext &ctx) {
 static int32 mSAMPLE_ALWAYS(TwinEEngine *engine, MoveScriptContext &ctx) {
 	int32 sampleIdx = ctx.stream.readSint16LE();
 	if (!engine->_sound->isSamplePlaying(sampleIdx)) { // if its not playing
-		engine->_sound->playSample(sampleIdx, -1, ctx.actor->x, ctx.actor->y, ctx.actor->z, ctx.actorIdx);
+		engine->_sound->playSample(sampleIdx, -1, ctx.actor->pos, ctx.actorIdx);
 	}
 	return 0;
 }
@@ -605,7 +605,7 @@ static int32 mREPEAT_SAMPLE(TwinEEngine *engine, MoveScriptContext &ctx) {
  */
 static int32 mSIMPLE_SAMPLE(TwinEEngine *engine, MoveScriptContext &ctx) {
 	int32 sampleIdx = ctx.stream.readSint16LE();
-	engine->_sound->playSample(sampleIdx, ctx.numRepeatSample, ctx.actor->x, ctx.actor->y, ctx.actor->z, ctx.actorIdx);
+	engine->_sound->playSample(sampleIdx, ctx.numRepeatSample, ctx.actor->pos, ctx.actorIdx);
 	ctx.numRepeatSample = 1;
 	return 0;
 }
@@ -621,7 +621,7 @@ static int32 mFACE_HERO(TwinEEngine *engine, MoveScriptContext &ctx) {
 	}
 	engine->_scene->currentScriptValue = angle;
 	if (engine->_scene->currentScriptValue == -1 && ctx.actor->move.numOfStep == 0) {
-		engine->_scene->currentScriptValue = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->x, ctx.actor->z, engine->_scene->sceneHero->x, engine->_scene->sceneHero->z);
+		engine->_scene->currentScriptValue = engine->_movements->getAngleAndSetTargetActorDistance(ctx.actor->pos.x, ctx.actor->pos.z, engine->_scene->sceneHero->pos.x, engine->_scene->sceneHero->pos.z);
 		engine->_movements->moveActor(ctx.actor->angle, engine->_scene->currentScriptValue, ctx.actor->speed, &ctx.actor->move);
 		ctx.stream.rewind(2);
 		ctx.stream.writeSint16LE(engine->_scene->currentScriptValue);
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index b1e16b1096..564c1880d9 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -550,7 +550,7 @@ void TwinEEngine::unfreezeTime() {
 void TwinEEngine::processActorSamplePosition(int32 actorIdx) {
 	const ActorStruct *actor = _scene->getActor(actorIdx);
 	const int32 channelIdx = _sound->getActorChannel(actorIdx);
-	_sound->setSamplePosition(channelIdx, actor->x, actor->y, actor->z);
+	_sound->setSamplePosition(channelIdx, actor->pos.x, actor->pos.y, actor->pos.z);
 }
 
 void TwinEEngine::processBookOfBu() {
@@ -633,9 +633,9 @@ void TwinEEngine::processInventoryAction() {
 	case kiPinguin: {
 		ActorStruct *pinguin = _scene->getActor(_scene->mecaPinguinIdx);
 
-		pinguin->x = _renderer->destX + _scene->sceneHero->x;
-		pinguin->y = _scene->sceneHero->y;
-		pinguin->z = _renderer->destZ + _scene->sceneHero->z;
+		pinguin->pos.x = _renderer->destX + _scene->sceneHero->pos.x;
+		pinguin->pos.y = _scene->sceneHero->pos.y;
+		pinguin->pos.z = _renderer->destZ + _scene->sceneHero->pos.z;
 		pinguin->angle = _scene->sceneHero->angle;
 
 		_movements->rotateActor(0, 800, pinguin->angle);
@@ -855,10 +855,10 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 				_animations->initAnim(AnimationTypes::kLandDeath, kAnimationType_4, AnimationTypes::kStanding, 0);
 				actor->controlMode = ControlMode::kNoMove;
 			} else {
-				_sound->playSample(Samples::Explode, 1, actor->x, actor->y, actor->z, a);
+				_sound->playSample(Samples::Explode, 1, actor->pos, a);
 
 				if (a == _scene->mecaPinguinIdx) {
-					_extra->addExtraExplode(actor->x, actor->y, actor->z);
+					_extra->addExtraExplode(actor->pos.x, actor->pos.y, actor->pos.z);
 				}
 			}
 
@@ -869,9 +869,9 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 
 		_movements->processActorMovements(a);
 
-		actor->collisionX = actor->x;
-		actor->collisionY = actor->y;
-		actor->collisionZ = actor->z;
+		actor->collisionX = actor->pos.x;
+		actor->collisionY = actor->pos.y;
+		actor->collisionZ = actor->pos.z;
 
 		if (actor->positionInMoveScript != -1) {
 			_scriptMove->processMoveScript(a);
@@ -894,7 +894,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 		}
 
 		if (actor->staticFlags.bCanDrown) {
-			int32 brickSound = _grid->getBrickSoundType(actor->x, actor->y - 1, actor->z);
+			int32 brickSound = _grid->getBrickSoundType(actor->pos.x, actor->pos.y - 1, actor->pos.z);
 			actor->brickSound = brickSound;
 
 			if ((brickSound & 0xF0) == 0xF0) {
@@ -903,17 +903,17 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 						if (_actor->heroBehaviour != HeroBehaviourType::kProtoPack || actor->anim != AnimationTypes::kForward) {
 							if (!_actor->cropBottomScreen) {
 								_animations->initAnim(AnimationTypes::kDrawn, kAnimationType_4, AnimationTypes::kStanding, 0);
-								_renderer->projectPositionOnScreen(actor->x - _grid->camera.x, actor->y - _grid->camera.y, actor->z - _grid->camera.z);
+								_renderer->projectPositionOnScreen(actor->pos.x - _grid->camera.x, actor->pos.y - _grid->camera.y, actor->pos.z - _grid->camera.z);
 								_actor->cropBottomScreen = _renderer->projPosY;
 							}
-							_renderer->projectPositionOnScreen(actor->x - _grid->camera.x, actor->y - _grid->camera.y, actor->z - _grid->camera.z);
+							_renderer->projectPositionOnScreen(actor->pos.x - _grid->camera.x, actor->pos.y - _grid->camera.y, actor->pos.z - _grid->camera.z);
 							actor->controlMode = ControlMode::kNoMove;
 							actor->life = -1;
 							_actor->cropBottomScreen = _renderer->projPosY;
 							actor->staticFlags.bCanDrown |= 0x10; // TODO: doesn't make sense
 						}
 					} else {
-						_sound->playSample(Samples::Explode, 1, actor->x, actor->y, actor->z, a);
+						_sound->playSample(Samples::Explode, 1, actor->pos, a);
 						if (actor->bonusParameter.cloverleaf || actor->bonusParameter.kashes || actor->bonusParameter.key || actor->bonusParameter.lifepoints || actor->bonusParameter.magicpoints) {
 							if (!actor->bonusParameter.unk1) {
 								_actor->processActorExtraBonus(a);
@@ -929,9 +929,9 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 			if (IS_HERO(a)) {
 				if (actor->dynamicFlags.bAnimEnded) {
 					if (_gameState->inventoryNumLeafs > 0) { // use clover leaf automaticaly
-						_scene->sceneHero->x = _scene->newHeroX;
-						_scene->sceneHero->y = _scene->newHeroY;
-						_scene->sceneHero->z = _scene->newHeroZ;
+						_scene->sceneHero->pos.x = _scene->newHeroX;
+						_scene->sceneHero->pos.y = _scene->newHeroY;
+						_scene->sceneHero->pos.z = _scene->newHeroZ;
 
 						_scene->needChangeScene = _scene->currentSceneIdx;
 						_gameState->inventoryMagicPoints = _gameState->magicLevelIdx * 20;


Commit: 63a27de46fd0c55c0f36cac0860de6c3a0a63c01
    https://github.com/scummvm/scummvm/commit/63a27de46fd0c55c0f36cac0860de6c3a0a63c01
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:12:52+01:00

Commit Message:
TWINE: converted lastPos to Vec3 struct

Changed paths:
    engines/twine/renderer/redraw.cpp
    engines/twine/scene/actor.cpp
    engines/twine/scene/actor.h
    engines/twine/scene/animations.cpp
    engines/twine/scene/collision.cpp
    engines/twine/scene/movements.cpp
    engines/twine/scene/movements.h
    engines/twine/script/script_life_v1.cpp


diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index f861c7e984..c864f7fa15 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -230,7 +230,7 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 				drawList[drawListPos].type = DrawListType::DrawActorSprites;
 				drawList[drawListPos].actorIdx = modelActorPos;
 				if (actor->staticFlags.bUsesClipping) {
-					tmpVal = actor->lastX - _engine->_grid->camera.x + actor->lastZ - _engine->_grid->camera.z;
+					tmpVal = actor->lastPos.x - _engine->_grid->camera.x + actor->lastPos.z - _engine->_grid->camera.z;
 				}
 			} else {
 				drawList[drawListPos].type = 0;
@@ -431,9 +431,9 @@ void Redraw::processDrawListActorSprites(const DrawListStruct &drawCmd, bool bgR
 		actor->dynamicFlags.bIsVisible = 1;
 
 		if (actor->staticFlags.bUsesClipping) {
-			const int32 tmpX = (actor->lastX + BRICK_HEIGHT) / BRICK_SIZE;
-			const int32 tmpY = actor->lastY / BRICK_HEIGHT;
-			const int32 tmpZ = (actor->lastZ + BRICK_HEIGHT) / BRICK_SIZE;
+			const int32 tmpX = (actor->lastPos.x + BRICK_HEIGHT) / BRICK_SIZE;
+			const int32 tmpY = actor->lastPos.y / BRICK_HEIGHT;
+			const int32 tmpZ = (actor->lastPos.z + BRICK_HEIGHT) / BRICK_SIZE;
 			_engine->_grid->drawOverSpriteActor(tmpX, tmpY, tmpZ);
 		} else {
 			const int32 tmpX = (actor->pos.x + actor->boudingBox.x.topRight + BRICK_HEIGHT) / BRICK_SIZE;
diff --git a/engines/twine/scene/actor.cpp b/engines/twine/scene/actor.cpp
index e18d69e7f2..5d7a7aba0c 100644
--- a/engines/twine/scene/actor.cpp
+++ b/engines/twine/scene/actor.cpp
@@ -322,9 +322,7 @@ void Actor::initActor(int16 actorIdx) {
 		_engine->_movements->setActorAngleSafe(ANGLE_0, ANGLE_0, ANGLE_0, &actor->move);
 
 		if (actor->staticFlags.bUsesClipping) {
-			actor->lastX = actor->pos.x;
-			actor->lastY = actor->pos.y;
-			actor->lastZ = actor->pos.z;
+			actor->lastPos = actor->pos;
 		}
 	} else {
 		actor->entity = -1;
@@ -387,9 +385,9 @@ void Actor::resetActor(int16 actorIdx) {
 	actor->armor = 1;
 	actor->hitBy = -1;
 	actor->lastRotationAngle = ANGLE_0;
-	actor->lastX = 0;
-	actor->lastY = 0;
-	actor->lastZ = 0;
+	actor->lastPos.x = 0;
+	actor->lastPos.y = 0;
+	actor->lastPos.z = 0;
 	actor->entity = -1;
 	actor->previousAnimIdx = -1;
 	actor->animType = kAnimationTypeLoop;
diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index f39e6e9885..9a99f2a9ff 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -236,9 +236,7 @@ public:
 	int32 zone = 0;
 
 	int32 lastRotationAngle = ANGLE_0;
-	int32 lastX = 0;
-	int32 lastZ = 0;
-	int32 lastY = 0;
+	Vec3 lastPos;
 	int32 previousAnimIdx = 0;
 	int32 doorStatus = 0;
 	int32 animPosition = 0;
diff --git a/engines/twine/scene/animations.cpp b/engines/twine/scene/animations.cpp
index c505948976..a13cff2d39 100644
--- a/engines/twine/scene/animations.cpp
+++ b/engines/twine/scene/animations.cpp
@@ -499,9 +499,9 @@ bool Animations::initAnim(AnimationTypes newAnim, int16 animType, AnimationTypes
 	processAnimActions(actorIdx);
 
 	actor->lastRotationAngle = ANGLE_0;
-	actor->lastX = 0;
-	actor->lastY = 0;
-	actor->lastZ = 0;
+	actor->lastPos.x = 0;
+	actor->lastPos.y = 0;
+	actor->lastPos.z = 0;
 
 	return true;
 }
@@ -553,15 +553,15 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 				if (actor->dynamicFlags.bIsSpriteMoving) {
 					if (actor->doorStatus) { // open door
-						if (_engine->_movements->getDistance2D(_engine->_movements->processActorX, _engine->_movements->processActorZ, actor->lastX, actor->lastZ) >= actor->doorStatus) {
+						if (_engine->_movements->getDistance2D(_engine->_movements->processActorX, _engine->_movements->processActorZ, actor->lastPos.x, actor->lastPos.z) >= actor->doorStatus) {
 							if (actor->angle == ANGLE_0) {
-								_engine->_movements->processActorZ = actor->lastZ + actor->doorStatus;
+								_engine->_movements->processActorZ = actor->lastPos.z + actor->doorStatus;
 							} else if (actor->angle == ANGLE_90) {
-								_engine->_movements->processActorX = actor->lastX + actor->doorStatus;
+								_engine->_movements->processActorX = actor->lastPos.x + actor->doorStatus;
 							} else if (actor->angle == ANGLE_180) {
-								_engine->_movements->processActorZ = actor->lastZ - actor->doorStatus;
+								_engine->_movements->processActorZ = actor->lastPos.z - actor->doorStatus;
 							} else if (actor->angle == ANGLE_270) {
-								_engine->_movements->processActorX = actor->lastX - actor->doorStatus;
+								_engine->_movements->processActorX = actor->lastPos.x - actor->doorStatus;
 							}
 
 							actor->dynamicFlags.bIsSpriteMoving = 0;
@@ -571,27 +571,27 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 						bool updatePos = false;
 
 						if (actor->angle == ANGLE_0) {
-							if (_engine->_movements->processActorZ <= actor->lastZ) {
+							if (_engine->_movements->processActorZ <= actor->lastPos.z) {
 								updatePos = true;
 							}
 						} else if (actor->angle == ANGLE_90) {
-							if (_engine->_movements->processActorX <= actor->lastX) {
+							if (_engine->_movements->processActorX <= actor->lastPos.x) {
 								updatePos = true;
 							}
 						} else if (actor->angle == ANGLE_180) {
-							if (_engine->_movements->processActorZ >= actor->lastZ) {
+							if (_engine->_movements->processActorZ >= actor->lastPos.z) {
 								updatePos = true;
 							}
 						} else if (actor->angle == ANGLE_270) {
-							if (_engine->_movements->processActorX >= actor->lastX) {
+							if (_engine->_movements->processActorX >= actor->lastPos.x) {
 								updatePos = true;
 							}
 						}
 
 						if (updatePos) {
-							_engine->_movements->processActorX = actor->lastX;
-							_engine->_movements->processActorY = actor->lastY;
-							_engine->_movements->processActorZ = actor->lastZ;
+							_engine->_movements->processActorX = actor->lastPos.x;
+							_engine->_movements->processActorY = actor->lastPos.y;
+							_engine->_movements->processActorZ = actor->lastPos.z;
 
 							actor->dynamicFlags.bIsSpriteMoving = 0;
 							actor->speed = 0;
@@ -601,18 +601,18 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			}
 
 			if (actor->staticFlags.bCanBePushed) {
-				_engine->_movements->processActorX += actor->lastX;
-				_engine->_movements->processActorY += actor->lastY;
-				_engine->_movements->processActorZ += actor->lastZ;
+				_engine->_movements->processActorX += actor->lastPos.x;
+				_engine->_movements->processActorY += actor->lastPos.y;
+				_engine->_movements->processActorZ += actor->lastPos.z;
 
 				if (actor->staticFlags.bUseMiniZv) {
 					_engine->_movements->processActorX = ((_engine->_movements->processActorX / 128) * 128);
 					_engine->_movements->processActorZ = ((_engine->_movements->processActorZ / 128) * 128);
 				}
 
-				actor->lastX = 0;
-				actor->lastY = 0;
-				actor->lastZ = 0;
+				actor->lastPos.x = 0;
+				actor->lastPos.y = 0;
+				actor->lastPos.z = 0;
 			}
 		}
 	} else { // 3D actor
@@ -639,13 +639,13 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			currentStepX = _engine->_renderer->destX;
 			currentStepZ = _engine->_renderer->destZ;
 
-			_engine->_movements->processActorX = actor->pos.x + currentStepX - actor->lastX;
-			_engine->_movements->processActorY = actor->pos.y + currentStepY - actor->lastY;
-			_engine->_movements->processActorZ = actor->pos.z + currentStepZ - actor->lastZ;
+			_engine->_movements->processActorX = actor->pos.x + currentStepX - actor->lastPos.x;
+			_engine->_movements->processActorY = actor->pos.y + currentStepY - actor->lastPos.y;
+			_engine->_movements->processActorZ = actor->pos.z + currentStepZ - actor->lastPos.z;
 
-			actor->lastX = currentStepX;
-			actor->lastY = currentStepY;
-			actor->lastZ = currentStepZ;
+			actor->lastPos.x = currentStepX;
+			actor->lastPos.y = currentStepY;
+			actor->lastPos.z = currentStepZ;
 
 			actor->dynamicFlags.bAnimEnded = 0;
 			actor->dynamicFlags.bAnimFrameReached = 0;
@@ -685,9 +685,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 				actor->lastRotationAngle = ANGLE_0;
 
-				actor->lastX = 0;
-				actor->lastY = 0;
-				actor->lastZ = 0;
+				actor->lastPos.x = 0;
+				actor->lastPos.y = 0;
+				actor->lastPos.z = 0;
 			}
 		}
 	}
diff --git a/engines/twine/scene/collision.cpp b/engines/twine/scene/collision.cpp
index 04f631c0a1..ae8522850c 100644
--- a/engines/twine/scene/collision.cpp
+++ b/engines/twine/scene/collision.cpp
@@ -246,24 +246,24 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 							int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->pos.x, actorTest->pos.z);
 
 							if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
-								actorTest->lastY = 0;
+								actorTest->lastPos.y = 0;
 
 								if (actorTest->staticFlags.bUseMiniZv) {
 									if (newAngle >= ANGLE_45 && newAngle < ANGLE_135 && actor->angle > ANGLE_45 && actor->angle < ANGLE_135) {
-										actorTest->lastX = 192;
+										actorTest->lastPos.x = 192;
 									}
 									if (newAngle >= ANGLE_135 && newAngle < ANGLE_225 && actor->angle > ANGLE_135 && actor->angle < ANGLE_225) {
-										actorTest->lastZ = -64;
+										actorTest->lastPos.z = -64;
 									}
 									if (newAngle >= ANGLE_225 && newAngle < ANGLE_315 && actor->angle > ANGLE_225 && actor->angle < ANGLE_315) {
-										actorTest->lastX = -64;
+										actorTest->lastPos.x = -64;
 									}
 									if ((newAngle >= ANGLE_315 || newAngle < ANGLE_45) && (actor->angle > ANGLE_315 || actor->angle < ANGLE_45)) {
-										actorTest->lastX = 192;
+										actorTest->lastPos.x = 192;
 									}
 								} else {
-									actorTest->lastX = _engine->_movements->processActorX - actor->collisionX;
-									actorTest->lastZ = _engine->_movements->processActorZ - actor->collisionZ;
+									actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionX;
+									actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionZ;
 								}
 							}
 
@@ -298,24 +298,24 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 					int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->pos.x, actorTest->pos.z);
 
 					if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
-						actorTest->lastY = 0;
+						actorTest->lastPos.y = 0;
 
 						if (actorTest->staticFlags.bUseMiniZv) {
 							if (newAngle >= ANGLE_45 && newAngle < ANGLE_135 && actor->angle > ANGLE_45 && actor->angle < ANGLE_135) {
-								actorTest->lastX = 192;
+								actorTest->lastPos.x = 192;
 							}
 							if (newAngle >= ANGLE_135 && newAngle < ANGLE_225 && actor->angle > ANGLE_135 && actor->angle < ANGLE_225) {
-								actorTest->lastZ = -64;
+								actorTest->lastPos.z = -64;
 							}
 							if (newAngle >= ANGLE_225 && newAngle < ANGLE_315 && actor->angle > ANGLE_225 && actor->angle < ANGLE_315) {
-								actorTest->lastX = -64;
+								actorTest->lastPos.x = -64;
 							}
 							if ((newAngle >= ANGLE_315 || newAngle < ANGLE_45) && (actor->angle > ANGLE_315 || actor->angle < ANGLE_45)) {
-								actorTest->lastX = 192;
+								actorTest->lastPos.x = 192;
 							}
 						} else {
-							actorTest->lastX = _engine->_movements->processActorX - actor->collisionX;
-							actorTest->lastZ = _engine->_movements->processActorZ - actor->collisionZ;
+							actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionX;
+							actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionZ;
 						}
 					}
 
diff --git a/engines/twine/scene/movements.cpp b/engines/twine/scene/movements.cpp
index 50707df4ed..cc410a95cd 100644
--- a/engines/twine/scene/movements.cpp
+++ b/engines/twine/scene/movements.cpp
@@ -150,6 +150,10 @@ int32 Movements::getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2) const {
 	return (int32)sqrt((float)((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1)));
 }
 
+int32 Movements::getDistance2D(const Vec3 &v1, const Vec3 &v2) const {
+	return (int32)sqrt((float)((v2.x - v1.x) * (v2.x - v1.x) + (v2.z - v1.z) * (v2.z - v1.z)));
+}
+
 int32 Movements::getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2, int32 z2) const {
 	return (int32)sqrt((float)((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1)));
 }
diff --git a/engines/twine/scene/movements.h b/engines/twine/scene/movements.h
index fca3b0d7f0..81357ef918 100644
--- a/engines/twine/scene/movements.h
+++ b/engines/twine/scene/movements.h
@@ -208,6 +208,7 @@ public:
 	 * @param z2 Actor 2 Z coordinate
 	 */
 	int32 getDistance2D(int32 x1, int32 z1, int32 x2, int32 z2) const;
+	int32 getDistance2D(const Vec3 &v1, const Vec3 &v2) const;
 
 	/**
 	 * Get distance value in 3D
@@ -220,6 +221,7 @@ public:
 	 */
 	int32 getDistance3D(int32 x1, int32 y1, int32 z1, int32 x2, int32 y2, int32 z2) const;
 	int32 getDistance3D(const Vec3 &v1, const Vec3 &v2) const;
+
 	/**
 	 * Move actor around the scene
 	 * @param angleFrom Current actor angle
diff --git a/engines/twine/script/script_life_v1.cpp b/engines/twine/script/script_life_v1.cpp
index db6d53cbf0..1e3eed962a 100644
--- a/engines/twine/script/script_life_v1.cpp
+++ b/engines/twine/script/script_life_v1.cpp
@@ -952,7 +952,7 @@ static int32 lSET_DOOR_LEFT(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_270;
-	ctx.actor->pos.x = ctx.actor->lastX - distance;
+	ctx.actor->pos.x = ctx.actor->lastPos.x - distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -967,7 +967,7 @@ static int32 lSET_DOOR_RIGHT(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_90;
-	ctx.actor->pos.x = ctx.actor->lastX + distance;
+	ctx.actor->pos.x = ctx.actor->lastPos.x + distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -982,7 +982,7 @@ static int32 lSET_DOOR_UP(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_180;
-	ctx.actor->pos.z = ctx.actor->lastZ - distance;
+	ctx.actor->pos.z = ctx.actor->lastPos.z - distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 
@@ -997,7 +997,7 @@ static int32 lSET_DOOR_DOWN(TwinEEngine *engine, LifeScriptContext &ctx) {
 	int32 distance = ctx.stream.readSint16LE();
 
 	ctx.actor->angle = ANGLE_0;
-	ctx.actor->pos.z = ctx.actor->lastZ + distance;
+	ctx.actor->pos.z = ctx.actor->lastPos.z + distance;
 	ctx.actor->dynamicFlags.bIsSpriteMoving = 0;
 	ctx.actor->speed = 0;
 


Commit: 91e34e13074f3aa4f04057a7e0853645b36a6364
    https://github.com/scummvm/scummvm/commit/91e34e13074f3aa4f04057a7e0853645b36a6364
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:15:44+01:00

Commit Message:
TWINE: convertged collision position to Vec3 struct

Changed paths:
    engines/twine/scene/actor.h
    engines/twine/scene/animations.cpp
    engines/twine/scene/collision.cpp
    engines/twine/scene/scene.cpp
    engines/twine/twine.cpp


diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index 9a99f2a9ff..00040827b0 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -214,9 +214,7 @@ public:
 	int32 armor = 0; // field_14
 	int32 life = 0;
 
-	int32 collisionX = 0; // field_20
-	int32 collisionY = 0; // field_22
-	int32 collisionZ = 0; // field_24
+	Vec3 collisionPos;
 
 	int32 positionInMoveScript = 0;
 	uint8 *moveScript = nullptr;
diff --git a/engines/twine/scene/animations.cpp b/engines/twine/scene/animations.cpp
index a13cff2d39..ae9c82a7a2 100644
--- a/engines/twine/scene/animations.cpp
+++ b/engines/twine/scene/animations.cpp
@@ -516,9 +516,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		return;
 	}
 
-	_engine->_movements->previousActorX = actor->collisionX;
-	_engine->_movements->previousActorY = actor->collisionY;
-	_engine->_movements->previousActorZ = actor->collisionZ;
+	_engine->_movements->previousActorX = actor->collisionPos.x;
+	_engine->_movements->previousActorY = actor->collisionPos.y;
+	_engine->_movements->previousActorZ = actor->collisionPos.z;
 
 	if (actor->staticFlags.bIsSpriteActor) { // is sprite actor
 		if (actor->strengthOfHit) {
@@ -695,9 +695,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 	// actor standing on another actor
 	if (actor->standOn != -1) {
 		const ActorStruct *standOnActor = _engine->_scene->getActor(actor->standOn);
-		_engine->_movements->processActorX -= standOnActor->collisionX;
-		_engine->_movements->processActorY -= standOnActor->collisionY;
-		_engine->_movements->processActorZ -= standOnActor->collisionZ;
+		_engine->_movements->processActorX -= standOnActor->collisionPos.x;
+		_engine->_movements->processActorY -= standOnActor->collisionPos.y;
+		_engine->_movements->processActorZ -= standOnActor->collisionPos.z;
 
 		_engine->_movements->processActorX += standOnActor->pos.x;
 		_engine->_movements->processActorY += standOnActor->pos.y;
diff --git a/engines/twine/scene/collision.cpp b/engines/twine/scene/collision.cpp
index ae8522850c..679a27a981 100644
--- a/engines/twine/scene/collision.cpp
+++ b/engines/twine/scene/collision.cpp
@@ -262,8 +262,8 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 										actorTest->lastPos.x = 192;
 									}
 								} else {
-									actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionX;
-									actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionZ;
+									actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionPos.x;
+									actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionPos.z;
 								}
 							}
 
@@ -314,8 +314,8 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 								actorTest->lastPos.x = 192;
 							}
 						} else {
-							actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionX;
-							actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionZ;
+							actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionPos.x;
+							actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionPos.z;
 						}
 					}
 
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index 2a1479b0a1..3fbf60358c 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -198,11 +198,11 @@ bool Scene::loadSceneLBA2() {
 		act->anim = (AnimationTypes)stream.readByte();
 		act->sprite = stream.readUint16LE();
 		act->pos.x = stream.readUint16LE();
-		act->collisionX = act->pos.x;
+		act->collisionPos.x = act->pos.x;
 		act->pos.y = stream.readUint16LE();
-		act->collisionY = act->pos.y;
+		act->collisionPos.y = act->pos.y;
 		act->pos.z = stream.readUint16LE();
-		act->collisionZ = act->pos.z;
+		act->collisionPos.z = act->pos.z;
 		act->strengthOfHit = stream.readByte();
 		setBonusParameterFlags(act, stream.readUint16LE());
 		act->angle = stream.readUint16LE();
@@ -331,11 +331,11 @@ bool Scene::loadSceneLBA1() {
 		act->anim = (AnimationTypes)stream.readByte();
 		act->sprite = stream.readUint16LE();
 		act->pos.x = stream.readUint16LE();
-		act->collisionX = act->pos.x;
+		act->collisionPos.x = act->pos.x;
 		act->pos.y = stream.readUint16LE();
-		act->collisionY = act->pos.y;
+		act->collisionPos.y = act->pos.y;
 		act->pos.z = stream.readUint16LE();
-		act->collisionZ = act->pos.z;
+		act->collisionPos.z = act->pos.z;
 		act->strengthOfHit = stream.readByte();
 		setBonusParameterFlags(act, stream.readUint16LE());
 		act->angle = stream.readUint16LE();
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 564c1880d9..7ab9c77bca 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -869,9 +869,7 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 
 		_movements->processActorMovements(a);
 
-		actor->collisionX = actor->pos.x;
-		actor->collisionY = actor->pos.y;
-		actor->collisionZ = actor->pos.z;
+		actor->collisionPos = actor->pos;
 
 		if (actor->positionInMoveScript != -1) {
 			_scriptMove->processMoveScript(a);


Commit: eaf9de0bf052acee6d355db7d8948113c6c64fee
    https://github.com/scummvm/scummvm/commit/eaf9de0bf052acee6d355db7d8948113c6c64fee
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:17:57+01:00

Commit Message:
TWINE: converted shadow coordinates to Vec3 struct

Changed paths:
    engines/twine/renderer/redraw.cpp
    engines/twine/scene/actor.h
    engines/twine/scene/movements.cpp


diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index c864f7fa15..c65ad62c2e 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -244,9 +244,9 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 			// if use shadows
 			if (_engine->cfgfile.ShadowMode != 0 && !(actor->staticFlags.bDoesntCastShadow)) {
 				if (actor->standOn != -1) {
-					_engine->_actor->shadowX = actor->pos.x;
-					_engine->_actor->shadowY = actor->pos.y - 1;
-					_engine->_actor->shadowZ = actor->pos.z;
+					_engine->_actor->shadowCoord.x = actor->pos.x;
+					_engine->_actor->shadowCoord.y = actor->pos.y - 1;
+					_engine->_actor->shadowCoord.z = actor->pos.z;
 				} else {
 					_engine->_movements->getShadowPosition(actor->pos.x, actor->pos.y, actor->pos.z);
 				}
@@ -255,9 +255,9 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 				drawList[drawListPos].posValue = tmpVal; // save the shadow entry in the drawList
 				drawList[drawListPos].type = DrawListType::DrawShadows;
 				drawList[drawListPos].actorIdx = 0;
-				drawList[drawListPos].x = _engine->_actor->shadowX;
-				drawList[drawListPos].y = _engine->_actor->shadowY;
-				drawList[drawListPos].z = _engine->_actor->shadowZ;
+				drawList[drawListPos].x = _engine->_actor->shadowCoord.x;
+				drawList[drawListPos].y = _engine->_actor->shadowCoord.y;
+				drawList[drawListPos].z = _engine->_actor->shadowCoord.z;
 				drawList[drawListPos].offset = 2;
 				drawListPos++;
 			}
@@ -299,9 +299,9 @@ int32 Redraw::fillExtraDrawingList(int32 drawListPos) {
 					drawList[drawListPos].posValue = extra->x - _engine->_grid->camera.x + extra->z - _engine->_grid->camera.z - 1;
 					drawList[drawListPos].actorIdx = 0;
 					drawList[drawListPos].type = DrawListType::DrawShadows;
-					drawList[drawListPos].x = _engine->_actor->shadowX;
-					drawList[drawListPos].y = _engine->_actor->shadowY;
-					drawList[drawListPos].z = _engine->_actor->shadowZ;
+					drawList[drawListPos].x = _engine->_actor->shadowCoord.x;
+					drawList[drawListPos].y = _engine->_actor->shadowCoord.y;
+					drawList[drawListPos].z = _engine->_actor->shadowCoord.z;
 					drawList[drawListPos].offset = 0;
 					drawListPos++;
 				}
diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index 00040827b0..7c3a6c37f2 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -285,12 +285,8 @@ public:
 
 	ActorStruct *processActorPtr = nullptr; // processActorVar1
 
-	/** Actor shadow X coordinate */
-	int32 shadowX = 0;
-	/** Actor shadow Y coordinate */
-	int32 shadowY = 0;
-	/** Actor shadow Z coordinate */
-	int32 shadowZ = 0;
+	/** Actor shadow coordinate */
+	Vec3 shadowCoord;
 	/** Actor shadow collition type - brick shape */
 	ShapeType shadowCollisionType = ShapeType::kNone; // shadowVar
 
diff --git a/engines/twine/scene/movements.cpp b/engines/twine/scene/movements.cpp
index cc410a95cd..5620276bf2 100644
--- a/engines/twine/scene/movements.cpp
+++ b/engines/twine/scene/movements.cpp
@@ -51,9 +51,9 @@ void Movements::getShadowPosition(int32 x, int32 y, int32 z) {
 	}
 	_engine->_collision->reajustActorPosition(_engine->_actor->shadowCollisionType);
 
-	_engine->_actor->shadowX = processActorX;
-	_engine->_actor->shadowY = processActorY;
-	_engine->_actor->shadowZ = processActorZ;
+	_engine->_actor->shadowCoord.x = processActorX;
+	_engine->_actor->shadowCoord.y = processActorY;
+	_engine->_actor->shadowCoord.z = processActorZ;
 }
 
 void Movements::setActorAngleSafe(int16 startAngle, int16 endAngle, int16 stepAngle, ActorMoveStruct *movePtr) {


Commit: fda3ccc4df901c5acdddbd1d02d77b05f223025d
    https://github.com/scummvm/scummvm/commit/fda3ccc4df901c5acdddbd1d02d77b05f223025d
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:23:03+01:00

Commit Message:
TWINE: converted more positions to Vec3

Changed paths:
    engines/twine/scene/animations.cpp
    engines/twine/scene/collision.cpp
    engines/twine/scene/grid.cpp
    engines/twine/scene/grid.h
    engines/twine/scene/movements.cpp
    engines/twine/scene/movements.h
    engines/twine/scene/scene.cpp


diff --git a/engines/twine/scene/animations.cpp b/engines/twine/scene/animations.cpp
index ae9c82a7a2..43d9c8cbc5 100644
--- a/engines/twine/scene/animations.cpp
+++ b/engines/twine/scene/animations.cpp
@@ -516,18 +516,18 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		return;
 	}
 
-	_engine->_movements->previousActorX = actor->collisionPos.x;
-	_engine->_movements->previousActorY = actor->collisionPos.y;
-	_engine->_movements->previousActorZ = actor->collisionPos.z;
+	_engine->_movements->previousActor.x = actor->collisionPos.x;
+	_engine->_movements->previousActor.y = actor->collisionPos.y;
+	_engine->_movements->previousActor.z = actor->collisionPos.z;
 
 	if (actor->staticFlags.bIsSpriteActor) { // is sprite actor
 		if (actor->strengthOfHit) {
 			actor->dynamicFlags.bIsHitting = 1;
 		}
 
-		_engine->_movements->processActorX = actor->pos.x;
-		_engine->_movements->processActorY = actor->pos.y;
-		_engine->_movements->processActorZ = actor->pos.z;
+		_engine->_movements->processActor.x = actor->pos.x;
+		_engine->_movements->processActor.y = actor->pos.y;
+		_engine->_movements->processActor.z = actor->pos.z;
 
 		if (!actor->dynamicFlags.bIsFalling) {
 			if (actor->speed) {
@@ -542,26 +542,26 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 				_engine->_movements->rotateActor(xAxisRotation, 0, actor->animType);
 
-				_engine->_movements->processActorY = actor->pos.y - _engine->_renderer->destZ;
+				_engine->_movements->processActor.y = actor->pos.y - _engine->_renderer->destZ;
 
 				_engine->_movements->rotateActor(0, _engine->_renderer->destX, actor->angle);
 
-				_engine->_movements->processActorX = actor->pos.x + _engine->_renderer->destX;
-				_engine->_movements->processActorZ = actor->pos.z + _engine->_renderer->destZ;
+				_engine->_movements->processActor.x = actor->pos.x + _engine->_renderer->destX;
+				_engine->_movements->processActor.z = actor->pos.z + _engine->_renderer->destZ;
 
 				_engine->_movements->setActorAngle(ANGLE_0, actor->speed, ANGLE_17, &actor->move);
 
 				if (actor->dynamicFlags.bIsSpriteMoving) {
 					if (actor->doorStatus) { // open door
-						if (_engine->_movements->getDistance2D(_engine->_movements->processActorX, _engine->_movements->processActorZ, actor->lastPos.x, actor->lastPos.z) >= actor->doorStatus) {
+						if (_engine->_movements->getDistance2D(_engine->_movements->processActor.x, _engine->_movements->processActor.z, actor->lastPos.x, actor->lastPos.z) >= actor->doorStatus) {
 							if (actor->angle == ANGLE_0) {
-								_engine->_movements->processActorZ = actor->lastPos.z + actor->doorStatus;
+								_engine->_movements->processActor.z = actor->lastPos.z + actor->doorStatus;
 							} else if (actor->angle == ANGLE_90) {
-								_engine->_movements->processActorX = actor->lastPos.x + actor->doorStatus;
+								_engine->_movements->processActor.x = actor->lastPos.x + actor->doorStatus;
 							} else if (actor->angle == ANGLE_180) {
-								_engine->_movements->processActorZ = actor->lastPos.z - actor->doorStatus;
+								_engine->_movements->processActor.z = actor->lastPos.z - actor->doorStatus;
 							} else if (actor->angle == ANGLE_270) {
-								_engine->_movements->processActorX = actor->lastPos.x - actor->doorStatus;
+								_engine->_movements->processActor.x = actor->lastPos.x - actor->doorStatus;
 							}
 
 							actor->dynamicFlags.bIsSpriteMoving = 0;
@@ -571,27 +571,27 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 						bool updatePos = false;
 
 						if (actor->angle == ANGLE_0) {
-							if (_engine->_movements->processActorZ <= actor->lastPos.z) {
+							if (_engine->_movements->processActor.z <= actor->lastPos.z) {
 								updatePos = true;
 							}
 						} else if (actor->angle == ANGLE_90) {
-							if (_engine->_movements->processActorX <= actor->lastPos.x) {
+							if (_engine->_movements->processActor.x <= actor->lastPos.x) {
 								updatePos = true;
 							}
 						} else if (actor->angle == ANGLE_180) {
-							if (_engine->_movements->processActorZ >= actor->lastPos.z) {
+							if (_engine->_movements->processActor.z >= actor->lastPos.z) {
 								updatePos = true;
 							}
 						} else if (actor->angle == ANGLE_270) {
-							if (_engine->_movements->processActorX >= actor->lastPos.x) {
+							if (_engine->_movements->processActor.x >= actor->lastPos.x) {
 								updatePos = true;
 							}
 						}
 
 						if (updatePos) {
-							_engine->_movements->processActorX = actor->lastPos.x;
-							_engine->_movements->processActorY = actor->lastPos.y;
-							_engine->_movements->processActorZ = actor->lastPos.z;
+							_engine->_movements->processActor.x = actor->lastPos.x;
+							_engine->_movements->processActor.y = actor->lastPos.y;
+							_engine->_movements->processActor.z = actor->lastPos.z;
 
 							actor->dynamicFlags.bIsSpriteMoving = 0;
 							actor->speed = 0;
@@ -601,13 +601,13 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			}
 
 			if (actor->staticFlags.bCanBePushed) {
-				_engine->_movements->processActorX += actor->lastPos.x;
-				_engine->_movements->processActorY += actor->lastPos.y;
-				_engine->_movements->processActorZ += actor->lastPos.z;
+				_engine->_movements->processActor.x += actor->lastPos.x;
+				_engine->_movements->processActor.y += actor->lastPos.y;
+				_engine->_movements->processActor.z += actor->lastPos.z;
 
 				if (actor->staticFlags.bUseMiniZv) {
-					_engine->_movements->processActorX = ((_engine->_movements->processActorX / 128) * 128);
-					_engine->_movements->processActorZ = ((_engine->_movements->processActorZ / 128) * 128);
+					_engine->_movements->processActor.x = ((_engine->_movements->processActor.x / 128) * 128);
+					_engine->_movements->processActor.z = ((_engine->_movements->processActor.z / 128) * 128);
 				}
 
 				actor->lastPos.x = 0;
@@ -639,9 +639,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			currentStepX = _engine->_renderer->destX;
 			currentStepZ = _engine->_renderer->destZ;
 
-			_engine->_movements->processActorX = actor->pos.x + currentStepX - actor->lastPos.x;
-			_engine->_movements->processActorY = actor->pos.y + currentStepY - actor->lastPos.y;
-			_engine->_movements->processActorZ = actor->pos.z + currentStepZ - actor->lastPos.z;
+			_engine->_movements->processActor.x = actor->pos.x + currentStepX - actor->lastPos.x;
+			_engine->_movements->processActor.y = actor->pos.y + currentStepY - actor->lastPos.y;
+			_engine->_movements->processActor.z = actor->pos.z + currentStepZ - actor->lastPos.z;
 
 			actor->lastPos.x = currentStepX;
 			actor->lastPos.y = currentStepY;
@@ -695,13 +695,13 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 	// actor standing on another actor
 	if (actor->standOn != -1) {
 		const ActorStruct *standOnActor = _engine->_scene->getActor(actor->standOn);
-		_engine->_movements->processActorX -= standOnActor->collisionPos.x;
-		_engine->_movements->processActorY -= standOnActor->collisionPos.y;
-		_engine->_movements->processActorZ -= standOnActor->collisionPos.z;
+		_engine->_movements->processActor.x -= standOnActor->collisionPos.x;
+		_engine->_movements->processActor.y -= standOnActor->collisionPos.y;
+		_engine->_movements->processActor.z -= standOnActor->collisionPos.z;
 
-		_engine->_movements->processActorX += standOnActor->pos.x;
-		_engine->_movements->processActorY += standOnActor->pos.y;
-		_engine->_movements->processActorZ += standOnActor->pos.z;
+		_engine->_movements->processActor.x += standOnActor->pos.x;
+		_engine->_movements->processActor.y += standOnActor->pos.y;
+		_engine->_movements->processActor.z += standOnActor->pos.z;
 
 		if (!_engine->_collision->standingOnActor(actorIdx, actor->standOn)) {
 			actor->standOn = -1; // no longer standing on other actor
@@ -710,22 +710,22 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 	// actor falling Y speed
 	if (actor->dynamicFlags.bIsFalling) {
-		_engine->_movements->processActorX = _engine->_movements->previousActorX;
-		_engine->_movements->processActorY = _engine->_movements->previousActorY + _engine->loopActorStep; // add step to fall
-		_engine->_movements->processActorZ = _engine->_movements->previousActorZ;
+		_engine->_movements->processActor.x = _engine->_movements->previousActor.x;
+		_engine->_movements->processActor.y = _engine->_movements->previousActor.y + _engine->loopActorStep; // add step to fall
+		_engine->_movements->processActor.z = _engine->_movements->previousActor.z;
 	}
 
 	// actor collisions with bricks
 	if (actor->staticFlags.bComputeCollisionWithBricks) {
 		_engine->_collision->collisionY = 0;
 
-		ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->previousActorX, _engine->_movements->previousActorY, _engine->_movements->previousActorZ);
+		ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->previousActor.x, _engine->_movements->previousActor.y, _engine->_movements->previousActor.z);
 
 		if (brickShape != ShapeType::kNone) {
 			if (brickShape != ShapeType::kSolid) {
 				_engine->_collision->reajustActorPosition(brickShape);
 			} /*else { // this shouldn't happen (collision should avoid it)
-				actor->y = processActorY = (processActorY / BRICK_HEIGHT) * BRICK_HEIGHT + BRICK_HEIGHT; // go upper
+				actor->y = processActor.y = (processActor.y / BRICK_HEIGHT) * BRICK_HEIGHT + BRICK_HEIGHT; // go upper
 			}*/
 		}
 
@@ -739,9 +739,9 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 		_engine->_collision->causeActorDamage = 0;
 
-		_engine->_collision->processCollisionX = _engine->_movements->processActorX;
-		_engine->_collision->processCollisionY = _engine->_movements->processActorY;
-		_engine->_collision->processCollisionZ = _engine->_movements->processActorZ;
+		_engine->_collision->processCollisionX = _engine->_movements->processActor.x;
+		_engine->_collision->processCollisionY = _engine->_movements->processActor.y;
+		_engine->_collision->processCollisionZ = _engine->_movements->processActor.z;
 
 		if (IS_HERO(actorIdx) && !actor->staticFlags.bComputeLowCollision) {
 			// check hero collisions with bricks
@@ -761,11 +761,11 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		if (_engine->_collision->causeActorDamage && !actor->dynamicFlags.bIsFalling && !currentlyProcessedActorIdx && _engine->_actor->heroBehaviour == HeroBehaviourType::kAthletic && actor->anim == AnimationTypes::kForward) {
 			_engine->_movements->rotateActor(actor->boudingBox.x.bottomLeft, actor->boudingBox.z.bottomLeft, actor->angle + ANGLE_360 + ANGLE_135);
 
-			_engine->_renderer->destX += _engine->_movements->processActorX;
-			_engine->_renderer->destZ += _engine->_movements->processActorZ;
+			_engine->_renderer->destX += _engine->_movements->processActor.x;
+			_engine->_renderer->destZ += _engine->_movements->processActor.z;
 
 			if (_engine->_renderer->destX >= 0 && _engine->_renderer->destZ >= 0 && _engine->_renderer->destX <= 0x7E00 && _engine->_renderer->destZ <= 0x7E00) {
-				if (_engine->_grid->getBrickShape(_engine->_renderer->destX, _engine->_movements->processActorY + BRICK_HEIGHT, _engine->_renderer->destZ) != ShapeType::kNone && _engine->cfgfile.WallCollision) { // avoid wall hit damage
+				if (_engine->_grid->getBrickShape(_engine->_renderer->destX, _engine->_movements->processActor.y + BRICK_HEIGHT, _engine->_renderer->destZ) != ShapeType::kNone && _engine->cfgfile.WallCollision) { // avoid wall hit damage
 					_engine->_extra->addExtraSpecial(actor->pos.x, actor->pos.y + 1000, actor->pos.z, ExtraSpecialType::kHitStars);
 					initAnim(AnimationTypes::kBigHit, kAnimationType_2, AnimationTypes::kStanding, currentlyProcessedActorIdx);
 
@@ -778,14 +778,14 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			}
 		}
 
-		brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
+		brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z);
 		actor->setBrickShape(brickShape);
 
 		if (brickShape != ShapeType::kNone) {
 			if (brickShape == ShapeType::kSolid) {
 				if (actor->dynamicFlags.bIsFalling) {
 					_engine->_collision->stopFalling();
-					_engine->_movements->processActorY = (_engine->_collision->collisionY * BRICK_HEIGHT) + BRICK_HEIGHT;
+					_engine->_movements->processActor.y = (_engine->_collision->collisionY * BRICK_HEIGHT) + BRICK_HEIGHT;
 				} else {
 					if (IS_HERO(actorIdx) && _engine->_actor->heroBehaviour == HeroBehaviourType::kAthletic && actor->anim == AnimationTypes::kForward && _engine->cfgfile.WallCollision) { // avoid wall hit damage
 						_engine->_extra->addExtraSpecial(actor->pos.x, actor->pos.y + 1000, actor->pos.z, ExtraSpecialType::kHitStars);
@@ -795,18 +795,18 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 					}
 
 					// no Z coordinate issue
-					if (_engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ) == ShapeType::kNone) {
-						_engine->_movements->processActorZ = _engine->_movements->previousActorZ;
+					if (_engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->previousActor.z) == ShapeType::kNone) {
+						_engine->_movements->processActor.z = _engine->_movements->previousActor.z;
 					}
 
 					// no X coordinate issue
-					if (_engine->_grid->getBrickShape(_engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ) == ShapeType::kNone) {
-						_engine->_movements->processActorX = _engine->_movements->previousActorX;
+					if (_engine->_grid->getBrickShape(_engine->_movements->previousActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z) == ShapeType::kNone) {
+						_engine->_movements->processActor.x = _engine->_movements->previousActor.x;
 					}
 
 					// X and Z with issue, no move
-					if (_engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ) != ShapeType::kNone &&
-					    _engine->_grid->getBrickShape(_engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ) != ShapeType::kNone) {
+					if (_engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->previousActor.z) != ShapeType::kNone &&
+					    _engine->_grid->getBrickShape(_engine->_movements->previousActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z) != ShapeType::kNone) {
 						return;
 					}
 				}
@@ -821,7 +821,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			actor->dynamicFlags.bIsFalling = 0;
 		} else {
 			if (actor->staticFlags.bCanFall && actor->standOn == -1) {
-				brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY - 1, _engine->_movements->processActorZ);
+				brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y - 1, _engine->_movements->processActor.z);
 
 				if (brickShape != ShapeType::kNone) {
 					if (actor->dynamicFlags.bIsFalling) {
@@ -834,7 +834,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 						actor->dynamicFlags.bIsFalling = 1;
 
 						if (IS_HERO(actorIdx) && _engine->_scene->heroYBeforeFall == 0) {
-							_engine->_scene->heroYBeforeFall = _engine->_movements->processActorY;
+							_engine->_scene->heroYBeforeFall = _engine->_movements->processActor.y;
 						}
 
 						initAnim(AnimationTypes::kFall, kAnimationTypeLoop, AnimationTypes::kAnimInvalid, actorIdx);
@@ -858,29 +858,29 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 	}
 
 	// check and fix actor bounding position
-	if (_engine->_movements->processActorX < 0) {
-		_engine->_movements->processActorX = 0;
+	if (_engine->_movements->processActor.x < 0) {
+		_engine->_movements->processActor.x = 0;
 	}
 
-	if (_engine->_movements->processActorY < 0) {
-		_engine->_movements->processActorY = 0;
+	if (_engine->_movements->processActor.y < 0) {
+		_engine->_movements->processActor.y = 0;
 	}
 
-	if (_engine->_movements->processActorZ < 0) {
-		_engine->_movements->processActorZ = 0;
+	if (_engine->_movements->processActor.z < 0) {
+		_engine->_movements->processActor.z = 0;
 	}
 
-	if (_engine->_movements->processActorX > 0x7E00) {
-		_engine->_movements->processActorX = 0x7E00;
+	if (_engine->_movements->processActor.x > 0x7E00) {
+		_engine->_movements->processActor.x = 0x7E00;
 	}
 
-	if (_engine->_movements->processActorZ > 0x7E00) {
-		_engine->_movements->processActorZ = 0x7E00;
+	if (_engine->_movements->processActor.z > 0x7E00) {
+		_engine->_movements->processActor.z = 0x7E00;
 	}
 
-	actor->pos.x = _engine->_movements->processActorX;
-	actor->pos.y = _engine->_movements->processActorY;
-	actor->pos.z = _engine->_movements->processActorZ;
+	actor->pos.x = _engine->_movements->processActor.x;
+	actor->pos.y = _engine->_movements->processActor.y;
+	actor->pos.z = _engine->_movements->processActor.z;
 }
 
 } // namespace TwinE
diff --git a/engines/twine/scene/collision.cpp b/engines/twine/scene/collision.cpp
index 679a27a981..a139693264 100644
--- a/engines/twine/scene/collision.cpp
+++ b/engines/twine/scene/collision.cpp
@@ -45,14 +45,14 @@ bool Collision::standingOnActor(int32 actorIdx1, int32 actorIdx2) {
 	const ActorStruct *actor2 = _engine->_scene->getActor(actorIdx2);
 
 	// Current actor (actor 1)
-	const int32 x1Left = _engine->_movements->processActorX + actor1->boudingBox.x.bottomLeft;
-	const int32 x1Right = _engine->_movements->processActorX + actor1->boudingBox.x.topRight;
+	const int32 x1Left = _engine->_movements->processActor.x + actor1->boudingBox.x.bottomLeft;
+	const int32 x1Right = _engine->_movements->processActor.x + actor1->boudingBox.x.topRight;
 
-	const int32 y1Left = _engine->_movements->processActorY + actor1->boudingBox.y.bottomLeft;
-	const int32 y1Right = _engine->_movements->processActorY + actor1->boudingBox.y.topRight;
+	const int32 y1Left = _engine->_movements->processActor.y + actor1->boudingBox.y.bottomLeft;
+	const int32 y1Right = _engine->_movements->processActor.y + actor1->boudingBox.y.topRight;
 
-	const int32 z1Left = _engine->_movements->processActorZ + actor1->boudingBox.z.bottomLeft;
-	const int32 z1Right = _engine->_movements->processActorZ + actor1->boudingBox.z.topRight;
+	const int32 z1Left = _engine->_movements->processActor.z + actor1->boudingBox.z.bottomLeft;
+	const int32 z1Right = _engine->_movements->processActor.z + actor1->boudingBox.z.topRight;
 
 	// Actor 2
 	const int32 x2Left = actor2->pos.x + actor2->boudingBox.x.bottomLeft;
@@ -120,56 +120,56 @@ void Collision::reajustActorPosition(ShapeType brickShape) {
 	if (brickShape >= ShapeType::kDoubleSideStairsTop1 && brickShape <= ShapeType::kDoubleSideStairsRight2) {
 		switch (brickShape) {
 		case ShapeType::kDoubleSideStairsTop1:
-			if (_engine->_movements->processActorZ - collisionZ <= _engine->_movements->processActorX - collisionX) {
+			if (_engine->_movements->processActor.z - collisionZ <= _engine->_movements->processActor.x - collisionX) {
 				brickShape = ShapeType::kStairsTopLeft;
 			} else {
 				brickShape = ShapeType::kStairsTopRight;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsBottom1:
-			if (_engine->_movements->processActorZ - collisionZ <= _engine->_movements->processActorX - collisionX) {
+			if (_engine->_movements->processActor.z - collisionZ <= _engine->_movements->processActor.x - collisionX) {
 				brickShape = ShapeType::kStairsBottomLeft;
 			} else {
 				brickShape = ShapeType::kStairsBottomRight;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsLeft1:
-			if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
 				brickShape = ShapeType::kStairsTopLeft;
 			} else {
 				brickShape = ShapeType::kStairsBottomLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsRight1:
-			if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
 				brickShape = ShapeType::kStairsTopRight;
 			} else {
 				brickShape = ShapeType::kStairsBottomRight;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsTop2:
-			if (_engine->_movements->processActorX - collisionX >= _engine->_movements->processActorZ - collisionZ) {
+			if (_engine->_movements->processActor.x - collisionX >= _engine->_movements->processActor.z - collisionZ) {
 				brickShape = ShapeType::kStairsTopRight;
 			} else {
 				brickShape = ShapeType::kStairsTopLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsBottom2:
-			if (_engine->_movements->processActorZ - collisionZ <= _engine->_movements->processActorX - collisionX) {
+			if (_engine->_movements->processActor.z - collisionZ <= _engine->_movements->processActor.x - collisionX) {
 				brickShape = ShapeType::kStairsBottomRight;
 			} else {
 				brickShape = ShapeType::kStairsBottomLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsLeft2:
-			if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
 				brickShape = ShapeType::kStairsBottomLeft;
 			} else {
 				brickShape = ShapeType::kStairsTopLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsRight2:
-			if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
 				brickShape = ShapeType::kStairsBottomRight;
 			} else {
 				brickShape = ShapeType::kStairsTopRight;
@@ -186,16 +186,16 @@ void Collision::reajustActorPosition(ShapeType brickShape) {
 	if (brickShape >= ShapeType::kStairsTopLeft && brickShape <= ShapeType::kStairsBottomRight) {
 		switch (brickShape) {
 		case ShapeType::kStairsTopLeft:
-			_engine->_movements->processActorY = brkY + getAverageValue(0, BRICK_HEIGHT, BRICK_SIZE, _engine->_movements->processActorX - brkX);
+			_engine->_movements->processActor.y = brkY + getAverageValue(0, BRICK_HEIGHT, BRICK_SIZE, _engine->_movements->processActor.x - brkX);
 			break;
 		case ShapeType::kStairsTopRight:
-			_engine->_movements->processActorY = brkY + getAverageValue(0, BRICK_HEIGHT, BRICK_SIZE, _engine->_movements->processActorZ - brkZ);
+			_engine->_movements->processActor.y = brkY + getAverageValue(0, BRICK_HEIGHT, BRICK_SIZE, _engine->_movements->processActor.z - brkZ);
 			break;
 		case ShapeType::kStairsBottomLeft:
-			_engine->_movements->processActorY = brkY + getAverageValue(BRICK_HEIGHT, 0, BRICK_SIZE, _engine->_movements->processActorZ - brkZ);
+			_engine->_movements->processActor.y = brkY + getAverageValue(BRICK_HEIGHT, 0, BRICK_SIZE, _engine->_movements->processActor.z - brkZ);
 			break;
 		case ShapeType::kStairsBottomRight:
-			_engine->_movements->processActorY = brkY + getAverageValue(BRICK_HEIGHT, 0, BRICK_SIZE, _engine->_movements->processActorX - brkX);
+			_engine->_movements->processActor.y = brkY + getAverageValue(BRICK_HEIGHT, 0, BRICK_SIZE, _engine->_movements->processActor.x - brkX);
 			break;
 		default:
 			break;
@@ -206,14 +206,14 @@ void Collision::reajustActorPosition(ShapeType brickShape) {
 int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 
-	int32 xLeft = _engine->_movements->processActorX + actor->boudingBox.x.bottomLeft;
-	int32 xRight = _engine->_movements->processActorX + actor->boudingBox.x.topRight;
+	int32 xLeft = _engine->_movements->processActor.x + actor->boudingBox.x.bottomLeft;
+	int32 xRight = _engine->_movements->processActor.x + actor->boudingBox.x.topRight;
 
-	int32 yLeft = _engine->_movements->processActorY + actor->boudingBox.y.bottomLeft;
-	int32 yRight = _engine->_movements->processActorY + actor->boudingBox.y.topRight;
+	int32 yLeft = _engine->_movements->processActor.y + actor->boudingBox.y.bottomLeft;
+	int32 yRight = _engine->_movements->processActor.y + actor->boudingBox.y.topRight;
 
-	int32 zLeft = _engine->_movements->processActorZ + actor->boudingBox.z.bottomLeft;
-	int32 zRight = _engine->_movements->processActorZ + actor->boudingBox.z.topRight;
+	int32 zLeft = _engine->_movements->processActor.z + actor->boudingBox.z.bottomLeft;
+	int32 zRight = _engine->_movements->processActor.z + actor->boudingBox.z.topRight;
 
 	actor->collision = -1;
 
@@ -236,14 +236,14 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 
 				if (actorTest->staticFlags.bIsCarrierActor) {
 					if (actor->dynamicFlags.bIsFalling) {
-						_engine->_movements->processActorY = yRightTest - actor->boudingBox.y.bottomLeft + 1;
+						_engine->_movements->processActor.y = yRightTest - actor->boudingBox.y.bottomLeft + 1;
 						actor->standOn = a;
 					} else {
 						if (standingOnActor(actorIdx, a)) {
-							_engine->_movements->processActorY = yRightTest - actor->boudingBox.y.bottomLeft + 1;
+							_engine->_movements->processActor.y = yRightTest - actor->boudingBox.y.bottomLeft + 1;
 							actor->standOn = a;
 						} else {
-							int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->pos.x, actorTest->pos.z);
+							int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActor.x, _engine->_movements->processActor.z, actorTest->pos.x, actorTest->pos.z);
 
 							if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
 								actorTest->lastPos.y = 0;
@@ -262,30 +262,28 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 										actorTest->lastPos.x = 192;
 									}
 								} else {
-									actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionPos.x;
-									actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionPos.z;
+									actorTest->lastPos.x = _engine->_movements->processActor.x - actor->collisionPos.x;
+									actorTest->lastPos.z = _engine->_movements->processActor.z - actor->collisionPos.z;
 								}
 							}
 
 							if ((actorTest->boudingBox.x.topRight - actorTest->boudingBox.x.bottomLeft == actorTest->boudingBox.z.topRight - actorTest->boudingBox.z.bottomLeft) &&
 							    (actor->boudingBox.x.topRight - actor->boudingBox.x.bottomLeft == actor->boudingBox.z.topRight - actor->boudingBox.z.bottomLeft)) {
 								if (newAngle < ANGLE_135) {
-									_engine->_movements->processActorX = xLeftTest - actor->boudingBox.x.topRight;
+									_engine->_movements->processActor.x = xLeftTest - actor->boudingBox.x.topRight;
 								}
 								if (newAngle >= ANGLE_135 && newAngle < ANGLE_225) {
-									_engine->_movements->processActorZ = zRightTest - actor->boudingBox.z.bottomLeft;
+									_engine->_movements->processActor.z = zRightTest - actor->boudingBox.z.bottomLeft;
 								}
 								if (newAngle >= ANGLE_225 && newAngle < ANGLE_315) {
-									_engine->_movements->processActorX = xRightTest - actor->boudingBox.x.bottomLeft;
+									_engine->_movements->processActor.x = xRightTest - actor->boudingBox.x.bottomLeft;
 								}
 								if (newAngle >= ANGLE_315 || (newAngle < ANGLE_315 && newAngle < ANGLE_45)) {
-									_engine->_movements->processActorZ = zLeftTest - actor->boudingBox.z.topRight;
+									_engine->_movements->processActor.z = zLeftTest - actor->boudingBox.z.topRight;
 								}
 							} else {
 								if (!actor->dynamicFlags.bIsFalling) {
-									_engine->_movements->processActorX = _engine->_movements->previousActorX;
-									_engine->_movements->processActorY = _engine->_movements->previousActorY;
-									_engine->_movements->processActorZ = _engine->_movements->previousActorZ;
+									_engine->_movements->processActor = _engine->_movements->previousActor;
 								}
 							}
 						}
@@ -295,7 +293,7 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 						_engine->_actor->hitActor(actorIdx, a, 1, -1);
 					}
 
-					int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->pos.x, actorTest->pos.z);
+					int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActor.x, _engine->_movements->processActor.z, actorTest->pos.x, actorTest->pos.z);
 
 					if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
 						actorTest->lastPos.y = 0;
@@ -314,30 +312,30 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 								actorTest->lastPos.x = 192;
 							}
 						} else {
-							actorTest->lastPos.x = _engine->_movements->processActorX - actor->collisionPos.x;
-							actorTest->lastPos.z = _engine->_movements->processActorZ - actor->collisionPos.z;
+							actorTest->lastPos.x = _engine->_movements->processActor.x - actor->collisionPos.x;
+							actorTest->lastPos.z = _engine->_movements->processActor.z - actor->collisionPos.z;
 						}
 					}
 
 					if ((actorTest->boudingBox.x.topRight - actorTest->boudingBox.x.bottomLeft == actorTest->boudingBox.z.topRight - actorTest->boudingBox.z.bottomLeft) &&
 					    (actor->boudingBox.x.topRight - actor->boudingBox.x.bottomLeft == actor->boudingBox.z.topRight - actor->boudingBox.z.bottomLeft)) {
 						if (newAngle < ANGLE_135) {
-							_engine->_movements->processActorX = xLeftTest - actor->boudingBox.x.topRight;
+							_engine->_movements->processActor.x = xLeftTest - actor->boudingBox.x.topRight;
 						}
 						if (newAngle >= ANGLE_135 && newAngle < ANGLE_225) {
-							_engine->_movements->processActorZ = zRightTest - actor->boudingBox.z.bottomLeft;
+							_engine->_movements->processActor.z = zRightTest - actor->boudingBox.z.bottomLeft;
 						}
 						if (newAngle >= ANGLE_225 && newAngle < ANGLE_315) {
-							_engine->_movements->processActorX = xRightTest - actor->boudingBox.x.bottomLeft;
+							_engine->_movements->processActor.x = xRightTest - actor->boudingBox.x.bottomLeft;
 						}
 						if (newAngle >= ANGLE_315 || (newAngle < ANGLE_315 && newAngle < ANGLE_45)) {
-							_engine->_movements->processActorZ = zLeftTest - actor->boudingBox.z.topRight;
+							_engine->_movements->processActor.z = zLeftTest - actor->boudingBox.z.topRight;
 						}
 					} else {
 						if (!actor->dynamicFlags.bIsFalling) {
-							_engine->_movements->processActorX = _engine->_movements->previousActorX;
-							_engine->_movements->processActorY = _engine->_movements->previousActorY;
-							_engine->_movements->processActorZ = _engine->_movements->previousActorZ;
+							_engine->_movements->processActor.x = _engine->_movements->previousActor.x;
+							_engine->_movements->processActor.y = _engine->_movements->previousActor.y;
+							_engine->_movements->processActor.z = _engine->_movements->previousActor.z;
 						}
 					}
 				}
@@ -348,14 +346,14 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 	if (actor->dynamicFlags.bIsHitting) {
 		_engine->_movements->rotateActor(0, 200, actor->angle);
 
-		xLeft = _engine->_renderer->destX + _engine->_movements->processActorX + actor->boudingBox.x.bottomLeft;
-		xRight = _engine->_renderer->destX + _engine->_movements->processActorX + actor->boudingBox.x.topRight;
+		xLeft = _engine->_renderer->destX + _engine->_movements->processActor.x + actor->boudingBox.x.bottomLeft;
+		xRight = _engine->_renderer->destX + _engine->_movements->processActor.x + actor->boudingBox.x.topRight;
 
-		yLeft = _engine->_movements->processActorY + actor->boudingBox.y.bottomLeft;
-		yRight = _engine->_movements->processActorY + actor->boudingBox.y.topRight;
+		yLeft = _engine->_movements->processActor.y + actor->boudingBox.y.bottomLeft;
+		yRight = _engine->_movements->processActor.y + actor->boudingBox.y.topRight;
 
-		zLeft = _engine->_renderer->destZ + _engine->_movements->processActorZ + actor->boudingBox.z.bottomLeft;
-		zRight = _engine->_renderer->destZ + _engine->_movements->processActorZ + actor->boudingBox.z.topRight;
+		zLeft = _engine->_renderer->destZ + _engine->_movements->processActor.z + actor->boudingBox.z.bottomLeft;
+		zRight = _engine->_renderer->destZ + _engine->_movements->processActor.z + actor->boudingBox.z.topRight;
 
 		for (int32 a = 0; a < _engine->_scene->sceneNumActors; a++) {
 			const ActorStruct *actorTest = _engine->_scene->getActor(a);
@@ -383,72 +381,72 @@ int32 Collision::checkCollisionWithActors(int32 actorIdx) {
 }
 
 void Collision::checkHeroCollisionWithBricks(int32 x, int32 y, int32 z, int32 damageMask) {
-	ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
+	ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z);
 
-	_engine->_movements->processActorX += x;
-	_engine->_movements->processActorY += y;
-	_engine->_movements->processActorZ += z;
+	_engine->_movements->processActor.x += x;
+	_engine->_movements->processActor.y += y;
+	_engine->_movements->processActor.z += z;
 
-	if (_engine->_movements->processActorX >= 0 && _engine->_movements->processActorZ >= 0 && _engine->_movements->processActorX <= 0x7E00 && _engine->_movements->processActorZ <= 0x7E00) {
+	if (_engine->_movements->processActor.x >= 0 && _engine->_movements->processActor.z >= 0 && _engine->_movements->processActor.x <= 0x7E00 && _engine->_movements->processActor.z <= 0x7E00) {
 		reajustActorPosition(brickShape);
-		brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_actor->processActorPtr->boudingBox.y.topRight);
+		brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 		if (brickShape == ShapeType::kSolid) {
 			causeActorDamage |= damageMask;
-			brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ + z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
+			brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->previousActor.z + z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 			if (brickShape == ShapeType::kSolid) {
-				brickShape = _engine->_grid->getBrickShapeFull(x + _engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_actor->processActorPtr->boudingBox.y.topRight);
+				brickShape = _engine->_grid->getBrickShapeFull(x + _engine->_movements->previousActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 				if (brickShape != ShapeType::kSolid) {
-					processCollisionX = _engine->_movements->previousActorX;
+					processCollisionX = _engine->_movements->previousActor.x;
 				}
 			} else {
-				processCollisionZ = _engine->_movements->previousActorZ;
+				processCollisionZ = _engine->_movements->previousActor.z;
 			}
 		}
 	}
 
-	_engine->_movements->processActorX = processCollisionX;
-	_engine->_movements->processActorY = processCollisionY;
-	_engine->_movements->processActorZ = processCollisionZ;
+	_engine->_movements->processActor.x = processCollisionX;
+	_engine->_movements->processActor.y = processCollisionY;
+	_engine->_movements->processActor.z = processCollisionZ;
 }
 
 void Collision::checkActorCollisionWithBricks(int32 x, int32 y, int32 z, int32 damageMask) {
-	ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
+	ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z);
 
-	_engine->_movements->processActorX += x;
-	_engine->_movements->processActorY += y;
-	_engine->_movements->processActorZ += z;
+	_engine->_movements->processActor.x += x;
+	_engine->_movements->processActor.y += y;
+	_engine->_movements->processActor.z += z;
 
-	if (_engine->_movements->processActorX >= 0 && _engine->_movements->processActorZ >= 0 && _engine->_movements->processActorX <= 0x7E00 && _engine->_movements->processActorZ <= 0x7E00) {
+	if (_engine->_movements->processActor.x >= 0 && _engine->_movements->processActor.z >= 0 && _engine->_movements->processActor.x <= 0x7E00 && _engine->_movements->processActor.z <= 0x7E00) {
 		reajustActorPosition(brickShape);
-		brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
+		brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z);
 
 		if (brickShape == ShapeType::kSolid) {
 			causeActorDamage |= damageMask;
-			brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ + z);
+			brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActor.x, _engine->_movements->processActor.y, _engine->_movements->previousActor.z + z);
 
 			if (brickShape == ShapeType::kSolid) {
-				brickShape = _engine->_grid->getBrickShape(x + _engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
+				brickShape = _engine->_grid->getBrickShape(x + _engine->_movements->previousActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z);
 
 				if (brickShape != ShapeType::kSolid) {
-					processCollisionX = _engine->_movements->previousActorX;
+					processCollisionX = _engine->_movements->previousActor.x;
 				}
 			} else {
-				processCollisionZ = _engine->_movements->previousActorZ;
+				processCollisionZ = _engine->_movements->previousActor.z;
 			}
 		}
 	}
 
-	_engine->_movements->processActorX = processCollisionX;
-	_engine->_movements->processActorY = processCollisionY;
-	_engine->_movements->processActorZ = processCollisionZ;
+	_engine->_movements->processActor.x = processCollisionX;
+	_engine->_movements->processActor.y = processCollisionY;
+	_engine->_movements->processActor.z = processCollisionZ;
 }
 
 void Collision::stopFalling() { // ReceptionObj()
 	if (IS_HERO(_engine->_animations->currentlyProcessedActorIdx)) {
-		const int32 fall = _engine->_scene->heroYBeforeFall - _engine->_movements->processActorY;
+		const int32 fall = _engine->_scene->heroYBeforeFall - _engine->_movements->processActor.y;
 
 		if (fall >= BRICK_HEIGHT * 8) {
 			_engine->_extra->addExtraSpecial(_engine->_actor->processActorPtr->pos.x, _engine->_actor->processActorPtr->pos.y + 1000, _engine->_actor->processActorPtr->pos.z, ExtraSpecialType::kHitStars);
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index fa7e2a1b2c..d577912a69 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -594,7 +594,7 @@ uint8 *Grid::getBlockBuffer(int32 x, int32 y, int32 z) {
 	return blockBuffer + tempY * 2 + tempX * GRID_SIZE_Y * 2 + (tempZ * GRID_SIZE_X) * GRID_SIZE_Y * 2;
 }
 
-const uint8 *Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground) {
+const uint8 *Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int32 &ground) {
 	updateCollisionCoordinates(x, y, z);
 	const int32 tempX = _engine->_collision->collisionX;
 	int32 tempY = _engine->_collision->collisionY;
diff --git a/engines/twine/scene/grid.h b/engines/twine/scene/grid.h
index 2cc1f9be87..3f5625021a 100644
--- a/engines/twine/scene/grid.h
+++ b/engines/twine/scene/grid.h
@@ -194,7 +194,7 @@ public:
 	/**
 	 * search down until either ground is found or lower border of the cube is reached
 	 */
-	const uint8 *getBlockBufferGround(int32 x, int32 y, int32 z, int16 &ground);
+	const uint8 *getBlockBufferGround(int32 x, int32 y, int32 z, int32 &ground);
 
 	/** New grid camera x, y and z coordinates */
 	Vec3 newCamera;
diff --git a/engines/twine/scene/movements.cpp b/engines/twine/scene/movements.cpp
index 5620276bf2..f173f85031 100644
--- a/engines/twine/scene/movements.cpp
+++ b/engines/twine/scene/movements.cpp
@@ -38,9 +38,9 @@ namespace TwinE {
 Movements::Movements(TwinEEngine *engine) : _engine(engine) {}
 
 void Movements::getShadowPosition(int32 x, int32 y, int32 z) {
-	const uint8 *ptr = _engine->_grid->getBlockBufferGround(x, y, z, processActorY);
-	processActorX = x;
-	processActorZ = z;
+	const uint8 *ptr = _engine->_grid->getBlockBufferGround(x, y, z, processActor.y);
+	processActor.x = x;
+	processActor.z = z;
 
 	if (*ptr) {
 		const uint8 *blockPtr = _engine->_grid->getBlockLibrary(*ptr - 1) + 3 + *(ptr + 1) * 4;
@@ -51,9 +51,7 @@ void Movements::getShadowPosition(int32 x, int32 y, int32 z) {
 	}
 	_engine->_collision->reajustActorPosition(_engine->_actor->shadowCollisionType);
 
-	_engine->_actor->shadowCoord.x = processActorX;
-	_engine->_actor->shadowCoord.y = processActorY;
-	_engine->_actor->shadowCoord.z = processActorZ;
+	_engine->_actor->shadowCoord = processActor;
 }
 
 void Movements::setActorAngleSafe(int16 startAngle, int16 endAngle, int16 stepAngle, ActorMoveStruct *movePtr) {
diff --git a/engines/twine/scene/movements.h b/engines/twine/scene/movements.h
index 81357ef918..bc97a39646 100644
--- a/engines/twine/scene/movements.h
+++ b/engines/twine/scene/movements.h
@@ -135,29 +135,21 @@ public:
 	/** Hero moved */
 	bool heroMoved = false; // twinsenMove
 
-	/** Process actor.x coordinate */
-	int16 processActorX = 0;
-	/** Process actor.y coordinate */
-	int16 processActorY = 0;
-	/** Process actor.z coordinate */
-	int16 processActorZ = 0;
-
-	/** Previous process actor.x coordinate */
-	int16 previousActorX = 0; // processActorVar2
-	/** Previous process actor.y coordinate */
-	int16 previousActorY = 0; // processActorVar3
-	/** Previous process actor.z coordinate */
-	int16 previousActorZ = 0; // processActorVar4
+	/** Process actor coordinate */
+	Vec3 processActor;
+
+	/** Previous process actor coordinate */
+	Vec3 previousActor;
 
 	int32 targetActorDistance = 0; // DoTrackVar1
 
 	/**
 	 * Get shadow position
-	 * @param X Shadow X coordinate
-	 * @param Y Shadow Y coordinate
-	 * @param Z Shadow Z coordinate
+	 * @param x Shadow X coordinate
+	 * @param y Shadow Y coordinate
+	 * @param z Shadow Z coordinate
 	 */
-	void getShadowPosition(int32 X, int32 Y, int32 Z);
+	void getShadowPosition(int32 x, int32 y, int32 z);
 
 	/**
 	 * Set actor safe angle
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index 3fbf60358c..bf4d3dfb71 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -719,8 +719,8 @@ void Scene::processActorZones(int32 actorIdx) {
 			case ZoneType::kLadder:
 				if (IS_HERO(actorIdx) && _engine->_actor->heroBehaviour != HeroBehaviourType::kProtoPack && (actor->anim == AnimationTypes::kForward || actor->anim == AnimationTypes::kTopLadder || actor->anim == AnimationTypes::kClimbLadder)) {
 					_engine->_movements->rotateActor(actor->boudingBox.x.bottomLeft, actor->boudingBox.z.bottomLeft, actor->angle + ANGLE_360 + ANGLE_135);
-					_engine->_renderer->destX += _engine->_movements->processActorX;
-					_engine->_renderer->destZ += _engine->_movements->processActorZ;
+					_engine->_renderer->destX += _engine->_movements->processActor.x;
+					_engine->_renderer->destZ += _engine->_movements->processActor.z;
 
 					if (_engine->_renderer->destX >= 0 && _engine->_renderer->destZ >= 0 && _engine->_renderer->destX <= 0x7E00 && _engine->_renderer->destZ <= 0x7E00) {
 						if (_engine->_grid->getBrickShape(_engine->_renderer->destX, actor->pos.y + ANGLE_90, _engine->_renderer->destZ) != ShapeType::kNone) {


Commit: ec340779065e7e0822595553e114cf0a2ae574a2
    https://github.com/scummvm/scummvm/commit/ec340779065e7e0822595553e114cf0a2ae574a2
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:27:37+01:00

Commit Message:
TWINE: converted more positions to Vec3

Changed paths:
    engines/twine/scene/animations.cpp
    engines/twine/scene/collision.cpp
    engines/twine/scene/collision.h
    engines/twine/scene/extra.cpp
    engines/twine/scene/grid.cpp
    engines/twine/shared.h


diff --git a/engines/twine/scene/animations.cpp b/engines/twine/scene/animations.cpp
index 43d9c8cbc5..ac96ab8325 100644
--- a/engines/twine/scene/animations.cpp
+++ b/engines/twine/scene/animations.cpp
@@ -695,13 +695,8 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 	// actor standing on another actor
 	if (actor->standOn != -1) {
 		const ActorStruct *standOnActor = _engine->_scene->getActor(actor->standOn);
-		_engine->_movements->processActor.x -= standOnActor->collisionPos.x;
-		_engine->_movements->processActor.y -= standOnActor->collisionPos.y;
-		_engine->_movements->processActor.z -= standOnActor->collisionPos.z;
-
-		_engine->_movements->processActor.x += standOnActor->pos.x;
-		_engine->_movements->processActor.y += standOnActor->pos.y;
-		_engine->_movements->processActor.z += standOnActor->pos.z;
+		_engine->_movements->processActor -= standOnActor->collisionPos;
+		_engine->_movements->processActor += standOnActor->pos;
 
 		if (!_engine->_collision->standingOnActor(actorIdx, actor->standOn)) {
 			actor->standOn = -1; // no longer standing on other actor
@@ -717,7 +712,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 	// actor collisions with bricks
 	if (actor->staticFlags.bComputeCollisionWithBricks) {
-		_engine->_collision->collisionY = 0;
+		_engine->_collision->collision.y = 0;
 
 		ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->previousActor.x, _engine->_movements->previousActor.y, _engine->_movements->previousActor.z);
 
@@ -739,9 +734,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 
 		_engine->_collision->causeActorDamage = 0;
 
-		_engine->_collision->processCollisionX = _engine->_movements->processActor.x;
-		_engine->_collision->processCollisionY = _engine->_movements->processActor.y;
-		_engine->_collision->processCollisionZ = _engine->_movements->processActor.z;
+		_engine->_collision->processCollision = _engine->_movements->processActor;
 
 		if (IS_HERO(actorIdx) && !actor->staticFlags.bComputeLowCollision) {
 			// check hero collisions with bricks
@@ -785,7 +778,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			if (brickShape == ShapeType::kSolid) {
 				if (actor->dynamicFlags.bIsFalling) {
 					_engine->_collision->stopFalling();
-					_engine->_movements->processActor.y = (_engine->_collision->collisionY * BRICK_HEIGHT) + BRICK_HEIGHT;
+					_engine->_movements->processActor.y = (_engine->_collision->collision.y * BRICK_HEIGHT) + BRICK_HEIGHT;
 				} else {
 					if (IS_HERO(actorIdx) && _engine->_actor->heroBehaviour == HeroBehaviourType::kAthletic && actor->anim == AnimationTypes::kForward && _engine->cfgfile.WallCollision) { // avoid wall hit damage
 						_engine->_extra->addExtraSpecial(actor->pos.x, actor->pos.y + 1000, actor->pos.z, ExtraSpecialType::kHitStars);
@@ -844,7 +837,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		}
 
 		// if under the map, than die
-		if (_engine->_collision->collisionY == -1) {
+		if (_engine->_collision->collision.y == -1) {
 			actor->life = 0;
 		}
 	} else {
diff --git a/engines/twine/scene/collision.cpp b/engines/twine/scene/collision.cpp
index a139693264..154523c2f2 100644
--- a/engines/twine/scene/collision.cpp
+++ b/engines/twine/scene/collision.cpp
@@ -112,64 +112,64 @@ void Collision::reajustActorPosition(ShapeType brickShape) {
 		return;
 	}
 
-	const int32 brkX = (collisionX * BRICK_SIZE) - BRICK_HEIGHT;
-	const int32 brkY = collisionY * BRICK_HEIGHT;
-	const int32 brkZ = (collisionZ * BRICK_SIZE) - BRICK_HEIGHT;
+	const int32 brkX = (collision.x * BRICK_SIZE) - BRICK_HEIGHT;
+	const int32 brkY = collision.y * BRICK_HEIGHT;
+	const int32 brkZ = (collision.z * BRICK_SIZE) - BRICK_HEIGHT;
 
 	// double-side stairs
 	if (brickShape >= ShapeType::kDoubleSideStairsTop1 && brickShape <= ShapeType::kDoubleSideStairsRight2) {
 		switch (brickShape) {
 		case ShapeType::kDoubleSideStairsTop1:
-			if (_engine->_movements->processActor.z - collisionZ <= _engine->_movements->processActor.x - collisionX) {
+			if (_engine->_movements->processActor.z - collision.z <= _engine->_movements->processActor.x - collision.x) {
 				brickShape = ShapeType::kStairsTopLeft;
 			} else {
 				brickShape = ShapeType::kStairsTopRight;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsBottom1:
-			if (_engine->_movements->processActor.z - collisionZ <= _engine->_movements->processActor.x - collisionX) {
+			if (_engine->_movements->processActor.z - collision.z <= _engine->_movements->processActor.x - collision.x) {
 				brickShape = ShapeType::kStairsBottomLeft;
 			} else {
 				brickShape = ShapeType::kStairsBottomRight;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsLeft1:
-			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collision.x <= _engine->_movements->processActor.z - collision.z) {
 				brickShape = ShapeType::kStairsTopLeft;
 			} else {
 				brickShape = ShapeType::kStairsBottomLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsRight1:
-			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collision.x <= _engine->_movements->processActor.z - collision.z) {
 				brickShape = ShapeType::kStairsTopRight;
 			} else {
 				brickShape = ShapeType::kStairsBottomRight;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsTop2:
-			if (_engine->_movements->processActor.x - collisionX >= _engine->_movements->processActor.z - collisionZ) {
+			if (_engine->_movements->processActor.x - collision.x >= _engine->_movements->processActor.z - collision.z) {
 				brickShape = ShapeType::kStairsTopRight;
 			} else {
 				brickShape = ShapeType::kStairsTopLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsBottom2:
-			if (_engine->_movements->processActor.z - collisionZ <= _engine->_movements->processActor.x - collisionX) {
+			if (_engine->_movements->processActor.z - collision.z <= _engine->_movements->processActor.x - collision.x) {
 				brickShape = ShapeType::kStairsBottomRight;
 			} else {
 				brickShape = ShapeType::kStairsBottomLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsLeft2:
-			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collision.x <= _engine->_movements->processActor.z - collision.z) {
 				brickShape = ShapeType::kStairsBottomLeft;
 			} else {
 				brickShape = ShapeType::kStairsTopLeft;
 			}
 			break;
 		case ShapeType::kDoubleSideStairsRight2:
-			if (512 - _engine->_movements->processActor.x - collisionX <= _engine->_movements->processActor.z - collisionZ) {
+			if (512 - _engine->_movements->processActor.x - collision.x <= _engine->_movements->processActor.z - collision.z) {
 				brickShape = ShapeType::kStairsBottomRight;
 			} else {
 				brickShape = ShapeType::kStairsTopRight;
@@ -399,17 +399,15 @@ void Collision::checkHeroCollisionWithBricks(int32 x, int32 y, int32 z, int32 da
 				brickShape = _engine->_grid->getBrickShapeFull(x + _engine->_movements->previousActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
 
 				if (brickShape != ShapeType::kSolid) {
-					processCollisionX = _engine->_movements->previousActor.x;
+					processCollision.x = _engine->_movements->previousActor.x;
 				}
 			} else {
-				processCollisionZ = _engine->_movements->previousActor.z;
+				processCollision.z = _engine->_movements->previousActor.z;
 			}
 		}
 	}
 
-	_engine->_movements->processActor.x = processCollisionX;
-	_engine->_movements->processActor.y = processCollisionY;
-	_engine->_movements->processActor.z = processCollisionZ;
+	_engine->_movements->processActor = processCollision;
 }
 
 void Collision::checkActorCollisionWithBricks(int32 x, int32 y, int32 z, int32 damageMask) {
@@ -431,17 +429,15 @@ void Collision::checkActorCollisionWithBricks(int32 x, int32 y, int32 z, int32 d
 				brickShape = _engine->_grid->getBrickShape(x + _engine->_movements->previousActor.x, _engine->_movements->processActor.y, _engine->_movements->processActor.z);
 
 				if (brickShape != ShapeType::kSolid) {
-					processCollisionX = _engine->_movements->previousActor.x;
+					processCollision.x = _engine->_movements->previousActor.x;
 				}
 			} else {
-				processCollisionZ = _engine->_movements->previousActor.z;
+				processCollision.z = _engine->_movements->previousActor.z;
 			}
 		}
 	}
 
-	_engine->_movements->processActor.x = processCollisionX;
-	_engine->_movements->processActor.y = processCollisionY;
-	_engine->_movements->processActor.z = processCollisionZ;
+	_engine->_movements->processActor = processCollision;
 }
 
 void Collision::stopFalling() { // ReceptionObj()
diff --git a/engines/twine/scene/collision.h b/engines/twine/scene/collision.h
index 346bd07b83..b1e3b4e84e 100644
--- a/engines/twine/scene/collision.h
+++ b/engines/twine/scene/collision.h
@@ -36,19 +36,11 @@ private:
 
 public:
 	Collision(TwinEEngine *engine);
-	/** Actor collition X coordinate */
-	int32 collisionX = 0; // getPosVar1
-	/** Actor collition Y coordinate */
-	int32 collisionY = 0; // getPosVar2
-	/** Actor collition Z coordinate */
-	int32 collisionZ = 0; // getPosVar3
-
-	/** Actor collition X coordinate */
-	int32 processCollisionX = 0; // processActorVar11
-	/** Actor collition Y coordinate */
-	int32 processCollisionY = 0; // processActorVar12
-	/** Actor collition Z coordinate */
-	int32 processCollisionZ = 0; // processActorVar13
+	/** Actor collision coordinate */
+	Vec3 collision;
+
+	/** Actor collision coordinate */
+	Vec3 processCollision;
 
 	/** Cause damage in current processed actor */
 	int32 causeActorDamage = 0; //fieldCauseDamage
diff --git a/engines/twine/scene/extra.cpp b/engines/twine/scene/extra.cpp
index 9304eac910..46eeb48006 100644
--- a/engines/twine/scene/extra.cpp
+++ b/engines/twine/scene/extra.cpp
@@ -859,7 +859,7 @@ void Extra::processExtras() {
 
 			if (process) {
 				const BoundingBox *bbox = _engine->_resources->spriteBoundingBox.bbox(extra->info0);
-				extra->y = (_engine->_collision->collisionY * BRICK_HEIGHT) + BRICK_HEIGHT - bbox->mins.y;
+				extra->y = (_engine->_collision->collision.y * BRICK_HEIGHT) + BRICK_HEIGHT - bbox->mins.y;
 				extra->type &= ~(ExtraType::STOP_COL | ExtraType::FLY);
 				continue;
 			}
diff --git a/engines/twine/scene/grid.cpp b/engines/twine/scene/grid.cpp
index d577912a69..ed47d14cc8 100644
--- a/engines/twine/scene/grid.cpp
+++ b/engines/twine/scene/grid.cpp
@@ -596,9 +596,9 @@ uint8 *Grid::getBlockBuffer(int32 x, int32 y, int32 z) {
 
 const uint8 *Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int32 &ground) {
 	updateCollisionCoordinates(x, y, z);
-	const int32 tempX = _engine->_collision->collisionX;
-	int32 tempY = _engine->_collision->collisionY;
-	const int32 tempZ = _engine->_collision->collisionZ;
+	const int32 tempX = _engine->_collision->collision.x;
+	int32 tempY = _engine->_collision->collision.y;
+	const int32 tempZ = _engine->_collision->collision.z;
 	const uint8 *ptr = blockBuffer + tempY * 2 + tempX * GRID_SIZE_Y * 2 + (tempZ * GRID_SIZE_X) * GRID_SIZE_Y * 2;
 
 	while (tempY) {
@@ -609,7 +609,7 @@ const uint8 *Grid::getBlockBufferGround(int32 x, int32 y, int32 z, int32 &ground
 		ptr -= 2;
 	}
 
-	_engine->_collision->collisionY = tempY;
+	_engine->_collision->collision.y = tempY;
 	ground = (int16)((tempY + 1) * BRICK_HEIGHT);
 
 	return ptr;
@@ -707,22 +707,22 @@ void Grid::redrawGrid() {
 ShapeType Grid::getBrickShape(int32 x, int32 y, int32 z) {
 	updateCollisionCoordinates(x, y, z);
 
-	if (_engine->_collision->collisionX < 0 || _engine->_collision->collisionX >= GRID_SIZE_X) {
+	if (_engine->_collision->collision.x < 0 || _engine->_collision->collision.x >= GRID_SIZE_X) {
 		return ShapeType::kNone;
 	}
 
-	if (_engine->_collision->collisionY <= -1) {
+	if (_engine->_collision->collision.y <= -1) {
 		return ShapeType::kSolid;
 	}
 
-	if (_engine->_collision->collisionY < 0 || _engine->_collision->collisionY >= GRID_SIZE_Y || _engine->_collision->collisionZ < 0 || _engine->_collision->collisionZ >= GRID_SIZE_Z) {
+	if (_engine->_collision->collision.y < 0 || _engine->_collision->collision.y >= GRID_SIZE_Y || _engine->_collision->collision.z < 0 || _engine->_collision->collision.z >= GRID_SIZE_Z) {
 		return ShapeType::kNone;
 	}
 
 	uint8 *blockBufferPtr = blockBuffer;
-	blockBufferPtr += _engine->_collision->collisionX * GRID_SIZE_Y * 2;
-	blockBufferPtr += _engine->_collision->collisionY * 2;
-	blockBufferPtr += (_engine->_collision->collisionZ * GRID_SIZE_X * 2) * GRID_SIZE_Y;
+	blockBufferPtr += _engine->_collision->collision.x * GRID_SIZE_Y * 2;
+	blockBufferPtr += _engine->_collision->collision.y * 2;
+	blockBufferPtr += (_engine->_collision->collision.z * GRID_SIZE_X * 2) * GRID_SIZE_Y;
 
 	uint8 blockIdx = *blockBufferPtr;
 
@@ -741,30 +741,30 @@ ShapeType Grid::getBrickShape(int32 x, int32 y, int32 z) {
 }
 
 void Grid::updateCollisionCoordinates(int32 x, int32 y, int32 z) {
-	_engine->_collision->collisionX = (x + BRICK_HEIGHT) / BRICK_SIZE;
-	_engine->_collision->collisionY = y / BRICK_HEIGHT;
-	_engine->_collision->collisionZ = (z + BRICK_HEIGHT) / BRICK_SIZE;
+	_engine->_collision->collision.x = (x + BRICK_HEIGHT) / BRICK_SIZE;
+	_engine->_collision->collision.y = y / BRICK_HEIGHT;
+	_engine->_collision->collision.z = (z + BRICK_HEIGHT) / BRICK_SIZE;
 }
 
 ShapeType Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 	updateCollisionCoordinates(x, y, z);
 
-	if (_engine->_collision->collisionX < 0 || _engine->_collision->collisionX >= GRID_SIZE_X) {
+	if (_engine->_collision->collision.x < 0 || _engine->_collision->collision.x >= GRID_SIZE_X) {
 		return ShapeType::kNone;
 	}
 
-	if (_engine->_collision->collisionY <= -1) {
+	if (_engine->_collision->collision.y <= -1) {
 		return ShapeType::kSolid;
 	}
 
-	if (_engine->_collision->collisionY < 0 || _engine->_collision->collisionY >= GRID_SIZE_Y || _engine->_collision->collisionZ < 0 || _engine->_collision->collisionZ >= GRID_SIZE_Z) {
+	if (_engine->_collision->collision.y < 0 || _engine->_collision->collision.y >= GRID_SIZE_Y || _engine->_collision->collision.z < 0 || _engine->_collision->collision.z >= GRID_SIZE_Z) {
 		return ShapeType::kNone;
 	}
 
 	uint8 *blockBufferPtr = blockBuffer;
-	blockBufferPtr += _engine->_collision->collisionX * GRID_SIZE_Y * 2;
-	blockBufferPtr += _engine->_collision->collisionY * 2;
-	blockBufferPtr += (_engine->_collision->collisionZ * GRID_SIZE_X * 2) * GRID_SIZE_Y;
+	blockBufferPtr += _engine->_collision->collision.x * GRID_SIZE_Y * 2;
+	blockBufferPtr += _engine->_collision->collision.y * 2;
+	blockBufferPtr += (_engine->_collision->collision.z * GRID_SIZE_X * 2) * GRID_SIZE_Y;
 
 	uint8 blockIdx = *blockBufferPtr;
 
@@ -780,7 +780,7 @@ ShapeType Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 		const ShapeType brickShape = (ShapeType)*blockPtr;
 
 		const int32 newY = (y2 + (BRICK_HEIGHT - 1)) / BRICK_HEIGHT;
-		int32 currY = _engine->_collision->collisionY;
+		int32 currY = _engine->_collision->collision.y;
 
 		for (int32 i = 0; i < newY; i++) {
 			if (currY >= GRID_SIZE_Y) {
@@ -800,7 +800,7 @@ ShapeType Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 	const ShapeType brickShape = (ShapeType) * (blockBufferPtr + 1);
 
 	const int32 newY = (y2 + (BRICK_HEIGHT - 1)) / BRICK_HEIGHT;
-	int32 currY = _engine->_collision->collisionY;
+	int32 currY = _engine->_collision->collision.y;
 
 	for (int32 i = 0; i < newY; i++) {
 		if (currY >= GRID_SIZE_Y) {
@@ -821,22 +821,22 @@ ShapeType Grid::getBrickShapeFull(int32 x, int32 y, int32 z, int32 y2) {
 int32 Grid::getBrickSoundType(int32 x, int32 y, int32 z) { // getPos2
 	updateCollisionCoordinates(x, y, z);
 
-	if (_engine->_collision->collisionX < 0 || _engine->_collision->collisionX >= GRID_SIZE_X) {
+	if (_engine->_collision->collision.x < 0 || _engine->_collision->collision.x >= GRID_SIZE_X) {
 		return 0; // none
 	}
 
-	if (_engine->_collision->collisionY <= -1) {
+	if (_engine->_collision->collision.y <= -1) {
 		return 1; // solid
 	}
 
-	if (_engine->_collision->collisionY < 0 || _engine->_collision->collisionY >= GRID_SIZE_Y || _engine->_collision->collisionZ < 0 || _engine->_collision->collisionZ >= GRID_SIZE_Z) {
+	if (_engine->_collision->collision.y < 0 || _engine->_collision->collision.y >= GRID_SIZE_Y || _engine->_collision->collision.z < 0 || _engine->_collision->collision.z >= GRID_SIZE_Z) {
 		return 0; // none
 	}
 
 	const uint8 *blockBufferPtr = blockBuffer;
-	blockBufferPtr += _engine->_collision->collisionX * GRID_SIZE_Y * 2;
-	blockBufferPtr += _engine->_collision->collisionY * 2;
-	blockBufferPtr += (_engine->_collision->collisionZ * GRID_SIZE_X * 2) * GRID_SIZE_Y;
+	blockBufferPtr += _engine->_collision->collision.x * GRID_SIZE_Y * 2;
+	blockBufferPtr += _engine->_collision->collision.y * 2;
+	blockBufferPtr += (_engine->_collision->collision.z * GRID_SIZE_X * 2) * GRID_SIZE_Y;
 
 	uint8 blockIdx = *blockBufferPtr;
 
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 9d96fb619a..674c1ed334 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -36,6 +36,20 @@ struct Vec3 {
 	int32 x;
 	int32 y;
 	int32 z;
+
+	inline Vec3& operator+=(const Vec3 &other) {
+		x += other.x;
+		y += other.y;
+		z += other.z;
+		return *this;
+	}
+
+	inline Vec3& operator-=(const Vec3 &other) {
+		x -= other.x;
+		y -= other.y;
+		z -= other.z;
+		return *this;
+	}
 };
 
 struct BoundingBox {


Commit: 87893749b5a159551ddf4157102450d67f8c9beb
    https://github.com/scummvm/scummvm/commit/87893749b5a159551ddf4157102450d67f8c9beb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:30:47+01:00

Commit Message:
TWINE: new color constant

Changed paths:
    engines/twine/scene/extra.cpp
    engines/twine/text.h


diff --git a/engines/twine/scene/extra.cpp b/engines/twine/scene/extra.cpp
index 46eeb48006..2b557dcc61 100644
--- a/engines/twine/scene/extra.cpp
+++ b/engines/twine/scene/extra.cpp
@@ -693,7 +693,7 @@ void Extra::processExtras() {
 
 				if (extraKey->info1 > 1) {
 					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->camera.x, extraKey->y - _engine->_grid->camera.y, extraKey->z - _engine->_grid->camera.z);
-					_engine->_redraw->addOverlay(OverlayType::koNumber, extraKey->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, 0, OverlayPosType::koNormal, 2);
+					_engine->_redraw->addOverlay(OverlayType::koNumber, extraKey->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, COLOR_BLACK, OverlayPosType::koNormal, 2);
 				}
 
 				_engine->_redraw->addOverlay(OverlayType::koSprite, SPRITEHQR_KEY, 10, 30, 0, OverlayPosType::koNormal, 2);
@@ -726,7 +726,7 @@ void Extra::processExtras() {
 
 				if (extraKey->info1 > 1) {
 					_engine->_renderer->projectPositionOnScreen(extraKey->x - _engine->_grid->camera.x, extraKey->y - _engine->_grid->camera.y, extraKey->z - _engine->_grid->camera.z);
-					_engine->_redraw->addOverlay(OverlayType::koNumber, extraKey->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, 0, OverlayPosType::koNormal, 2);
+					_engine->_redraw->addOverlay(OverlayType::koNumber, extraKey->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, COLOR_BLACK, OverlayPosType::koNormal, 2);
 				}
 
 				_engine->_redraw->addOverlay(OverlayType::koSprite, SPRITEHQR_KEY, 10, 30, 0, OverlayPosType::koNormal, 2);
@@ -872,7 +872,7 @@ void Extra::processExtras() {
 
 				if (extra->info1 > 1 && !_engine->_input->isActionActive(TwinEActionType::MoveBackward)) {
 					_engine->_renderer->projectPositionOnScreen(extra->x - _engine->_grid->camera.x, extra->y - _engine->_grid->camera.y, extra->z - _engine->_grid->camera.z);
-					const int16 fontColor = 158;
+					const int16 fontColor = COLOR_158;
 					_engine->_redraw->addOverlay(OverlayType::koNumber, extra->info1, _engine->_renderer->projPosX, _engine->_renderer->projPosY, fontColor, OverlayPosType::koNormal, 2);
 				}
 
diff --git a/engines/twine/text.h b/engines/twine/text.h
index e9b28b3fd5..08f79de891 100644
--- a/engines/twine/text.h
+++ b/engines/twine/text.h
@@ -119,6 +119,7 @@ enum _TextId {
 #define COLOR_BRIGHT_BLUE2 69
 #define COLOR_WHITE 15
 #define COLOR_GOLD 155
+#define COLOR_158 158
 
 enum class ProgressiveTextState {
 	End = 0,				/**< Text has reached its end and we are waiting for user input */


Commit: 290b5de7e43c5c09066c87d1d37c3c265b11cb24
    https://github.com/scummvm/scummvm/commit/290b5de7e43c5c09066c87d1d37c3c265b11cb24
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:34:10+01:00

Commit Message:
TWINE: converted hero position to Vec3 struct

Changed paths:
    engines/twine/scene/gamestate.cpp
    engines/twine/scene/scene.cpp
    engines/twine/scene/scene.h
    engines/twine/script/script_life_v1.cpp
    engines/twine/twine.cpp


diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index 23f2a60f03..572c82cc0f 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -114,9 +114,9 @@ void GameState::initEngineVars() {
 	initGameStateVars();
 	initHeroVars();
 
-	_engine->_scene->newHeroX = 0x2000;
-	_engine->_scene->newHeroY = 0x1800;
-	_engine->_scene->newHeroZ = 0x2000;
+	_engine->_scene->newHeroPos.x = 0x2000;
+	_engine->_scene->newHeroPos.y = 0x1800;
+	_engine->_scene->newHeroPos.z = 0x2000;
 
 	_engine->_scene->currentSceneIdx = -1;
 	_engine->_scene->needChangeScene = LBA1SceneId::Citadel_Island_Prison;
@@ -192,9 +192,9 @@ bool GameState::loadGame(Common::SeekableReadStream *file) {
 	magicLevelIdx = file->readByte();
 	inventoryMagicPoints = file->readByte();
 	inventoryNumLeafsBox = file->readByte();
-	_engine->_scene->newHeroX = file->readSint16LE();
-	_engine->_scene->newHeroY = file->readSint16LE();
-	_engine->_scene->newHeroZ = file->readSint16LE();
+	_engine->_scene->newHeroPos.x = file->readSint16LE();
+	_engine->_scene->newHeroPos.y = file->readSint16LE();
+	_engine->_scene->newHeroPos.z = file->readSint16LE();
 	_engine->_scene->sceneHero->angle = ToAngle(file->readSint16LE());
 	_engine->_actor->previousHeroAngle = _engine->_scene->sceneHero->angle;
 	_engine->_scene->sceneHero->body = (BodyType)file->readByte();
@@ -239,7 +239,7 @@ bool GameState::saveGame(Common::WriteStream *file) {
 	if (sceneIdx == Polar_Island_end_scene || sceneIdx == Citadel_Island_end_sequence_1 || sceneIdx == Citadel_Island_end_sequence_2 || sceneIdx == Credits_List_Sequence) {
 		/* inventoryMagicPoints = 0x50 */
 		/* herobehaviour = 0 */
-		/* newherox = 0xffff */
+		/* newheropos.x = 0xffff */
 		sceneIdx = Polar_Island_Final_Battle;
 	}
 
@@ -260,9 +260,9 @@ bool GameState::saveGame(Common::WriteStream *file) {
 	file->writeByte(inventoryNumLeafsBox);
 	// we don't save the whole scene state - so we have to make sure that the hero is
 	// respawned at the start of the scene - and not at its current position
-	file->writeSint16LE(_engine->_scene->newHeroX);
-	file->writeSint16LE(_engine->_scene->newHeroY);
-	file->writeSint16LE(_engine->_scene->newHeroZ);
+	file->writeSint16LE(_engine->_scene->newHeroPos.x);
+	file->writeSint16LE(_engine->_scene->newHeroPos.y);
+	file->writeSint16LE(_engine->_scene->newHeroPos.z);
 	file->writeSint16LE(FromAngle(_engine->_scene->sceneHero->angle));
 	file->writeByte((uint8)_engine->_scene->sceneHero->body);
 
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index bf4d3dfb71..24fc22aa2d 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -499,20 +499,20 @@ void Scene::changeScene() {
 	_engine->_grid->initGrid(needChangeScene);
 
 	if (heroPositionType == ScenePositionType::kZone) {
-		newHeroX = _zoneHeroX;
-		newHeroY = _zoneHeroY;
-		newHeroZ = _zoneHeroZ;
+		newHeroPos.x = _zoneHeroX;
+		newHeroPos.y = _zoneHeroY;
+		newHeroPos.z = _zoneHeroZ;
 	}
 
 	if (heroPositionType == ScenePositionType::kScene || heroPositionType == ScenePositionType::kNoPosition) {
-		newHeroX = _sceneHeroX;
-		newHeroY = _sceneHeroY;
-		newHeroZ = _sceneHeroZ;
+		newHeroPos.x = _sceneHeroX;
+		newHeroPos.y = _sceneHeroY;
+		newHeroPos.z = _sceneHeroZ;
 	}
 
-	sceneHero->pos.x = newHeroX;
-	sceneHero->pos.y = heroYBeforeFall = newHeroY;
-	sceneHero->pos.z = newHeroZ;
+	sceneHero->pos.x = newHeroPos.x;
+	sceneHero->pos.y = heroYBeforeFall = newHeroPos.y;
+	sceneHero->pos.z = newHeroPos.z;
 
 	_engine->_renderer->setLightVector(alphaLight, betaLight, ANGLE_0);
 
diff --git a/engines/twine/scene/scene.h b/engines/twine/scene/scene.h
index 9c6da43a22..a1340e7aa1 100644
--- a/engines/twine/scene/scene.h
+++ b/engines/twine/scene/scene.h
@@ -327,9 +327,7 @@ public:
 	int32 alphaLight = ANGLE_0;
 	int32 betaLight = ANGLE_0;
 
-	int16 newHeroX = 0; // newTwinsenX
-	int16 newHeroY = 0; // newTwinsenY
-	int16 newHeroZ = 0; // newTwinsenZ
+	Vec3 newHeroPos;
 
 	/** Hero Y coordinate before fall */
 	int16 heroYBeforeFall = 0;
diff --git a/engines/twine/script/script_life_v1.cpp b/engines/twine/script/script_life_v1.cpp
index 1e3eed962a..e5b7894c46 100644
--- a/engines/twine/script/script_life_v1.cpp
+++ b/engines/twine/script/script_life_v1.cpp
@@ -1666,7 +1666,7 @@ static int32 lTHE_END(TwinEEngine *engine, LifeScriptContext &ctx) {
 	engine->_gameState->inventoryMagicPoints = 80;
 	engine->_scene->currentSceneIdx = LBA1SceneId::Polar_Island_Final_Battle;
 	engine->_actor->heroBehaviour = engine->_actor->previousHeroBehaviour;
-	engine->_scene->newHeroX = -1;
+	engine->_scene->newHeroPos.x = -1;
 	engine->_scene->sceneHero->angle = engine->_actor->previousHeroAngle;
 	engine->autoSave();
 	return 1; // break;
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 7ab9c77bca..44a9ec948f 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -263,7 +263,7 @@ Common::Error TwinEEngine::run() {
 		}
 		case EngineState::LoadedGame:
 			debug("Loaded game");
-			if (_scene->newHeroX == -1) {
+			if (_scene->newHeroPos.x == -1) {
 				_scene->heroPositionType = ScenePositionType::kNoPosition;
 			}
 			_text->renderTextTriangle = false;
@@ -927,9 +927,9 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 			if (IS_HERO(a)) {
 				if (actor->dynamicFlags.bAnimEnded) {
 					if (_gameState->inventoryNumLeafs > 0) { // use clover leaf automaticaly
-						_scene->sceneHero->pos.x = _scene->newHeroX;
-						_scene->sceneHero->pos.y = _scene->newHeroY;
-						_scene->sceneHero->pos.z = _scene->newHeroZ;
+						_scene->sceneHero->pos.x = _scene->newHeroPos.x;
+						_scene->sceneHero->pos.y = _scene->newHeroPos.y;
+						_scene->sceneHero->pos.z = _scene->newHeroPos.z;
 
 						_scene->needChangeScene = _scene->currentSceneIdx;
 						_gameState->inventoryMagicPoints = _gameState->magicLevelIdx * 20;
@@ -952,9 +952,9 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 						actor->life = 50;
 
 						if (_scene->previousSceneIdx != _scene->currentSceneIdx) {
-							_scene->newHeroX = -1;
-							_scene->newHeroY = -1;
-							_scene->newHeroZ = -1;
+							_scene->newHeroPos.x = -1;
+							_scene->newHeroPos.y = -1;
+							_scene->newHeroPos.z = -1;
 							_scene->currentSceneIdx = _scene->previousSceneIdx;
 							_scene->stopRunningGame();
 						}


Commit: baadba59a809ba3f5d2f144b7d89bdadbfa4a9f4
    https://github.com/scummvm/scummvm/commit/baadba59a809ba3f5d2f144b7d89bdadbfa4a9f4
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:38:27+01:00

Commit Message:
TWINE: use Vec3 copy

Changed paths:
    engines/twine/scene/animations.cpp


diff --git a/engines/twine/scene/animations.cpp b/engines/twine/scene/animations.cpp
index ac96ab8325..bb060ffbc5 100644
--- a/engines/twine/scene/animations.cpp
+++ b/engines/twine/scene/animations.cpp
@@ -516,18 +516,14 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		return;
 	}
 
-	_engine->_movements->previousActor.x = actor->collisionPos.x;
-	_engine->_movements->previousActor.y = actor->collisionPos.y;
-	_engine->_movements->previousActor.z = actor->collisionPos.z;
+	_engine->_movements->previousActor = actor->collisionPos;
 
 	if (actor->staticFlags.bIsSpriteActor) { // is sprite actor
 		if (actor->strengthOfHit) {
 			actor->dynamicFlags.bIsHitting = 1;
 		}
 
-		_engine->_movements->processActor.x = actor->pos.x;
-		_engine->_movements->processActor.y = actor->pos.y;
-		_engine->_movements->processActor.z = actor->pos.z;
+		_engine->_movements->processActor = actor->pos;
 
 		if (!actor->dynamicFlags.bIsFalling) {
 			if (actor->speed) {
@@ -589,9 +585,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 						}
 
 						if (updatePos) {
-							_engine->_movements->processActor.x = actor->lastPos.x;
-							_engine->_movements->processActor.y = actor->lastPos.y;
-							_engine->_movements->processActor.z = actor->lastPos.z;
+							_engine->_movements->processActor = actor->lastPos;
 
 							actor->dynamicFlags.bIsSpriteMoving = 0;
 							actor->speed = 0;
@@ -601,9 +595,7 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 			}
 
 			if (actor->staticFlags.bCanBePushed) {
-				_engine->_movements->processActor.x += actor->lastPos.x;
-				_engine->_movements->processActor.y += actor->lastPos.y;
-				_engine->_movements->processActor.z += actor->lastPos.z;
+				_engine->_movements->processActor += actor->lastPos;
 
 				if (actor->staticFlags.bUseMiniZv) {
 					_engine->_movements->processActor.x = ((_engine->_movements->processActor.x / 128) * 128);
@@ -863,17 +855,15 @@ void Animations::processActorAnimations(int32 actorIdx) { // DoAnim
 		_engine->_movements->processActor.z = 0;
 	}
 
-	if (_engine->_movements->processActor.x > 0x7E00) {
+	if (_engine->_movements->processActor.x > 0x7E00) { // SCENE_SIZE_MAX
 		_engine->_movements->processActor.x = 0x7E00;
 	}
 
-	if (_engine->_movements->processActor.z > 0x7E00) {
+	if (_engine->_movements->processActor.z > 0x7E00) { // SCENE_SIZE_MAX
 		_engine->_movements->processActor.z = 0x7E00;
 	}
 
-	actor->pos.x = _engine->_movements->processActor.x;
-	actor->pos.y = _engine->_movements->processActor.y;
-	actor->pos.z = _engine->_movements->processActor.z;
+	actor->pos = _engine->_movements->processActor;
 }
 
 } // namespace TwinE


Commit: 2d3bd0bfb9c104aa900dce107bed4948afafad4e
    https://github.com/scummvm/scummvm/commit/2d3bd0bfb9c104aa900dce107bed4948afafad4e
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:43:06+01:00

Commit Message:
TWINE: converted scene hero positions to Vec3 struct

Changed paths:
    engines/twine/scene/actor.cpp
    engines/twine/scene/scene.cpp
    engines/twine/scene/scene.h


diff --git a/engines/twine/scene/actor.cpp b/engines/twine/scene/actor.cpp
index 5d7a7aba0c..29bbfc3391 100644
--- a/engines/twine/scene/actor.cpp
+++ b/engines/twine/scene/actor.cpp
@@ -464,7 +464,7 @@ void Actor::processActorExtraBonus(int32 actorIdx) { // GiveExtraBonus
 	}
 	if (actor->dynamicFlags.bIsDead) {
 		_engine->_extra->addExtraBonus(actor->pos.x, actor->pos.y, actor->pos.z, ANGLE_90, ANGLE_0, bonusSprite, actor->bonusAmount);
-		_engine->_sound->playSample(Samples::ItemPopup, 1, actor->pos.x, actor->pos.y, actor->pos.z, actorIdx);
+		_engine->_sound->playSample(Samples::ItemPopup, 1, actor->pos, actorIdx);
 	} else {
 		ActorStruct *sceneHero = _engine->_scene->sceneHero;
 		const int32 angle = _engine->_movements->getAngleAndSetTargetActorDistance(actor->pos.x, actor->pos.z, sceneHero->pos.x, sceneHero->pos.z);
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index 24fc22aa2d..158078d8df 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -173,9 +173,9 @@ bool Scene::loadSceneLBA2() {
 	_sceneMusic = stream.readByte();
 
 	// load hero properties
-	_sceneHeroX = stream.readSint16LE();
-	_sceneHeroY = stream.readSint16LE();
-	_sceneHeroZ = stream.readSint16LE();
+	_sceneHeroPos.x = stream.readSint16LE();
+	_sceneHeroPos.y = stream.readSint16LE();
+	_sceneHeroPos.z = stream.readSint16LE();
 
 	sceneHero->moveScriptSize = stream.readUint16LE();
 	sceneHero->moveScript = currentScene + stream.pos();
@@ -305,9 +305,9 @@ bool Scene::loadSceneLBA1() {
 	_sceneMusic = stream.readByte();
 
 	// load hero properties
-	_sceneHeroX = stream.readUint16LE();
-	_sceneHeroY = stream.readUint16LE();
-	_sceneHeroZ = stream.readUint16LE();
+	_sceneHeroPos.x = stream.readUint16LE();
+	_sceneHeroPos.y = stream.readUint16LE();
+	_sceneHeroPos.z = stream.readUint16LE();
 
 	sceneHero->moveScriptSize = stream.readUint16LE();
 	sceneHero->moveScript = currentScene + stream.pos();
@@ -499,15 +499,11 @@ void Scene::changeScene() {
 	_engine->_grid->initGrid(needChangeScene);
 
 	if (heroPositionType == ScenePositionType::kZone) {
-		newHeroPos.x = _zoneHeroX;
-		newHeroPos.y = _zoneHeroY;
-		newHeroPos.z = _zoneHeroZ;
+		newHeroPos = _zoneHeroPos;
 	}
 
 	if (heroPositionType == ScenePositionType::kScene || heroPositionType == ScenePositionType::kNoPosition) {
-		newHeroPos.x = _sceneHeroX;
-		newHeroPos.y = _sceneHeroY;
-		newHeroPos.z = _sceneHeroZ;
+		newHeroPos = _sceneHeroPos;
 	}
 
 	sceneHero->pos.x = newHeroPos.x;
@@ -665,9 +661,9 @@ void Scene::processActorZones(int32 actorIdx) {
 			case ZoneType::kCube:
 				if (IS_HERO(actorIdx) && actor->life > 0) {
 					needChangeScene = zone->infoData.ChangeScene.newSceneIdx;
-					_zoneHeroX = actor->pos.x - zone->bottomLeft.x + zone->infoData.ChangeScene.x;
-					_zoneHeroY = actor->pos.y - zone->bottomLeft.y + zone->infoData.ChangeScene.y;
-					_zoneHeroZ = actor->pos.z - zone->bottomLeft.z + zone->infoData.ChangeScene.z;
+					_zoneHeroPos.x = actor->pos.x - zone->bottomLeft.x + zone->infoData.ChangeScene.x;
+					_zoneHeroPos.y = actor->pos.y - zone->bottomLeft.y + zone->infoData.ChangeScene.y;
+					_zoneHeroPos.z = actor->pos.z - zone->bottomLeft.z + zone->infoData.ChangeScene.z;
 					heroPositionType = ScenePositionType::kZone;
 				}
 				break;
diff --git a/engines/twine/scene/scene.h b/engines/twine/scene/scene.h
index a1340e7aa1..474e5da02e 100644
--- a/engines/twine/scene/scene.h
+++ b/engines/twine/scene/scene.h
@@ -299,13 +299,9 @@ private:
 
 	int16 _sceneMusic = 0;
 
-	int16 _sceneHeroX = 0; // newTwinsenXByScene
-	int16 _sceneHeroY = 0; // newTwinsenYByScene
-	int16 _sceneHeroZ = 0; // newTwinsenZByScene
+	Vec3 _sceneHeroPos;
+	Vec3 _zoneHeroPos;
 
-	int16 _zoneHeroX = 0; // newTwinsenXByZone
-	int16 _zoneHeroY = 0; // newTwinsenYByZone
-	int16 _zoneHeroZ = 0; // newTwinsenZByZone
 	int32 _currentGameOverScene = 0;
 
 public:


Commit: 010dccc785a86301aca93ba396103017373dd888
    https://github.com/scummvm/scummvm/commit/010dccc785a86301aca93ba396103017373dd888
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T17:52:13+01:00

Commit Message:
TWINE: added projectPositionOnScreen Vec3 variant

Changed paths:
    engines/twine/renderer/redraw.cpp
    engines/twine/renderer/renderer.h
    engines/twine/shared.h
    engines/twine/twine.cpp


diff --git a/engines/twine/renderer/redraw.cpp b/engines/twine/renderer/redraw.cpp
index c65ad62c2e..199eaf5cc0 100644
--- a/engines/twine/renderer/redraw.cpp
+++ b/engines/twine/renderer/redraw.cpp
@@ -200,7 +200,7 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 		// no redraw required
 		if (actor->staticFlags.bIsBackgrounded && !bgRedraw) {
 			// get actor position on screen
-			_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
+			_engine->_renderer->projectPositionOnScreen(actor->pos - _engine->_grid->camera);
 
 			// check if actor is visible on screen, otherwise don't display it
 			if (_engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100) {
@@ -213,7 +213,7 @@ int32 Redraw::fillActorDrawingList(bool bgRedraw) {
 			continue;
 		}
 		// get actor position on screen
-		_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
+		_engine->_renderer->projectPositionOnScreen(actor->pos - _engine->_grid->camera);
 
 		if ((actor->staticFlags.bUsesClipping && _engine->_renderer->projPosX > -112 && _engine->_renderer->projPosX < _engine->width() + 112 && _engine->_renderer->projPosY > -50 && _engine->_renderer->projPosY < _engine->height() + 171) ||
 		    ((!actor->staticFlags.bUsesClipping) && _engine->_renderer->projPosX > -50 && _engine->_renderer->projPosX < _engine->width() + 40 && _engine->_renderer->projPosY > -30 && _engine->_renderer->projPosY < _engine->height() + 100)) {
@@ -406,7 +406,7 @@ void Redraw::processDrawListActorSprites(const DrawListStruct &drawCmd, bool bgR
 	const uint8 *spritePtr = _engine->_resources->spriteTable[actor->entity];
 
 	// get actor position on screen
-	_engine->_renderer->projectPositionOnScreen(actor->pos.x - _engine->_grid->camera.x, actor->pos.y - _engine->_grid->camera.y, actor->pos.z - _engine->_grid->camera.z);
+	_engine->_renderer->projectPositionOnScreen(actor->pos - _engine->_grid->camera);
 
 	const int32 spriteWidth = spriteData.surface().w;
 	const int32 spriteHeight = spriteData.surface().h;
diff --git a/engines/twine/renderer/renderer.h b/engines/twine/renderer/renderer.h
index 3dc3b1a8fa..82764df6bb 100644
--- a/engines/twine/renderer/renderer.h
+++ b/engines/twine/renderer/renderer.h
@@ -421,6 +421,10 @@ public:
 	static void prepareIsoModel(uint8 *bodyPtr);
 	void renderPolygons(const CmdRenderPolygon &polygon, Vertex *vertices);
 
+	inline int32 projectPositionOnScreen(const Vec3& pos) {
+		return projectPositionOnScreen(pos.x, pos.y, pos.z);
+	}
+
 	int32 projectPositionOnScreen(int32 cX, int32 cY, int32 cZ);
 	void setCameraPosition(int32 x, int32 y, int32 depthOffset, int32 scaleY, int32 scaleZ);
 	void setCameraAngle(int32 transPosX, int32 transPosY, int32 transPosZ, int32 rotPosX, int32 rotPosY, int32 rotPosZ, int32 param6);
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 674c1ed334..0b0aef5d45 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -52,6 +52,14 @@ struct Vec3 {
 	}
 };
 
+inline Vec3 operator+(const Vec3 &lhs, const Vec3 &rhs) {
+	return Vec3{lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z};
+}
+
+inline Vec3 operator-(const Vec3 &lhs, const Vec3 &rhs) {
+	return Vec3{lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z};
+}
+
 struct BoundingBox {
 	Vec3 mins;
 	Vec3 maxs;
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 44a9ec948f..02f407b2ec 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -901,10 +901,10 @@ int32 TwinEEngine::runGameEngine() { // mainLoopInteration
 						if (_actor->heroBehaviour != HeroBehaviourType::kProtoPack || actor->anim != AnimationTypes::kForward) {
 							if (!_actor->cropBottomScreen) {
 								_animations->initAnim(AnimationTypes::kDrawn, kAnimationType_4, AnimationTypes::kStanding, 0);
-								_renderer->projectPositionOnScreen(actor->pos.x - _grid->camera.x, actor->pos.y - _grid->camera.y, actor->pos.z - _grid->camera.z);
+								_renderer->projectPositionOnScreen(actor->pos - _grid->camera);
 								_actor->cropBottomScreen = _renderer->projPosY;
 							}
-							_renderer->projectPositionOnScreen(actor->pos.x - _grid->camera.x, actor->pos.y - _grid->camera.y, actor->pos.z - _grid->camera.z);
+							_renderer->projectPositionOnScreen(actor->pos - _grid->camera);
 							actor->controlMode = ControlMode::kNoMove;
 							actor->life = -1;
 							_actor->cropBottomScreen = _renderer->projPosY;


Commit: e3d413d2fe88b4b93e9c0e662e3e2fa711a0b0d3
    https://github.com/scummvm/scummvm/commit/e3d413d2fe88b4b93e9c0e662e3e2fa711a0b0d3
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T19:22:38+01:00

Commit Message:
TWINE: added debug command set_life

Changed paths:
    engines/twine/debugger/console.cpp
    engines/twine/debugger/console.h


diff --git a/engines/twine/debugger/console.cpp b/engines/twine/debugger/console.cpp
index f7e42609a1..e826349f7e 100644
--- a/engines/twine/debugger/console.cpp
+++ b/engines/twine/debugger/console.cpp
@@ -54,6 +54,7 @@ TwinEConsole::TwinEConsole(TwinEEngine *engine) : _engine(engine), GUI::Debugger
 	registerCmd("toggle_scenechanges", WRAP_METHOD(TwinEConsole, doToggleSceneChanges));
 	registerCmd("scene_actor", WRAP_METHOD(TwinEConsole, doSkipSceneActorsBut));
 	registerCmd("hero_pos", WRAP_METHOD(TwinEConsole, doSetHeroPosition));
+	registerCmd("set_life", WRAP_METHOD(TwinEConsole, doSetLife));
 	registerCmd("set_game_flag", WRAP_METHOD(TwinEConsole, doSetGameFlag));
 	registerCmd("show_game_flag", WRAP_METHOD(TwinEConsole, doPrintGameFlag));
 	registerCmd("set_inventory_flag", WRAP_METHOD(TwinEConsole, doSetInventoryFlag));
@@ -423,4 +424,16 @@ bool TwinEConsole::doGiveAllItems(int argc, const char **argv) {
 	return true;
 }
 
+bool TwinEConsole::doSetLife(int argc, const char **argv) {
+	if (argc <= 1) {
+		debugPrintf("Expected to get the life points as parameter\n");
+		return true;
+	}
+	_engine->_scene->sceneHero->life = atoi(argv[1]);
+	if (_engine->_scene->sceneHero->life > 50) {
+		_engine->_scene->sceneHero->life = 50;
+	}
+	return true;
+}
+
 } // End of namespace TwinE
diff --git a/engines/twine/debugger/console.h b/engines/twine/debugger/console.h
index 9ad3d5a0b9..c42c98c300 100644
--- a/engines/twine/debugger/console.h
+++ b/engines/twine/debugger/console.h
@@ -41,6 +41,7 @@ private:
 	bool doPrintHolomapFlag(int argc, const char **argv);
 	bool doSetHeroPosition(int argc, const char **argv);
 	bool doGiveItem(int argc, const char **argv);
+	bool doSetLife(int argc, const char **argv);
 	bool doGiveAllItems(int argc, const char **argv);
 	bool doChangeScene(int argc, const char **argv);
 	bool doListMenuText(int argc, const char **argv);


Commit: ca3375e7b44a7b8c370573100c9207bc0e28ecf1
    https://github.com/scummvm/scummvm/commit/ca3375e7b44a7b8c370573100c9207bc0e28ecf1
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T19:22:49+01:00

Commit Message:
TWINE: don't close the debug console for invalid parameters

Changed paths:
    engines/twine/debugger/console.cpp


diff --git a/engines/twine/debugger/console.cpp b/engines/twine/debugger/console.cpp
index e826349f7e..177a3cd441 100644
--- a/engines/twine/debugger/console.cpp
+++ b/engines/twine/debugger/console.cpp
@@ -97,7 +97,7 @@ bool TwinEConsole::doToggleSceneryView(int argc, const char **argv) {
 bool TwinEConsole::doAddMagicPoints(int argc, const char **argv) {
 	if (argc < 2) {
 		debugPrintf("Usage: specify the magic points\n");
-		return false;
+		return true;
 	}
 	const int16 magicPoints = atoi(argv[1]);
 	_engine->_gameState->magicLevelIdx = CLIP<int16>(magicPoints, 0, 4);
@@ -108,7 +108,7 @@ bool TwinEConsole::doAddMagicPoints(int argc, const char **argv) {
 bool TwinEConsole::doSkipSceneActorsBut(int argc, const char **argv) {
 	if (argc < 2) {
 		debugPrintf("Usage: give actor id of scene or -1 to disable\n");
-		return false;
+		return true;
 	}
 	const int16 actorIdx = atoi(argv[1]);
 	debugPrintf("Only load actor %d in the next scene\n", actorIdx);


Commit: 2f62076720a3811629dfafc5e00d65265a6a304c
    https://github.com/scummvm/scummvm/commit/2f62076720a3811629dfafc5e00d65265a6a304c
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T19:23:09+01:00

Commit Message:
TWINE: re-added constants for original window dimensions

Changed paths:
    engines/twine/twine.cpp


diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 02f407b2ec..219a90f60d 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -73,6 +73,9 @@
 #include "twine/script/script_move_v1.h"
 #include "twine/text.h"
 
+#define ORIGINAL_WIDTH 640
+#define ORIGINAL_HEIGHT 480
+
 namespace TwinE {
 
 ScopedEngineFreeze::ScopedEngineFreeze(TwinEEngine *engine) : _engine(engine) {
@@ -223,8 +226,8 @@ Common::Error TwinEEngine::run() {
 	debug("(c) 1994 by Adeline Software International, All Rights Reserved.");
 
 	syncSoundSettings();
-	int32 w = 640;
-	int32 h = 480;
+	int32 w = ORIGINAL_WIDTH;
+	int32 h = ORIGINAL_HEIGHT;
 	if (ConfMan.hasKey("usehighres")) {
 		const bool highRes = ConfMan.getBool("usehighres");
 		if (highRes) {
@@ -356,7 +359,7 @@ void TwinEEngine::autoSave() {
 void TwinEEngine::allocVideoMemory(int32 w, int32 h) {
 	const Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
 
-	imageBuffer.create(640, 480, format); // original lba1 resolution for a lot of images.
+	imageBuffer.create(ORIGINAL_WIDTH, ORIGINAL_HEIGHT, format); // original lba1 resolution for a lot of images.
 
 	workVideoBuffer.create(w, h, format);
 	frontVideoBuffer.create(w, h, format);


Commit: 097b9192959b0c109309777fd70edf9aa0a41e5d
    https://github.com/scummvm/scummvm/commit/097b9192959b0c109309777fd70edf9aa0a41e5d
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2021-02-25T19:34:36+01:00

Commit Message:
TWINE: fixed position of game-over animation in high-res mode

Changed paths:
    engines/twine/scene/gamestate.cpp
    engines/twine/twine.cpp
    engines/twine/twine.h


diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index 572c82cc0f..e41a6d436a 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -500,16 +500,12 @@ void GameState::processGameoverAnimation() {
 		return;
 	}
 
-	const int32 left = 120;
-	const int32 top = 120;
-	const int32 right = 519;
-	const int32 bottom = 359;
-	const Common::Rect rect(left, top, right, bottom);
 	Renderer::prepareIsoModel(gameOverPtr);
 	_engine->_sound->stopSamples();
 	_engine->_music->stopMidiMusic(); // stop fade music
 	_engine->_renderer->setCameraPosition(_engine->width() / 2, _engine->height() / 2, 128, 200, 200);
 	int32 startLbaTime = _engine->lbaTime;
+	const Common::Rect &rect = _engine->centerOnScreen(_engine->width() / 2, _engine->height() / 2);
 	_engine->_interface->setClip(rect);
 
 	while (!_engine->_input->toggleAbortAction() && (_engine->lbaTime - startLbaTime) <= 500) {
diff --git a/engines/twine/twine.cpp b/engines/twine/twine.cpp
index 219a90f60d..1dde5bcbdf 100644
--- a/engines/twine/twine.cpp
+++ b/engines/twine/twine.cpp
@@ -1162,4 +1162,12 @@ bool TwinEEngine::unlockAchievement(const Common::String &id) {
 	return AchMan.setAchievement(id, msg);
 }
 
+Common::Rect TwinEEngine::centerOnScreen(int32 w, int32 h) const {
+	const int32 left = width() / 2 - w / 2;
+	const int32 right = left + w;
+	const int32 top = height() / 2 - h / 2;
+	const int32 bottom = top + h;
+	return Common::Rect(left, top, right, bottom);
+}
+
 } // namespace TwinE
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index bdb6e6391a..ff745c5131 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -264,6 +264,7 @@ public:
 	int width() const;
 	int height() const;
 	Common::Rect rect() const;
+	Common::Rect centerOnScreen(int32 w, int32 h) const;
 
 	void initSceneryView();
 	void exitSceneryView();




More information about the Scummvm-git-logs mailing list