[Scummvm-git-logs] scummvm master -> 9f1b8658295963017520a74dfc2c7202a22b747e

neuromancer noreply at scummvm.org
Wed May 17 08:11:12 UTC 2023


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

Summary:
2e45130a70 MATH: added function to obtain size of AABBs
9ac9b0b6a4 FREESCAPE: new collision code
1fc9f7f300 FREESCAPE: remove spaces from area name when displaying info menu in driller
406ea4c395 FREESCAPE: make sure end game area is properly renderer in driller
04b70217b1 FREESCAPE: palette fixes for driller cpc
3961413046 FREESCAPE: color remap fixes for driller cpc/amiga/atari
334339c0c1 FREESCAPE: info menu fixes for driller zx/amiga/atari
783e057538 FREESCAPE: added missing items for driller cga palettes
2c33d94aca FREESCAPE: improved handling of entrance usage
3f44942adc FREESCAPE: improved handling of rise/fall
9f1b865829 FREESCAPE: initial parsing and rendering of group objects


Commit: 2e45130a70611fde552e28ba2378e5b15eff845d
    https://github.com/scummvm/scummvm/commit/2e45130a70611fde552e28ba2378e5b15eff845d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
MATH: added function to obtain size of AABBs

Changed paths:
    math/aabb.h


diff --git a/math/aabb.h b/math/aabb.h
index 8c80e12ef72..e49411693fe 100644
--- a/math/aabb.h
+++ b/math/aabb.h
@@ -38,6 +38,7 @@ public:
 	void transform(const Math::Matrix4 &matrix);
 	Math::Vector3d getMin() const { return _min; }
 	Math::Vector3d getMax() const { return _max; }
+	Math::Vector3d getSize() const { return _max - _min; }
 	bool isValid() const { return _valid; }
 	bool collides(const AABB &aabb);
 


Commit: 9ac9b0b6a4ff1bb00ae28e498394c38f234868c2
    https://github.com/scummvm/scummvm/commit/9ac9b0b6a4ff1bb00ae28e498394c38f234868c2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
FREESCAPE: new collision code

Changed paths:
    engines/freescape/area.cpp
    engines/freescape/area.h
    engines/freescape/freescape.h
    engines/freescape/movement.cpp


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index ac168712e88..df1339e9db4 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -258,6 +258,121 @@ ObjectArray Area::checkCollisions(const Math::AABB &boundingBox) {
 	return collided;
 }
 
