[Scummvm-git-logs] scummvm master -> cc375694be27e4a53a19add033e789d23d2c3e4f

mgerhardy martin.gerhardy at gmail.com
Mon Dec 7 21:56:54 UTC 2020


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

Summary:
6efa01a76d TWINE: const for entity animation pointers
55c3a8108d TWINE: reduced scope, unsigned and const
99d7f4fffb TWINE: moved ActionType into shared.h
2e6f235236 TWINE: put a comment to mark the relation between the two methods
cc375694be TWINE: prepare to load the entity data into a struct


Commit: 6efa01a76d4343954dfba391cac5f78a977e6059
    https://github.com/scummvm/scummvm/commit/6efa01a76d4343954dfba391cac5f78a977e6059
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-12-07T22:55:10+01:00

Commit Message:
TWINE: const for entity animation pointers

Changed paths:
    engines/twine/animations.cpp


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 7f7eeebce3..483b0e24c8 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -304,10 +304,10 @@ bool Animations::setModelAnimation(int32 animState, const uint8 *animPtr, uint8
 }
 
 int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
-	uint8 *costumePtr = nullptr;
+	const uint8 *costumePtr = nullptr;
 
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
-	uint8 *bodyPtr = actor->entityDataPtr;
+	const uint8 *bodyPtr = actor->entityDataPtr;
 
 	do {
 		int8 type = *(bodyPtr++);
@@ -317,14 +317,14 @@ int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 			return -1;
 		}
 
-		uint8 *ptr = (bodyPtr + 1);
+		const uint8 *ptr = (bodyPtr + 1);
 
 		if (type == 3) {
 			if (animIdx == (AnimationTypes)*bodyPtr) {
 				ptr++;
 				uint16 realAnimIdx = READ_LE_INT16(ptr);
 				ptr += 2;
-				uint8 *ptr2 = ptr;
+				const uint8 *ptr2 = ptr;
 				ptr++;
 				if (*ptr2 != 0) {
 					costumePtr = ptr - 1;


Commit: 55c3a8108d07793c128e722af63e6b5d39c6b3bb
    https://github.com/scummvm/scummvm/commit/55c3a8108d07793c128e722af63e6b5d39c6b3bb
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-12-07T22:55:11+01:00

Commit Message:
TWINE: reduced scope, unsigned and const

Changed paths:
    engines/twine/animations.cpp


diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 483b0e24c8..70857830df 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -304,15 +304,12 @@ bool Animations::setModelAnimation(int32 animState, const uint8 *animPtr, uint8
 }
 
 int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
-	const uint8 *costumePtr = nullptr;
-
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	const uint8 *bodyPtr = actor->entityDataPtr;
 
 	do {
-		int8 type = *(bodyPtr++);
-
-		if (type == -1) {
+		const uint8 type = *bodyPtr++;
+		if (type == 0xFF) {
 			currentActorAnimExtraPtr = nullptr;
 			return -1;
 		}
@@ -326,6 +323,7 @@ int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 				ptr += 2;
 				const uint8 *ptr2 = ptr;
 				ptr++;
+				const uint8 *costumePtr = nullptr;
 				if (*ptr2 != 0) {
 					costumePtr = ptr - 1;
 				}
@@ -335,7 +333,6 @@ int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 		}
 
 		bodyPtr = *ptr + ptr;
-
 	} while (1);
 
 	return 0;


Commit: 99d7f4fffbbce0e0f9f67572044d6caf930d6837
    https://github.com/scummvm/scummvm/commit/99d7f4fffbbce0e0f9f67572044d6caf930d6837
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-12-07T22:55:11+01:00

Commit Message:
TWINE: moved ActionType into shared.h

Changed paths:
    engines/twine/actor.cpp
    engines/twine/animations.cpp
    engines/twine/shared.h


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index b34e18924e..ea5111f765 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -231,7 +231,7 @@ int32 Actor::initBody(int32 bodyIdx, int32 actorIdx, ActorBoundingBox &actorBoun
 					return index;
 				}
 
-				if (stream.readByte() != 14) {
+				if (stream.readByte() != ActionType::ACTION_ZV) {
 					return index;
 				}
 
diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 70857830df..2a8177d406 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -48,31 +48,6 @@ static const int32 magicLevelStrengthOfHit[] = {
 	0
 };
 
-enum ActionType {
-	ACTION_NOP = 0,
-	ACTION_BODY = 1,
-	ACTION_BODP = 2,
-	ACTION_ANIM = 3,
-	ACTION_ANIP = 4,
-	ACTION_HITTING = 5,
-	ACTION_SAMPLE = 6,
-	ACTION_SAMPLE_FREQ = 7,
-	ACTION_THROW_EXTRA_BONUS = 8,
-	ACTION_THROW_MAGIC_BALL = 9,
-	ACTION_SAMPLE_REPEAT = 10,
-	ACTION_THROW_SEARCH = 11,
-	ACTION_THROW_ALPHA = 12,
-	ACTION_SAMPLE_STOP = 13,
-	ACTION_ZV = 14, // unused
-	ACTION_LEFT_STEP = 15,
-	ACTION_RIGHT_STEP = 16,
-	ACTION_HERO_HITTING = 17,
-	ACTION_THROW_3D = 18,
-	ACTION_THROW_3D_ALPHA = 19,
-	ACTION_THROW_3D_SEARCH = 20,
-	ACTION_LAST
-};
-
 Animations::Animations(TwinEEngine *engine) : _engine(engine), animBuffer((uint8 *)malloc(5000 * sizeof(uint8))) {
 	animBufferPos = animBuffer;
 }
@@ -305,19 +280,19 @@ bool Animations::setModelAnimation(int32 animState, const uint8 *animPtr, uint8
 
 int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
-	const uint8 *bodyPtr = actor->entityDataPtr;
+	const uint8 *entityDataPtr = actor->entityDataPtr;
 
 	do {
-		const uint8 type = *bodyPtr++;
+		const uint8 type = *entityDataPtr++;
 		if (type == 0xFF) {
 			currentActorAnimExtraPtr = nullptr;
 			return -1;
 		}
 
-		const uint8 *ptr = (bodyPtr + 1);
+		const uint8 *ptr = (entityDataPtr + 1);
 
 		if (type == 3) {
-			if (animIdx == (AnimationTypes)*bodyPtr) {
+			if (animIdx == (AnimationTypes)*entityDataPtr) {
 				ptr++;
 				uint16 realAnimIdx = READ_LE_INT16(ptr);
 				ptr += 2;
@@ -332,7 +307,7 @@ int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 			}
 		}
 
-		bodyPtr = *ptr + ptr;
+		entityDataPtr = *ptr + ptr;
 	} while (1);
 
 	return 0;
@@ -437,12 +412,12 @@ void Animations::processAnimActions(int32 actorIdx) {
 	const int32 endAnimEntityIdx = stream.readByte();
 	while (index++ < endAnimEntityIdx) {
 		const int32 actionType = stream.readByte();
-		if (actionType >= ACTION_LAST) {
+		if (actionType >= ActionType::ACTION_LAST) {
 			return;
 		}
 
 		switch (actionType) {
-		case ACTION_HITTING: {
+		case ActionType::ACTION_HITTING: {
 			const int32 animFrame = stream.readByte() - 1;
 			const int32 strength = stream.readByte();
 
@@ -452,7 +427,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_SAMPLE: {
+		case ActionType::ACTION_SAMPLE: {
 			const int32 animFrame = stream.readByte();
 			const int16 sampleIdx = stream.readSint16LE();
 
@@ -461,7 +436,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_SAMPLE_FREQ: {
+		case ActionType::ACTION_SAMPLE_FREQ: {
 			const int32 animFrame = stream.readByte();
 			const int16 sampleIdx = stream.readSint16LE();
 			/*int16 frequency = */stream.readSint16LE();
@@ -471,7 +446,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_EXTRA_BONUS: {
+		case ActionType::ACTION_THROW_EXTRA_BONUS: {
 			const int32 animFrame = stream.readByte();
 			const int32 yHeight = stream.readSint16LE();
 			const int32 sprite = stream.readByte();
@@ -486,7 +461,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_MAGIC_BALL: {
+		case ActionType::ACTION_THROW_MAGIC_BALL: {
 			const int32 animFrame = stream.readByte();
 			const int32 yOffset = stream.readSint16LE();
 			const int32 xAngle = ToAngle(stream.readSint16LE());
@@ -498,7 +473,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_SAMPLE_REPEAT: {
+		case ActionType::ACTION_SAMPLE_REPEAT: {
 			const int32 animFrame = stream.readByte();
 			const int16 sampleIdx = stream.readSint16LE();
 			const int16 repeat = stream.readSint16LE();
@@ -508,7 +483,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_SEARCH: {
+		case ActionType::ACTION_THROW_SEARCH: {
 			const int32 animFrame = stream.readByte();
 			const int32 yOffset = stream.readSint16LE();
 			const int32 spriteIdx = stream.readByte();
@@ -520,7 +495,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_ALPHA: {
+		case ActionType::ACTION_THROW_ALPHA: {
 			const int32 animFrame = stream.readByte();
 			const int32 yHeight = stream.readSint16LE();
 			const int32 spriteIdx = stream.readByte();
@@ -535,7 +510,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_SAMPLE_STOP: {
+		case ActionType::ACTION_SAMPLE_STOP: {
 			const int32 animFrame = stream.readByte();
 			const int32 sampleIdx = stream.readByte(); //why is it reading a byte but saving it in a 32bit variable?
 			stream.skip(1);               // TODO what is the meaning of this extra byte?
@@ -545,8 +520,8 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_LEFT_STEP:
-		case ACTION_RIGHT_STEP: {
+		case ActionType::ACTION_LEFT_STEP:
+		case ActionType::ACTION_RIGHT_STEP: {
 			const int32 animFrame = stream.readByte();
 			if (animFrame == actor->animPosition && (actor->brickSound & 0x0F0) != 0x0F0) {
 				const int16 sampleIdx = (actor->brickSound & 0x0F) + Samples::WalkFloorBegin;
@@ -554,7 +529,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_HERO_HITTING: {
+		case ActionType::ACTION_HERO_HITTING: {
 			const int32 animFrame = stream.readByte() - 1;
 			if (animFrame == actor->animPosition) {
 				actor->strengthOfHit = magicLevelStrengthOfHit[_engine->_gameState->magicLevelIdx];
@@ -562,7 +537,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_3D: {
+		case ActionType::ACTION_THROW_3D: {
 			const int32 animFrame = stream.readByte();
 			const int32 distanceX = stream.readSint16LE();
 			const int32 distanceY = stream.readSint16LE();
@@ -586,7 +561,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_3D_ALPHA: {
+		case ActionType::ACTION_THROW_3D_ALPHA: {
 			const int32 animFrame = stream.readByte();
 			const int32 distanceX = stream.readSint16LE();
 			const int32 distanceY = stream.readSint16LE();
@@ -612,7 +587,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_THROW_3D_SEARCH: {
+		case ActionType::ACTION_THROW_3D_SEARCH: {
 			const int32 animFrame = stream.readByte();
 			const int32 distanceX = stream.readSint16LE();
 			const int32 distanceY = stream.readSint16LE();
@@ -629,7 +604,7 @@ void Animations::processAnimActions(int32 actorIdx) {
 			}
 			break;
 		}
-		case ACTION_ZV:
+		case ActionType::ACTION_ZV:
 		default:
 			break;
 		}
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index c3e837f363..9e13afb71a 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -27,6 +27,31 @@
 
 namespace TwinE {
 
+enum ActionType {
+	ACTION_NOP = 0,
+	ACTION_BODY = 1,
+	ACTION_BODP = 2,
+	ACTION_ANIM = 3,
+	ACTION_ANIP = 4,
+	ACTION_HITTING = 5,
+	ACTION_SAMPLE = 6,
+	ACTION_SAMPLE_FREQ = 7,
+	ACTION_THROW_EXTRA_BONUS = 8,
+	ACTION_THROW_MAGIC_BALL = 9,
+	ACTION_SAMPLE_REPEAT = 10,
+	ACTION_THROW_SEARCH = 11,
+	ACTION_THROW_ALPHA = 12,
+	ACTION_SAMPLE_STOP = 13,
+	ACTION_ZV = 14,
+	ACTION_LEFT_STEP = 15,
+	ACTION_RIGHT_STEP = 16,
+	ACTION_HERO_HITTING = 17,
+	ACTION_THROW_3D = 18,
+	ACTION_THROW_3D_ALPHA = 19,
+	ACTION_THROW_3D_SEARCH = 20,
+	ACTION_LAST
+};
+
 enum class ShapeType {
 	kNone = 0,
 	kSolid = 1,


Commit: 2e6f235236cde9a47555f5c92cbc59144cf98d94
    https://github.com/scummvm/scummvm/commit/2e6f235236cde9a47555f5c92cbc59144cf98d94
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-12-07T22:55:11+01:00

Commit Message:
TWINE: put a comment to mark the relation between the two methods

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


diff --git a/engines/twine/actor.cpp b/engines/twine/actor.cpp
index ea5111f765..2360859e28 100644
--- a/engines/twine/actor.cpp
+++ b/engines/twine/actor.cpp
@@ -191,6 +191,7 @@ int32 Actor::getTextIdForBehaviour() const {
 	return (int32)_engine->_actor->heroBehaviour;
 }
 
+// see Animations::getBodyAnimIndex
 int32 Actor::initBody(int32 bodyIdx, int32 actorIdx, ActorBoundingBox &actorBoundingBox) {
 	if (bodyIdx == -1) {
 		return -1;
diff --git a/engines/twine/animations.cpp b/engines/twine/animations.cpp
index 2a8177d406..3d11b8edfb 100644
--- a/engines/twine/animations.cpp
+++ b/engines/twine/animations.cpp
@@ -278,6 +278,7 @@ bool Animations::setModelAnimation(int32 animState, const uint8 *animPtr, uint8
 	return false;
 }
 
+// see Actor::initBody
 int32 Animations::getBodyAnimIndex(AnimationTypes animIdx, int32 actorIdx) {
 	ActorStruct *actor = _engine->_scene->getActor(actorIdx);
 	const uint8 *entityDataPtr = actor->entityDataPtr;


Commit: cc375694be27e4a53a19add033e789d23d2c3e4f
    https://github.com/scummvm/scummvm/commit/cc375694be27e4a53a19add033e789d23d2c3e4f
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2020-12-07T22:55:11+01:00

Commit Message:
TWINE: prepare to load the entity data into a struct

Changed paths:
  A engines/twine/entity.cpp
  A engines/twine/entity.h
    engines/twine/actor.h
    engines/twine/module.mk
    engines/twine/shared.h


diff --git a/engines/twine/actor.h b/engines/twine/actor.h
index 5010186ce5..1c7241eb3d 100644
--- a/engines/twine/actor.h
+++ b/engines/twine/actor.h
@@ -255,22 +255,6 @@ private:
 	uint8 *heroEntityPROTOPACK = nullptr; // file3D4
 	int32 heroEntityPROTOPACKSize = 0;
 
-	struct ActorBoundingBox {
-		/** Bottom left X coordinate */
-		int16 bottomLeftX = 0;
-		/** Bottom left Y coordinate */
-		int16 bottomLeftY = 0;
-		/** Bottom left Z coordinate */
-		int16 bottomLeftZ = 0;
-		/** Top left X coordinate */
-		int16 topRightX = 0;
-		/** Top left Y coordinate */
-		int16 topRightY = 0;
-		/** Top left Z coordinate */
-		int16 topRightZ = 0;
-		bool hasBoundingBox = false;
-	};
-
 	void initSpriteActor(int32 actorIdx);
 
 	/**
diff --git a/engines/twine/entity.cpp b/engines/twine/entity.cpp
new file mode 100644
index 0000000000..dbcb3c6e66
--- /dev/null
+++ b/engines/twine/entity.cpp
@@ -0,0 +1,194 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "twine/entity.h"
+#include "common/stream.h"
+
+namespace TwinE {
+
+bool EntityData::loadBody(Common::SeekableReadStream &stream) {
+	EntityBody body;
+	body.index = stream.readByte();
+	const int32 pos = stream.pos();
+	uint8 size = stream.readByte();
+	body.bodyIndex = stream.readUint16LE();
+	body.actorBoundingBox.hasBoundingBox = stream.readByte();
+	if (body.actorBoundingBox.hasBoundingBox) {
+		if (stream.readByte() == ActionType::ACTION_ZV) {
+			body.actorBoundingBox.bottomLeftX = stream.readUint16LE();
+			body.actorBoundingBox.bottomLeftY = stream.readUint16LE();
+			body.actorBoundingBox.bottomLeftZ = stream.readUint16LE();
+			body.actorBoundingBox.topRightX = stream.readUint16LE();
+			body.actorBoundingBox.topRightY = stream.readUint16LE();
+			body.actorBoundingBox.topRightZ = stream.readUint16LE();
+		}
+	}
+	_bodies.push_back(body);
+	stream.seek(pos + size);
+	return !stream.err();
+}
+
+bool EntityData::loadAnim(Common::SeekableReadStream &stream) {
+	EntityAnim anim;
+	anim.animation = (AnimationTypes)stream.readByte();
+	const int32 pos = stream.pos();
+	uint8 size = stream.readByte();
+	anim.animIndex = stream.readSint16LE();
+	const uint8 numActions = stream.readByte();
+	for (uint8 i = 0U; i < numActions; ++i) {
+		EntityAnim::Action action;
+		action.type = stream.readByte();
+		switch (action.type) {
+		case ActionType::ACTION_HITTING:
+			action.animFrame = stream.readByte();
+			action.strength = stream.readByte();
+			break;
+		case ActionType::ACTION_SAMPLE:
+			action.animFrame = stream.readByte();
+			action.sampleIndex = stream.readSint16LE();
+			break;
+		case ActionType::ACTION_SAMPLE_FREQ:
+			action.animFrame = stream.readByte();
+			action.sampleIndex = stream.readSint16LE();
+			action.frequency = stream.readSint16LE();
+			break;
+		case ActionType::ACTION_THROW_MAGIC_BALL:
+			action.animFrame = stream.readByte();
+			action.yHeight = stream.readSint16LE();
+			action.xAngle = ToAngle(stream.readSint16LE());
+			action.xRotPoint = stream.readSint16LE();
+			action.extraAngle = stream.readByte();
+			break;
+		case ActionType::ACTION_SAMPLE_REPEAT:
+			action.animFrame = stream.readByte();
+			action.sampleIndex = stream.readSint16LE();
+			action.repeat = stream.readSint16LE();
+			break;
+		case ActionType::ACTION_THROW_SEARCH:
+			action.animFrame = stream.readByte();
+			action.yHeight = stream.readSint16LE();
+			action.spriteIndex = stream.readByte();
+			action.targetActor = stream.readByte();
+			action.finalAngle = stream.readSint16LE();
+			action.strength = stream.readByte();
+			break;
+		case ActionType::ACTION_THROW_EXTRA_BONUS:
+		case ActionType::ACTION_THROW_ALPHA:
+			action.animFrame = stream.readByte();
+			action.yHeight = stream.readSint16LE();
+			action.spriteIndex = stream.readByte();
+			action.xAngle = ToAngle(stream.readSint16LE());
+			action.yAngle = ToAngle(stream.readSint16LE());
+			action.xRotPoint = stream.readSint16LE();
+			action.extraAngle = ToAngle(stream.readByte());
+			action.strength = stream.readByte();
+			break;
+		case ActionType::ACTION_LEFT_STEP:
+		case ActionType::ACTION_RIGHT_STEP:
+		case ActionType::ACTION_HERO_HITTING:
+			action.animFrame = stream.readByte();
+			break;
+		case ActionType::ACTION_SAMPLE_STOP:
+			action.animFrame = stream.readByte();
+			action.sampleIndex = stream.readByte();
+			stream.skip(1);
+			break;
+		case ActionType::ACTION_THROW_3D:
+		case ActionType::ACTION_THROW_3D_ALPHA:
+			action.animFrame = stream.readByte();
+			action.distanceX = stream.readSint16LE();
+			action.distanceY = stream.readSint16LE();
+			action.distanceZ = stream.readSint16LE();
+			action.spriteIndex = stream.readByte();
+			action.xAngle = ToAngle(stream.readSint16LE());
+			action.yAngle = ToAngle(stream.readSint16LE());
+			action.xRotPoint = stream.readSint16LE();
+			action.extraAngle = ToAngle(stream.readByte());
+			action.strength = stream.readByte();
+			break;
+		case ActionType::ACTION_THROW_3D_SEARCH:
+			action.animFrame = stream.readByte();
+			action.distanceX = stream.readSint16LE();
+			action.distanceY = stream.readSint16LE();
+			action.distanceZ = stream.readSint16LE();
+			action.spriteIndex = stream.readByte();
+			action.targetActor = stream.readByte();
+			action.finalAngle = ToAngle(stream.readSint16LE());
+			action.strength = stream.readByte();
+			break;
+		case ActionType::ACTION_ZV:
+		default:
+			break;
+		}
+		anim._actions.push_back(action);
+	}
+	_animations.push_back(anim);
+	stream.seek(pos + size);
+	return !stream.err();
+}
+
+bool EntityData::loadFromStream(Common::SeekableReadStream &stream) {
+	do {
+		const uint8 opcode = stream.readByte();
+		if (opcode == 1) {
+			if (!loadBody(stream)) {
+				return false;
+			}
+		} else if (opcode == 3) {
+			if (!loadAnim(stream)) {
+				return false;
+			}
+		} else if (opcode == 0xFF) {
+			break;
+		}
+	} while (!stream.eos() && !stream.err());
+
+	return true;
+}
+
+bool EntityData::loadFromBuffer(const uint8* buf, uint32 size) {
+	if (size == 0) {
+		error("Failed to load entity data");
+	}
+	Common::MemoryReadStream stream(buf, size);
+	return loadFromStream(stream);
+}
+
+const EntityBody* EntityData::getBody(const int index) const {
+	for (const EntityBody& body : _bodies) {
+		if (body.index == index) {
+			return &body;
+		}
+	}
+	return nullptr;
+}
+
+int32 EntityData::getAnimIndex(AnimationTypes animation) const {
+	for (const EntityAnim& anim : _animations) {
+		if (anim.animation == animation) {
+			return anim.animIndex;
+		}
+	}
+	return -1;
+}
+
+} // End of namespace TwinE
diff --git a/engines/twine/entity.h b/engines/twine/entity.h
new file mode 100644
index 0000000000..38bb8c71eb
--- /dev/null
+++ b/engines/twine/entity.h
@@ -0,0 +1,85 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef TWINE_ENTITY_H
+#define TWINE_ENTITY_H
+
+#include "common/array.h"
+#include "common/memstream.h"
+#include "common/stream.h"
+#include "twine/shared.h"
+
+namespace TwinE {
+
+struct EntityBody {
+	int index;
+	ActorBoundingBox actorBoundingBox;
+	int bodyIndex;
+};
+
+struct EntityAnim {
+	AnimationTypes animation;
+	int animIndex;
+
+	struct Action {
+		uint8 type = 0;
+		uint8 animFrame = 0;
+		int16 sampleIndex = 0;
+		int16 frequency = 0;
+		int16 xAngle = 0;
+		int16 yAngle = 0;
+		int16 xRotPoint = 0;
+		int16 extraAngle = 0;
+		int16 finalAngle = 0;
+		int16 strength = 0;
+		int16 distanceX = 0;
+		int16 distanceY = 0;
+		int16 distanceZ = 0;
+		int16 yHeight = 0;
+		uint8 spriteIndex = 0;
+		uint8 targetActor = 0;
+		int16 repeat = 0;
+	};
+
+	Common::Array<Action> _actions;
+};
+
+class EntityData {
+private:
+	Common::Array<EntityBody> _bodies;
+	Common::Array<EntityAnim> _animations;
+
+	bool loadBody(Common::SeekableReadStream &stream);
+	bool loadAnim(Common::SeekableReadStream &stream);
+
+public:
+	bool loadFromStream(Common::SeekableReadStream &stream);
+
+	bool loadFromBuffer(const uint8* buf, uint32 size);
+
+	const EntityBody* getBody(const int index) const;
+	int32 getAnimIndex(AnimationTypes animation) const;
+};
+
+} // End of namespace TwinE
+
+#endif
diff --git a/engines/twine/module.mk b/engines/twine/module.mk
index 0e1f3c860e..421a25d1be 100644
--- a/engines/twine/module.mk
+++ b/engines/twine/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
 	debug_grid.o \
 	debug_scene.o \
 	detection.o \
+	entity.o \
 	extra.o \
 	flamovies.o \
 	gamestate.o \
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 9e13afb71a..64769a7168 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -27,6 +27,22 @@
 
 namespace TwinE {
 
+struct ActorBoundingBox {
+	/** Bottom left X coordinate */
+	int16 bottomLeftX = 0;
+	/** Bottom left Y coordinate */
+	int16 bottomLeftY = 0;
+	/** Bottom left Z coordinate */
+	int16 bottomLeftZ = 0;
+	/** Top left X coordinate */
+	int16 topRightX = 0;
+	/** Top left Y coordinate */
+	int16 topRightY = 0;
+	/** Top left Z coordinate */
+	int16 topRightZ = 0;
+	bool hasBoundingBox = false;
+};
+
 enum ActionType {
 	ACTION_NOP = 0,
 	ACTION_BODY = 1,




More information about the Scummvm-git-logs mailing list