+float lineToPlane(Math::Vector3d const &p, Math::Vector3d const &u,  Math::Vector3d const &v, Math::Vector3d const &n) {
+	float NdotU = n.dotProduct(u);
+	if (NdotU == 0)
+		return INFINITY;
+
+	return n.dotProduct(v - p) / NdotU;
+}
+
+bool between(float x, float a, float b) {
+	return x >= a && x <= b;
+}
+
+float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &direction, Math::Vector3d &normal) {
+	Math::Vector3d m = b.getMin() - a.getMax();
+	Math::Vector3d mh = a.getSize() + b.getSize();
+
+	float h = 1.0;
+	float s = 0.0;
+	Math::Vector3d zero;
+
+	// X min
+	s = lineToPlane(zero, direction, m, Math::Vector3d(-1, 0, 0));
+	if (s >= 0 && direction.x() > 0 && s < h && between(s * direction.y(), m.y(), m.y()+mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(-1, 0, 0);
+	}
+
+	// X max
+	m.x() = m.x() + mh.x();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(1, 0, 0));
+	if (s >= 0 && direction.x() < 0 && s < h && between(s * direction.y(), m.y(), m.y() + mh.y()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(1, 0, 0);
+	}
+
+	m.x() = m.x() - mh.x();
+	// Y min
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, -1, 0));
+	if (s >= 0 && direction.y() > 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(0, -1, 0);
+	}
+
+	// Y max
+	m.y() = m.y() + mh.y();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 1, 0));
+	if (s >= 0 && direction.y() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.z(), m.z(), m.z() + mh.z())) {
+		h = s;
+		normal = Math::Vector3d(0, 1, 0);
+	}
+
+	m.y() = m.y() - mh.y();
+
+	// Z min
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, -1));
+	if (s >= 0 && direction.z() > 0 && s < h && between(s * direction.x(), m.x() , m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
+		h = s;
+		normal = Math::Vector3d(0, 0, -1);
+	}
+
+	// Z max
+	m.z() = m.z() + mh.z();
+	s = lineToPlane(zero, direction, m, Math::Vector3d(0, 0, 1));
+	if (s >= 0 && direction.z() < 0 && s < h && between(s * direction.x(), m.x(), m.x() + mh.x()) && between(s * direction.y(), m.y(), m.y() + mh.y())) {
+		h = s;
+		normal = Math::Vector3d(0, 0, 1);
+	}
+
+	//debug("%f", h);
+	return h;
+}
+
+Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight) {
+	Math::AABB boundingBox(position, position);
+
+	Math::Vector3d v1(position.x() + 1, position.y() + 1, position.z() + 1);
+	Math::Vector3d v2(position.x() - 1, position.y() - playerHeight, position.z() - 1);
+
+	boundingBox.expand(v1);
+	boundingBox.expand(v2);
+	return boundingBox;
+}
+
+Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, const Math::Vector3d &newPosition_, int playerHeight) {
+	Math::Vector3d position = newPosition_;
+	Math::Vector3d lastPosition = lastPosition_;
+
+	float epsilon = 1.5;
+	int i = 0;
+	while (true) {
+		float distance = 1.0;
+		Math::Vector3d normal;
+		Math::Vector3d direction = position - lastPosition;
+
+		Math::AABB boundingBox = createPlayerAABB(lastPosition, playerHeight);
+		for (auto &obj : _drawableObjects) {
+			if (!obj->isDestroyed() && !obj->isInvisible()) {
+				GeometricObject *gobj = (GeometricObject *)obj;
+				Math::Vector3d collidedNormal;
+				float collidedDistance = sweepAABB(boundingBox, gobj->_boundingBox, direction, collidedNormal);
+				if (collidedDistance < distance) {
+					distance = collidedDistance;
+					normal = collidedNormal;
+				}
+			}
+		}
+		position = lastPosition + distance * direction + epsilon * normal;
+		if (distance >= 1.0)
+			break;
+		i++;
+		assert(i <= 5);
+	}
+	return position;
+}
+
 bool Area::checkInSight(const Math::Ray &ray, float maxDistance) {
 	Math::Vector3d direction = ray.getDirection();
 	direction.normalize();
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index 294b73a5c88..a6fa1e2fdc7 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -55,6 +55,7 @@ public:
 	Object *shootRay(const Math::Ray &ray);
 	bool checkInSight(const Math::Ray &ray, float maxDistance);
 	ObjectArray checkCollisions(const Math::AABB &boundingBox);
+	Math::Vector3d resolveCollisions(Math::Vector3d const &lastPosition, Math::Vector3d const &newPosition, int playerHeight);
 	void addObjectFromArea(int16 id, Area *global);
 	void addObject(Object *obj);
 	void addFloor();
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 97b00b2d94e..6e3d666dec9 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -225,6 +225,7 @@ public:
 	virtual void pressedKey(const int keycode);
 	virtual bool onScreenControls(Common::Point mouse);
 	void move(CameraMovement direction, uint8 scale, float deltaTime);
+	void resolveCollisions(Math::Vector3d newPosition);
 	virtual void checkIfStillInArea();
 	void changePlayerHeight(int index);
 	void increaseStepSize();
@@ -275,7 +276,7 @@ public:
 	Common::Array<Common::String> _conditionSources;
 	Common::Array<FCLInstructionVector> _conditions;
 
-	bool checkCollisions(bool executeCode);
+	void runCollisionConditions(Math::Vector3d const lastPosition, Math::Vector3d const newPosition);
 	Math::Vector3d _objExecutingCodeSize;
 	virtual void executeMovementConditions();
 	void executeObjectConditions(GeometricObject *obj, bool shot, bool collided, bool activated);
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 7d89bafe446..e5245723426 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -158,7 +158,7 @@ void FreescapeEngine::rise() {
 		changePlayerHeight(_playerHeightNumber);
 	}
 
-	bool collided = checkCollisions(true) || _position.y() >= 2016;
+	bool collided = /*checkCollisions(true) ||*/ _position.y() >= 2016;
 	if (collided) {
 		if (_currentArea->getAreaID() == previousAreaID) {
 			if (_flyMode)
@@ -181,7 +181,7 @@ void FreescapeEngine::lower() {
 
 	if (_flyMode) {
 		_position.setValue(1, _position.y() - (_playerSteps[_playerStepIndex] * 0.5));
-		bool collided = checkCollisions(true);
+		bool collided = false; //checkCollisions(true);
 		if (collided) {
 			if (_currentArea->getAreaID() == previousAreaID) {
 				_position = _lastPosition;
@@ -222,21 +222,26 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 	stepFront.z() = floor(stepFront.z()) + 0.5;
 
 	float positionY = _position.y();
+	Math::Vector3d destination;
 	switch (direction) {
 	case kForwardMovement:
-		_position = _position + stepFront;
+		destination = _position + stepFront;
 		break;
 	case kBackwardMovement:
-		_position = _position - stepFront;
+		destination = _position - stepFront;
 		break;
 	case kRightMovement:
-		_position = _position - stepRight;
+		destination = _position - stepRight;
 		break;
 	case kLeftMovement:
-		_position = _position + stepRight;
+		destination = _position + stepRight;
 		break;
 	}
 
+	if (!_flyMode)
+		destination.y() = positionY;
+	resolveCollisions(destination);
+	/*
 	// restore y coordinate
 	if (!_flyMode)
 		_position.set(_position.x(), positionY, _position.z());
@@ -306,6 +311,7 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 			}
 		}
 	}
+	*/
 
 	_lastPosition = _position;
 	debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
@@ -315,66 +321,64 @@ void FreescapeEngine::move(CameraMovement direction, uint8 scale, float deltaTim
 	clearGameBit(31);
 }
 
-bool FreescapeEngine::checkFloor(Math::Vector3d currentPosition) {
-	debugC(1, kFreescapeDebugMove, "Checking floor under the player");
-	bool collided = checkCollisions(false);
-	assert(!collided);
+void FreescapeEngine::resolveCollisions(Math::Vector3d const position) {
+	Math::Vector3d newPosition = position;
+	Math::Vector3d lastPosition = _lastPosition;
 
-	_position.set(_position.x(), _position.y() - 2, _position.z());
-	collided = checkCollisions(false);
-	_position = currentPosition;
-	return collided;
-}
+	int previousAreaID = _currentArea->getAreaID();
+	runCollisionConditions(lastPosition, newPosition);
+	if (_currentArea->getAreaID() != previousAreaID) {
+		return;
+	}
 
-bool FreescapeEngine::tryStepUp(Math::Vector3d currentPosition) {
-	debugC(1, kFreescapeDebugMove, "Try to step up!");
-	_position.set(_position.x(), _position.y() + 64, _position.z());
-	bool collided = checkCollisions(false);
-	if (collided) {
-		_position = currentPosition;
-		return false;
-	} else {
-		// Try to step down
-		return true;
+	newPosition = _currentArea->resolveCollisions(lastPosition, newPosition, _playerHeight);
+
+	if (_flyMode) {
+		_position = newPosition;
+		return;
 	}
-}
 
-bool FreescapeEngine::tryStepDown(Math::Vector3d currentPosition) {
-	debugC(1, kFreescapeDebugMove, "Try to step down!");
-	_position.set(_position.x(), _position.y() - 1, _position.z());
-	if (checkFloor(_position)) {
-		return true;
-	} else {
-		_position = currentPosition;
-		return false;
+	if ((lastPosition - newPosition).length() < 1) { // If the player has not moved
+		// Try to step up
+		newPosition = position;
+		newPosition.y() = newPosition.y() + 64;
+
+		lastPosition = _lastPosition;
+		lastPosition.y() = lastPosition.y() + 64;
+
+		newPosition = _currentArea->resolveCollisions(lastPosition, newPosition, _playerHeight);
 	}
-}
 
-bool FreescapeEngine::checkCollisions(bool executeCode) {
-	if (_noClipMode)
-		return false;
-	Math::AABB boundingBox(_lastPosition, _lastPosition);
+	/*if ((lastPosition - newPosition).length() >= 1) { // Step up
+		playSound(4, false);
+	}*/
 
-	Math::Vector3d v1(_position.x() + 1, _position.y() + 1, _position.z() + 1);
-	Math::Vector3d v2(_position.x() - 1, _position.y() - _playerHeight, _position.z() - 1);
+	lastPosition = newPosition;
+	newPosition.y() = -8192;
+	newPosition = _currentArea->resolveCollisions(lastPosition, newPosition, _playerHeight);
+	int fallen = lastPosition.y() - newPosition.y();
 
-	boundingBox.expand(v1);
-	boundingBox.expand(v2);
-	ObjectArray objs = _currentArea->checkCollisions(boundingBox);
-	bool collided = !objs.empty();
+	if (fallen > 64)
+		_hasFallen = !_disableFalling;
 
-	// If we don't need to execute code, we can finish here
-	if (!executeCode) {
-		return collided;
+	if (!_hasFallen && fallen > 0) {
+		// Position in Y was changed, let's re-run effects
+		runCollisionConditions(lastPosition, newPosition);
 	}
+	_position = newPosition;
+}
+
+void FreescapeEngine::runCollisionConditions(Math::Vector3d const lastPosition, Math::Vector3d const newPosition) {
+	if (_noClipMode)
+		return;
 
-	// If we need to execute code, we need to make sure the bounding box touches the floor
-	// so we will expand it and re-run the collision checking
-	uint tolerance = 1;
-	Math::Vector3d v3(_position.x() - 1, _position.y() - _playerHeight - tolerance, _position.z() - 1);
-	boundingBox.expand(v3);
+	// We need to make sure the bounding box touches the floor so we will expand it and run the collision checking
+	uint tolerance = 3;
+	Math::Vector3d v(newPosition.x() - 1, newPosition.y() - _playerHeight - tolerance, newPosition.z() - 1);
+	Math::AABB boundingBox(lastPosition, lastPosition);
+	boundingBox.expand(v);
 
-	objs = _currentArea->checkCollisions(boundingBox);
+	ObjectArray objs = _currentArea->checkCollisions(boundingBox);
 
 	// sort so the condition from those objects that are larger are executed last
 	struct {
@@ -393,7 +397,7 @@ bool FreescapeEngine::checkCollisions(bool executeCode) {
 		// The following check stops the player from going through big solid objects such as walls
 		// FIXME: find a better workaround of this
 		if (gobj->getSize().length() > 3000) {
-			if (largeObjectWasBlocking)
+			if (largeObjectWasBlocking && !(isDriller() && _currentArea->getAreaID() == 14))
 				continue;
 			largeObjectWasBlocking = true;
 		}
@@ -403,9 +407,6 @@ bool FreescapeEngine::checkCollisions(bool executeCode) {
 		if (areaID != _currentArea->getAreaID())
 			break;
 	}
-	// We still need to return the original result, not the collision using the expanded bounding box
-	// This will avoid detecting the floor constantly
-	return collided;
 }
 
 } // namespace Freescape


Commit: 1fc9f7f300b5dd4dc7c70a39ccd99c487ae1a838
    https://github.com/scummvm/scummvm/commit/1fc9f7f300b5dd4dc7c70a39ccd99c487ae1a838
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
FREESCAPE: remove spaces from area name when displaying info menu in driller

Changed paths:
    engines/freescape/games/driller/driller.cpp


diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 902354fcce9..42708de1e9f 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -245,7 +245,10 @@ void DrillerEngine::drawInfoMenu() {
 	_gfx->readFromPalette(color, r, g, b);
 	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
-	drawStringInSurface(Common::String::format("%10s : %s", "sector", _currentArea->_name.c_str()), 69, 25, front, black, surface);
+	Common::String areaName = _currentArea->_name;
+	areaName.trim();
+
+	drawStringInSurface(Common::String::format("%10s : %s", "sector", areaName.c_str()), 69, 25, front, black, surface);
 	Common::String rigStatus;
 	Common::String gasFound;
 	Common::String perTapped;


Commit: 406ea4c395d6893c7a63f979d27459dda06021b1
    https://github.com/scummvm/scummvm/commit/406ea4c395d6893c7a63f979d27459dda06021b1
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
FREESCAPE: make sure end game area is properly renderer in driller

Changed paths:
    engines/freescape/games/driller/driller.cpp


diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 42708de1e9f..2721262e168 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -799,9 +799,15 @@ bool DrillerEngine::checkIfGameEnded() {
 			insertTemporaryMessage(_messagesList[19], _countdown - 2);
 			_gameStateVars[32] = 0;  // Avoid repeating the message
 		}
-		drawFrame();
-		_gfx->flipBuffer();
-		g_system->updateScreen();
+
+		// Draw a few frames
+		for (int i = 0; i < 10; i++) {
+			drawFrame();
+			_gfx->flipBuffer();
+			g_system->updateScreen();
+			g_system->delayMillis(10);
+		}
+
 		g_system->delayMillis(5000);
 		return true;
 	}


Commit: 04b70217b1dc5ba4c0e97c7adbf23339eb63d7e6
    https://github.com/scummvm/scummvm/commit/04b70217b1dc5ba4c0e97c7adbf23339eb63d7e6
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
FREESCAPE: palette fixes for driller cpc

Changed paths:
    engines/freescape/games/driller/cpc.cpp
    engines/freescape/games/palettes.cpp


diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index f9d95eef943..e105189cd01 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -138,12 +138,12 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 	_gfx->selectColorFromFourColorPalette(color, r, g, b);
 	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
-	color = 0;
+	color = _currentArea->_usualBackgroundColor;
 	if (_gfx->_colorRemaps && _gfx->_colorRemaps->contains(color)) {
 		color = (*_gfx->_colorRemaps)[color];
 	}
 
-	_gfx->readFromPalette(color, r, g, b);
+	_gfx->selectColorFromFourColorPalette(color, r, g, b);
 	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
 	int score = _gameStateVars[k8bitVariableScore];
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index e2fe6b8e3c8..529f8f43284 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -74,13 +74,13 @@ byte kDrillerZXPalette[9][3] = {
 };
 
 byte kDrillerCPCPalette[32][3] = {
-	{0x00, 0x00, 0x00}, // 0: special case?
+	{0x80, 0x80, 0x80}, // 0: special case?
 	{0x11, 0x22, 0x33},
 	{0x80, 0xff, 0x80}, // 2
 	{0xff, 0xff, 0x80}, // 3
 	{0x11, 0x22, 0x33},
 	{0xff, 0x00, 0x80}, // 5
-	{0x00, 0xff, 0x80}, // 6
+	{0x00, 0x80, 0x00}, // 6
 	{0xff, 0x80, 0x80}, // 7
 	{0x11, 0x22, 0x33},
 	{0x11, 0x22, 0x33},


Commit: 39614130466bd2a6ef939a89a498a1c937d1fb32
    https://github.com/scummvm/scummvm/commit/39614130466bd2a6ef939a89a498a1c937d1fb32
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
FREESCAPE: color remap fixes for driller cpc/amiga/atari

Changed paths:
    engines/freescape/freescape.cpp
    engines/freescape/games/driller/cpc.cpp
    engines/freescape/games/driller/driller.cpp
    engines/freescape/games/palettes.cpp
    engines/freescape/gfx.cpp


diff --git a/engines/freescape/freescape.cpp b/engines/freescape/freescape.cpp
index 841e33f3c00..587c9d6e500 100644
--- a/engines/freescape/freescape.cpp
+++ b/engines/freescape/freescape.cpp
@@ -278,12 +278,13 @@ void FreescapeEngine::drawFrame() {
 	_gfx->positionCamera(_position, _position + _cameraFront);
 
 	if (_underFireFrames > 0) {
-		int underFireColor = isDriller() && isDOS() ? 1
-							: _currentArea->_underFireBackgroundColor;
-		if (underFireColor < 16) {
-			_currentArea->remapColor(_currentArea->_usualBackgroundColor, underFireColor);
-			_currentArea->remapColor(_currentArea->_skyColor, underFireColor);
-		}
+		int underFireColor = _currentArea->_underFireBackgroundColor;
+
+		if (isDriller() && (isDOS() || isAmiga() || isAtariST()))
+			underFireColor = 1;
+
+		_currentArea->remapColor(_currentArea->_usualBackgroundColor, underFireColor);
+		_currentArea->remapColor(_currentArea->_skyColor, underFireColor);
 	}
 
 	drawBackground();
diff --git a/engines/freescape/games/driller/cpc.cpp b/engines/freescape/games/driller/cpc.cpp
index e105189cd01..79016c4c0e7 100644
--- a/engines/freescape/games/driller/cpc.cpp
+++ b/engines/freescape/games/driller/cpc.cpp
@@ -132,10 +132,10 @@ void DrillerEngine::loadAssetsCPCFullGame() {
 }
 
 void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
-	uint32 color = 1;
+	uint32 color = _currentArea->_underFireBackgroundColor;
 	uint8 r, g, b;
 
-	_gfx->selectColorFromFourColorPalette(color, r, g, b);
+	_gfx->readFromPalette(color, r, g, b);
 	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
 	color = _currentArea->_usualBackgroundColor;
@@ -143,7 +143,7 @@ void DrillerEngine::drawCPCUI(Graphics::Surface *surface) {
 		color = (*_gfx->_colorRemaps)[color];
 	}
 
-	_gfx->selectColorFromFourColorPalette(color, r, g, b);
+	_gfx->readFromPalette(color, r, g, b);
 	uint32 back = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
 	int score = _gameStateVars[k8bitVariableScore];
diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 2721262e168..4eb1a81523a 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -180,8 +180,13 @@ void DrillerEngine::gotoArea(uint16 areaID, int entranceID) {
 	_gfx->setColorRemaps(&_currentArea->_colorRemaps);
 
 	swapPalette(areaID);
-	_currentArea->_skyColor = 0;
-	_currentArea->_usualBackgroundColor = 0;
+
+	if (isDOS() || isAmiga() || isAtariST()) {
+		_currentArea->_skyColor = 0;
+		_currentArea->_usualBackgroundColor = 0;
+	} else if (isCPC()) {
+		_currentArea->_skyColor = _currentArea->_usualBackgroundColor;
+	}
 
 	resetInput();
 }
diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 529f8f43284..0950f90e165 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -94,7 +94,7 @@ byte kDrillerCPCPalette[32][3] = {
 	{0x00, 0xff, 0x80}, // 17
 	{0x00, 0xff, 0x00}, // 18
 	{0x80, 0xff, 0xff}, // 19
-	{0x11, 0x22, 0x33},
+	{0x00, 0x00, 0x00}, // 20
 	{0x00, 0x00, 0xff}, // 21
 	{0x00, 0x80, 0x00}, // 22
 	{0x00, 0x80, 0xff}, // 23
diff --git a/engines/freescape/gfx.cpp b/engines/freescape/gfx.cpp
index 5ce2d991485..530f79588d5 100644
--- a/engines/freescape/gfx.cpp
+++ b/engines/freescape/gfx.cpp
@@ -927,19 +927,12 @@ void Renderer::renderPolygon(const Math::Vector3d &origin, const Math::Vector3d
 }
 
 void Renderer::drawBackground(uint8 color) {
-
 	if (_colorRemaps && _colorRemaps->contains(color)) {
 		color = (*_colorRemaps)[color];
 	}
-
-	byte *stipple = nullptr;
-	uint8 r1, g1, b1, r2, g2, b2;
-	bool render = getRGBAt(color, r1, g1, b1, r2, g2, b2, stipple);
-	if (!render)
-		r1 = g1 = b1 = 0;
-
-	//assert(stipple == nullptr); // Unclear if this is ever used
-	clear(r1, g1, b1);
+	uint8 r, g, b;
+	readFromPalette(color, r, g, b);
+	clear(r, g, b);
 }
 
 Graphics::RendererType determinateRenderType() {


Commit: 334339c0c1958976ac5f94f3ae996fd8417d4069
    https://github.com/scummvm/scummvm/commit/334339c0c1958976ac5f94f3ae996fd8417d4069
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:20+02:00

Commit Message:
FREESCAPE: info menu fixes for driller zx/amiga/atari

Changed paths:
    engines/freescape/games/driller/driller.cpp


diff --git a/engines/freescape/games/driller/driller.cpp b/engines/freescape/games/driller/driller.cpp
index 4eb1a81523a..3d4d2075e07 100644
--- a/engines/freescape/games/driller/driller.cpp
+++ b/engines/freescape/games/driller/driller.cpp
@@ -248,12 +248,18 @@ void DrillerEngine::drawInfoMenu() {
 	uint8 r, g, b;
 
 	_gfx->readFromPalette(color, r, g, b);
+	if (isAmiga() || isAtariST()) {
+		r = 0xFF;
+		g = 0xFF;
+		b = 0x55;
+	}
+
 	uint32 front = _gfx->_texturePixelFormat.ARGBToColor(0xFF, r, g, b);
 
 	Common::String areaName = _currentArea->_name;
 	areaName.trim();
 
-	drawStringInSurface(Common::String::format("%10s : %s", "sector", areaName.c_str()), 69, 25, front, black, surface);
+	drawStringInSurface(Common::String::format("%10s : %s", "sector", areaName.c_str()), 59, 25, front, black, surface);
 	Common::String rigStatus;
 	Common::String gasFound;
 	Common::String perTapped;
@@ -284,10 +290,10 @@ void DrillerEngine::drawInfoMenu() {
 			break;
 	}
 
-	drawStringInSurface(Common::String::format("%10s : %s", "rig status", rigStatus.c_str()), 69, 33, front, black, surface);
-	drawStringInSurface(Common::String::format("%10s : %s", "gas found", gasFound.c_str()), 69, 41, front, black, surface);
-	drawStringInSurface(Common::String::format("%10s : %s", "% tapped", perTapped.c_str()), 69, 49, front, black, surface);
-	drawStringInSurface(Common::String::format("%10s : %s", "gas tapped", gasTapped.c_str()), 69, 57, front, black, surface);
+	drawStringInSurface(Common::String::format("%10s : %s", "rig status", rigStatus.c_str()), 59, 33, front, black, surface);
+	drawStringInSurface(Common::String::format("%10s : %s", "gas found", gasFound.c_str()), 59, 41, front, black, surface);
+	drawStringInSurface(Common::String::format("%10s : %s", "% tapped", perTapped.c_str()), 59, 49, front, black, surface);
+	drawStringInSurface(Common::String::format("%10s : %s", "gas tapped", gasTapped.c_str()), 59, 57, front, black, surface);
 
 	drawStringInSurface(Common::String::format("%13s : %d", "total sectors", 18), 84, 73, front, black, surface);
 	drawStringInSurface(Common::String::format("%13s : %d", "safe sectors", _gameStateVars[32]), 84, 81, front, black, surface);
@@ -298,7 +304,8 @@ void DrillerEngine::drawInfoMenu() {
 	} else if (isSpectrum()) {
 		drawStringInSurface("l-load s-save 1-abort", 76, 97, front, black, surface);
 		drawStringInSurface("any other key-continue", 76, 105, front, black, surface);
-	}
+	} else if (isAmiga() || isAtariST())
+		drawStringInSurface("press any key to continue", 66, 97, front, black, surface);
 
 	_uiTexture->update(surface);
 	_gfx->setViewport(_fullscreenViewArea);


Commit: 783e05753859fc13f5088d3ff2dfc9a6c08223d3
    https://github.com/scummvm/scummvm/commit/783e05753859fc13f5088d3ff2dfc9a6c08223d3
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:21+02:00

Commit Message:
FREESCAPE: added missing items for driller cga palettes

Changed paths:
    engines/freescape/games/palettes.cpp


diff --git a/engines/freescape/games/palettes.cpp b/engines/freescape/games/palettes.cpp
index 0950f90e165..f66b90ed5af 100644
--- a/engines/freescape/games/palettes.cpp
+++ b/engines/freescape/games/palettes.cpp
@@ -176,19 +176,22 @@ static const struct CGAPalettteEntry {
 	{10, kDrillerCGAPalettePinkBlue},
 	{11, kDrillerCGAPaletteRedGreen},
 	{12, kDrillerCGAPalettePinkBlue},
-
+	{13, kDrillerCGAPaletteRedGreen},
 	{14, kDrillerCGAPalettePinkBlue},
-
+	{15, kDrillerCGAPaletteRedGreen},
 	{16, kDrillerCGAPalettePinkBlue},
-
+	{17, kDrillerCGAPalettePinkBlue},
+	{18, kDrillerCGAPalettePinkBlue},
 	{19, kDrillerCGAPaletteRedGreen},
 	{20, kDrillerCGAPalettePinkBlue},
 	{21, kDrillerCGAPaletteRedGreen},
 	{22, kDrillerCGAPalettePinkBlue},
 	{23, kDrillerCGAPaletteRedGreen},
-
+	{25, kDrillerCGAPalettePinkBlue},
+	{27, kDrillerCGAPaletteRedGreen},
 	{28, kDrillerCGAPalettePinkBlue},
 
+	{31, kDrillerCGAPaletteRedGreen},
 	{32, kDrillerCGAPalettePinkBlue},
 	{127, kDrillerCGAPaletteRedGreen},
 	{0, 0}   // This marks the end


Commit: 2c33d94acaa4c6ba0efca9395639839cc2896487
    https://github.com/scummvm/scummvm/commit/2c33d94acaa4c6ba0efca9395639839cc2896487
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:21+02:00

Commit Message:
FREESCAPE: improved handling of entrance usage

Changed paths:
    engines/freescape/language/instruction.cpp
    engines/freescape/movement.cpp


diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index beb817e9841..099a7744841 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -93,7 +93,7 @@ void FreescapeEngine::executeObjectConditions(GeometricObject *obj, bool shot, b
 	assert(obj != nullptr);
 	if (!obj->_conditionSource.empty()) {
 		_firstSound = true;
-		_objExecutingCodeSize = obj->getSize();
+		_objExecutingCodeSize = collided ? obj->getSize() : Math::Vector3d();
 		if (collided)
 			debugC(1, kFreescapeDebugCode, "Executing with collision flag: %s", obj->_conditionSource.c_str());
 		else if (shot)
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index e5245723426..0737675a376 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -46,10 +46,10 @@ void FreescapeEngine::traverseEntrance(uint16 entranceID) {
 	}
 
 	_pitch = rotation.x();
-	if (ABS(_objExecutingCodeSize.x()) <= ABS(_objExecutingCodeSize.z()))
-		_yaw = rotation.y() - 90;
-	else
+	if (_objExecutingCodeSize.length() == 0 || ABS(_objExecutingCodeSize.x()) > ABS(_objExecutingCodeSize.z()))
 		_yaw = rotation.y() + 90;
+	else
+		_yaw = rotation.y() - 90;
 
 	debugC(1, kFreescapeDebugMove, "entrace position: %f %f %f", _position.x(), _position.y(), _position.z());
 


Commit: 3f44942adc8f51e5becaab3125724708107d3cb6
    https://github.com/scummvm/scummvm/commit/3f44942adc8f51e5becaab3125724708107d3cb6
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:21+02:00

Commit Message:
FREESCAPE: improved handling of rise/fall

Changed paths:
    engines/freescape/area.cpp
    engines/freescape/movement.cpp


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index df1339e9db4..4f9605cf01f 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -330,20 +330,12 @@ float sweepAABB(Math::AABB const &a, Math::AABB const &b, Math::Vector3d const &
 	return h;
 }
 
-Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight) {
-	Math::AABB boundingBox(position, position);
-
-	Math::Vector3d v1(position.x() + 1, position.y() + 1, position.z() + 1);
-	Math::Vector3d v2(position.x() - 1, position.y() - playerHeight, position.z() - 1);
-
-	boundingBox.expand(v1);
-	boundingBox.expand(v2);
-	return boundingBox;
-}
+extern Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight);
 
 Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, const Math::Vector3d &newPosition_, int playerHeight) {
 	Math::Vector3d position = newPosition_;
 	Math::Vector3d lastPosition = lastPosition_;
+	Math::AABB boundingBox = createPlayerAABB(lastPosition, playerHeight);
 
 	float epsilon = 1.5;
 	int i = 0;
@@ -352,7 +344,6 @@ Math::Vector3d Area::resolveCollisions(const Math::Vector3d &lastPosition_, cons
 		Math::Vector3d normal;
 		Math::Vector3d direction = position - lastPosition;
 
-		Math::AABB boundingBox = createPlayerAABB(lastPosition, playerHeight);
 		for (auto &obj : _drawableObjects) {
 			if (!obj->isDestroyed() && !obj->isInvisible()) {
 				GeometricObject *gobj = (GeometricObject *)obj;
diff --git a/engines/freescape/movement.cpp b/engines/freescape/movement.cpp
index 0737675a376..c297bdb8d46 100644
--- a/engines/freescape/movement.cpp
+++ b/engines/freescape/movement.cpp
@@ -23,6 +23,17 @@
 
 namespace Freescape {
 
+Math::AABB createPlayerAABB(Math::Vector3d const position, int playerHeight) {
+	Math::AABB boundingBox(position, position);
+
+	Math::Vector3d v1(position.x() + 1, position.y() + 1, position.z() + 1);
+	Math::Vector3d v2(position.x() - 1, position.y() - playerHeight, position.z() - 1);
+
+	boundingBox.expand(v1);
+	boundingBox.expand(v2);
+	return boundingBox;
+}
+
 void FreescapeEngine::gotoArea(uint16 areaID, int entranceID) {
 	error("Function \"%s\" not implemented", __FUNCTION__);
 }
@@ -149,27 +160,26 @@ void FreescapeEngine::rise() {
 	debugC(1, kFreescapeDebugMove, "playerHeightNumber: %d", _playerHeightNumber);
 	int previousAreaID = _currentArea->getAreaID();
 	if (_flyMode) {
-		_position.setValue(1, _position.y() + _playerSteps[_playerStepIndex]);
+		Math::Vector3d destination = _position;
+		destination.y() = destination.y() + _playerSteps[_playerStepIndex];
+		resolveCollisions(destination);
 	} else {
 		if (_playerHeightNumber == int(_playerHeights.size()) - 1)
 			return;
 
 		_playerHeightNumber++;
 		changePlayerHeight(_playerHeightNumber);
-	}
 
-	bool collided = /*checkCollisions(true) ||*/ _position.y() >= 2016;
-	if (collided) {
-		if (_currentArea->getAreaID() == previousAreaID) {
-			if (_flyMode)
-				_position = _lastPosition;
-			else {
+		Math::AABB boundingBox = createPlayerAABB(_position, _playerHeight);
+		ObjectArray objs = _currentArea->checkCollisions(boundingBox);
+		bool collided = objs.size() > 0;
+		if (collided) {
+			if (_currentArea->getAreaID() == previousAreaID) {
 				_playerHeightNumber--;
 				changePlayerHeight(_playerHeightNumber);
 			}
 		}
 	}
-
 	_lastPosition = _position;
 	debugC(1, kFreescapeDebugMove, "new player position: %f, %f, %f", _position.x(), _position.y(), _position.z());
 	executeMovementConditions();
@@ -177,16 +187,10 @@ void FreescapeEngine::rise() {
 
 void FreescapeEngine::lower() {
 	debugC(1, kFreescapeDebugMove, "playerHeightNumber: %d", _playerHeightNumber);
-	int previousAreaID = _currentArea->getAreaID();
-
 	if (_flyMode) {
-		_position.setValue(1, _position.y() - (_playerSteps[_playerStepIndex] * 0.5));
-		bool collided = false; //checkCollisions(true);
-		if (collided) {
-			if (_currentArea->getAreaID() == previousAreaID) {
-				_position = _lastPosition;
-			}
-		}
+		Math::Vector3d destination = _position;
+		destination.y() = destination.y() - _playerSteps[_playerStepIndex];
+		resolveCollisions(destination);
 	} else {
 		if (_playerHeightNumber == 0)
 			return;


Commit: 9f1b8658295963017520a74dfc2c7202a22b747e
    https://github.com/scummvm/scummvm/commit/9f1b8658295963017520a74dfc2c7202a22b747e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2023-05-17T10:11:21+02:00

Commit Message:
FREESCAPE: initial parsing and rendering of group objects

Changed paths:
  A engines/freescape/objects/group.cpp
    engines/freescape/area.cpp
    engines/freescape/area.h
    engines/freescape/freescape.h
    engines/freescape/language/instruction.cpp
    engines/freescape/loaders/8bitBinaryLoader.cpp
    engines/freescape/module.mk
    engines/freescape/objects/geometricobject.cpp
    engines/freescape/objects/group.h


diff --git a/engines/freescape/area.cpp b/engines/freescape/area.cpp
index 4f9605cf01f..e1c20299fb1 100644
--- a/engines/freescape/area.cpp
+++ b/engines/freescape/area.cpp
@@ -226,11 +226,20 @@ void Area::draw(Freescape::Renderer *gfx) {
 	assert(_drawableObjects.size() > 0);
 	for (auto &obj : _drawableObjects) {
 		if (!obj->isDestroyed() && !obj->isInvisible()) {
-			obj->draw(gfx);
+			if (obj->getType() != ObjectType::kGroupType)
+				obj->draw(gfx);
+			else
+				drawGroup(gfx, (Group *)obj);
 		}
 	}
 }
 
+void Area::drawGroup(Freescape::Renderer *gfx, Group* group) {
+	for (auto &obj : group->_objects) {
+		obj->draw(gfx);
+	}
+}
+
 Object *Area::shootRay(const Math::Ray &ray) {
 	float size = 16.0 * 8192.0; // TODO: check if this is max size
 	Object *collided = nullptr;
diff --git a/engines/freescape/area.h b/engines/freescape/area.h
index a6fa1e2fdc7..7b149696e2e 100644
--- a/engines/freescape/area.h
+++ b/engines/freescape/area.h
@@ -30,6 +30,8 @@
 
 #include "freescape/language/instruction.h"
 #include "freescape/objects/object.h"
+#include "freescape/objects/group.h"
+
 
 namespace Freescape {
 
@@ -50,6 +52,7 @@ public:
 	void remapColor(int index, int color);
 	void unremapColor(int index);
 	void draw(Renderer *gfx);
+	void drawGroup(Renderer *gfx, Group *group);
 	void show();
 
 	Object *shootRay(const Math::Ray &ray);
diff --git a/engines/freescape/freescape.h b/engines/freescape/freescape.h
index 6e3d666dec9..299cebcfbd9 100644
--- a/engines/freescape/freescape.h
+++ b/engines/freescape/freescape.h
@@ -286,6 +286,7 @@ public:
 	// Instructions
 	bool checkConditional(FCLInstruction &instruction, bool shot, bool collided, bool timer, bool activated);
 	bool checkIfGreaterOrEqual(FCLInstruction &instruction);
+	void executeExecute(FCLInstruction &instruction);
 	void executeIncrementVariable(FCLInstruction &instruction);
 	void executeDecrementVariable(FCLInstruction &instruction);
 	void executeSetVariable(FCLInstruction &instruction);
diff --git a/engines/freescape/language/instruction.cpp b/engines/freescape/language/instruction.cpp
index 099a7744841..e040fe6492c 100644
--- a/engines/freescape/language/instruction.cpp
+++ b/engines/freescape/language/instruction.cpp
@@ -203,6 +203,9 @@ void FreescapeEngine::executeCode(FCLInstructionVector &code, bool shot, bool co
 		case Token::REDRAW:
 			executeRedraw(instruction);
 			break;
+		case Token::EXECUTE:
+			executeExecute(instruction);
+			break;
 		case Token::DELAY:
 			executeDelay(instruction);
 			break;
@@ -250,6 +253,12 @@ void FreescapeEngine::executeRedraw(FCLInstruction &instruction) {
 	waitForSounds();
 }
 
+void FreescapeEngine::executeExecute(FCLInstruction &instruction) {
+	// TODO
+	uint16 objId = instruction._source;
+	debugC(1, kFreescapeDebugCode, "Executing instructions from object %d", objId);
+}
+
 void FreescapeEngine::executeSound(FCLInstruction &instruction) {
 	if (_firstSound)
 		stopAllSounds();
diff --git a/engines/freescape/loaders/8bitBinaryLoader.cpp b/engines/freescape/loaders/8bitBinaryLoader.cpp
index e570d4dbb65..e5c15fc76ca 100644
--- a/engines/freescape/loaders/8bitBinaryLoader.cpp
+++ b/engines/freescape/loaders/8bitBinaryLoader.cpp
@@ -277,11 +277,23 @@ Object *FreescapeEngine::load8bitObject(Common::SeekableReadStream *file) {
 
 	case kGroupType:
 		debugC(1, kFreescapeDebugParser, "Object of type 'group'");
-		file->seek(byteSizeOfObject, SEEK_CUR);
+		Common::Array<uint8> groupDataArray;
+		groupDataArray.push_back(uint8(position.x()));
+		groupDataArray.push_back(uint8(position.y()));
+		groupDataArray.push_back(uint8(position.z()));
+
+		groupDataArray.push_back(uint8(v.x()));
+		groupDataArray.push_back(uint8(v.y()));
+		groupDataArray.push_back(uint8(v.z()));
+
+		byteSizeOfObject++;
+		while(--byteSizeOfObject > 0)
+			groupDataArray.push_back(file->readByte());
+
 		return new Group(
 			objectID,
-			position,
-			v);
+			rawFlagsAndType,
+			groupDataArray);
 		break;
 	}
 	// Unreachable
@@ -486,6 +498,12 @@ Area *FreescapeEngine::load8bitArea(Common::SeekableReadStream *file, uint16 nco
 		debugC(1, kFreescapeDebugParser, "Reading object: %d", object);
 		Object *newObject = load8bitObject(file);
 
+		if (newObject->getType() == ObjectType::kGroupType) {
+			Group *group = (Group *)newObject;
+			for (ObjectMap::iterator it = objectsByID->begin(); it != objectsByID->end(); ++it)
+				group->assemble(it->_value);
+		}
+
 		if (newObject) {
 			newObject->scale(scale);
 			if (newObject->getType() == kEntranceType) {
diff --git a/engines/freescape/module.mk b/engines/freescape/module.mk
index cf02372b576..3db7785ab67 100644
--- a/engines/freescape/module.mk
+++ b/engines/freescape/module.mk
@@ -26,6 +26,7 @@ MODULE_OBJS := \
 	movement.o \
 	neo.o \
 	objects/geometricobject.o \
+	objects/group.o \
 	objects/sensor.o \
 	scr.o \
 	sound.o \
diff --git a/engines/freescape/objects/geometricobject.cpp b/engines/freescape/objects/geometricobject.cpp
index ff74a5a3798..b754c528df3 100644
--- a/engines/freescape/objects/geometricobject.cpp
+++ b/engines/freescape/objects/geometricobject.cpp
@@ -171,6 +171,16 @@ GeometricObject::GeometricObject(
 }
 
 void GeometricObject::setOrigin(Math::Vector3d origin_) {
+	if (isPolygon(_type)) {
+		Math::Vector3d offset = origin_ - _origin;
+		offset = 32 * offset;
+		for (int i = 0; i < int(_ordinates->size()); i = i + 3) {
+			(*_ordinates)[i    ] += uint16(offset.x());
+			(*_ordinates)[i + 1] += uint16(offset.y());
+			(*_ordinates)[i + 2] += uint16(offset.z());
+		}
+	}
+
 	_origin = origin_;
 	computeBoundingBox();
 }
diff --git a/engines/freescape/objects/group.cpp b/engines/freescape/objects/group.cpp
new file mode 100644
index 00000000000..b080641418a
--- /dev/null
+++ b/engines/freescape/objects/group.cpp
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "freescape/freescape.h"
+#include "freescape/objects/group.h"
+#include "freescape/objects/geometricobject.h"
+
+namespace Freescape {
+
+Group::Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_) {
+	_objectID = objectID_;
+	_flags = flags_;
+
+	int i;
+	for (i = 0; i < 9; i++) {
+		debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
+		if (data_[i] > 0)
+			_objectIds.push_back(data_[i]);
+		/*else
+			break;*/
+	}
+	i = 9;
+	while (i < int(data_.size())) {
+		debugC(1, kFreescapeDebugParser, "group data[%d] = %d", i, data_[i]);
+
+		if (data_[i] >= _objectIds.size())
+			break;
+
+		_objects.push_back(nullptr);
+		//assert(data_[i] < _objectIds.size());
+		_objectIndices.push_back(data_[i]);
+
+		debug("data[%d] = %d", i + 1, data_[i + 1]);
+		debug("data[%d] = %d", i + 2, data_[i + 2]);
+		debug("data[%d] = %d", i + 3, data_[i + 3]);
+		Math::Vector3d position(data_[i + 1], data_[i + 2], data_[i + 3]);
+		_objectPositions.push_back(position);
+
+		i = i + 4;
+	}
+
+	if (isDestroyed()) // If the object is destroyed, restore it
+		restore();
+
+	_flags = _flags & ~0x80;
+	assert(!isInitiallyInvisible());
+	makeVisible();
+}
+
+void Group::assemble(Object *obj) {
+	int objectIndex = -1;
+	for (int i = 0; i < int(_objectIds.size()) ; i++) {
+		if (_objectIds[i] == obj->getObjectID()) {
+			objectIndex = i;
+			break;
+		}
+	}
+
+	if (objectIndex == -1)
+		return;
+
+	for (int i = 0; i < int(_objectIndices.size()) ; i++) {
+		int index = _objectIndices[i];
+		if (index == objectIndex) {
+			Object *duplicate = obj->duplicate();
+			Math::Vector3d position = _objectPositions[i];
+			duplicate->setOrigin(position);
+			_objects[i] = duplicate;
+		}
+	}
+}
+
+} // End of namespace Freescape
\ No newline at end of file
diff --git a/engines/freescape/objects/group.h b/engines/freescape/objects/group.h
index 514ca33542d..270485e276b 100644
--- a/engines/freescape/objects/group.h
+++ b/engines/freescape/objects/group.h
@@ -28,15 +28,16 @@ namespace Freescape {
 
 class Group : public Object {
 public:
-	Group(uint16 objectID_,
-		const Math::Vector3d &origin_,
-		const Math::Vector3d &rotation_) {
-		_objectID = objectID_;
-		_origin = origin_;
-		_rotation = rotation_;
-	}
+	Group(uint16 objectID_, uint16 flags_, const Common::Array<byte> data_);
+	void assemble(Object *obj);
+
+	Common::Array<Object *> _objects;
+	Common::Array<Math::Vector3d> _objectPositions;
+	Common::Array<int16> _objectIndices;
+	Common::Array<int16> _objectIds;
 
 	ObjectType getType() override { return ObjectType::kGroupType; };
+	bool isDrawable() override { return true; }
 	void draw(Freescape::Renderer *gfx) override { error("cannot render Group"); };
 	void scale(int factor) override { warning("cannot scale Group"); };
 	Object *duplicate() override { error("cannot duplicate Group"); };




More information about the Scummvm-git-logs mailing list