[Scummvm-git-logs] scummvm master -> 617ba4154d3c8faea900ce191d92faea3421f723
mgerhardy
noreply at scummvm.org
Wed Aug 14 15:30:55 UTC 2024
This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
3a6301ac30 TWINE: todo comment about lba2 shortcuts
f2802c0c83 TWINE: LBA2: implemented a few more opcodes
57690caaca TWINE: LBA2: unified initSprite with lba2
a7a7a1f15f TWINE: LBA2: added anim3ds parser
8ff7ab977d TWINE: LBA2: added further life opcodes
617ba4154d TWINE: LBA2: implemented more opcodes
Commit: 3a6301ac3091e46dc167e360df1fc3e5f67a0228
https://github.com/scummvm/scummvm/commit/3a6301ac3091e46dc167e360df1fc3e5f67a0228
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2024-08-14T17:28:39+02:00
Commit Message:
TWINE: todo comment about lba2 shortcuts
Changed paths:
engines/twine/metaengine.cpp
diff --git a/engines/twine/metaengine.cpp b/engines/twine/metaengine.cpp
index e8b0bcaeb20..c1120a437e8 100644
--- a/engines/twine/metaengine.cpp
+++ b/engines/twine/metaengine.cpp
@@ -440,6 +440,19 @@ Common::KeymapArray TwinEMetaEngine::initKeymaps(const char *target) const {
act->addDefaultInputMapping("JOY_BACK");
gameKeyMap->addAction(act);
+ // TODO: lba2 has shortcuts for the inventory items
+ // J: Protopack/Jetpack
+ // P: Mecha-Penguin
+ // H: Holomap
+ // X: Dodges
+ // 1: Magic Ball
+ // 2: Darts
+ // 3: Blowpipe/Blowtron
+ // 4: Conch Shell
+ // 5: Glove
+ // 6: Laser Gun
+ // 7: Saber
+
array[0] = gameKeyMap;
}
Commit: f2802c0c8326148d12dd3926c12e835ec6178bf7
https://github.com/scummvm/scummvm/commit/f2802c0c8326148d12dd3926c12e835ec6178bf7
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2024-08-14T17:29:46+02:00
Commit Message:
TWINE: LBA2: implemented a few more opcodes
Changed paths:
engines/twine/scene/gamestate.cpp
engines/twine/scene/gamestate.h
engines/twine/scene/scene.h
engines/twine/script/script_life.cpp
engines/twine/script/script_life.h
engines/twine/script/script_life_v1.cpp
engines/twine/script/script_life_v1.h
engines/twine/script/script_life_v2.cpp
engines/twine/script/script_life_v2.h
engines/twine/shared.h
engines/twine/twine.h
diff --git a/engines/twine/scene/gamestate.cpp b/engines/twine/scene/gamestate.cpp
index fb36b86dfe1..a0bb4f32597 100644
--- a/engines/twine/scene/gamestate.cpp
+++ b/engines/twine/scene/gamestate.cpp
@@ -149,6 +149,11 @@ bool GameState::loadGame(Common::SeekableReadStream *file) {
return false;
}
+ if (!_engine->isLBA1()) {
+ warning("Loading not implemented for lba2");
+ return false;
+ }
+
debug(2, "Load game");
const byte saveFileVersion = file->readByte();
// 4 is dotemu enhanced version of lba1
@@ -173,8 +178,8 @@ bool GameState::loadGame(Common::SeekableReadStream *file) {
} while (true);
byte numGameFlags = file->readByte();
- if (numGameFlags != NUM_GAME_FLAGS) {
- warning("Failed to load gameflags. Expected %u, but got %u", NUM_GAME_FLAGS, numGameFlags);
+ if (numGameFlags != NUM_GAME_FLAGS_LBA1) {
+ warning("Failed to load gameflags. Expected %u, but got %u", NUM_GAME_FLAGS_LBA1, numGameFlags);
return false;
}
for (uint8 i = 0; i < numGameFlags; ++i) {
@@ -248,9 +253,9 @@ bool GameState::saveGame(Common::WriteStream *file) {
file->writeByte(0x03);
file->writeString(_engine->_menuOptions->_saveGameName);
file->writeByte('\0');
- file->writeByte(NUM_GAME_FLAGS);
- for (uint8 i = 0; i < NUM_GAME_FLAGS; ++i) {
- file->writeByte(hasGameFlag(i));
+ file->writeByte(NUM_GAME_FLAGS_LBA1);
+ for (uint8 i = 0; i < NUM_GAME_FLAGS_LBA1; ++i) {
+ file->writeByte((uint8)hasGameFlag(i));
}
file->writeByte(sceneIdx);
file->writeByte(getChapter());
@@ -605,6 +610,11 @@ int16 GameState::setKashes(int16 value) {
return _goldPieces;
}
+int16 GameState::setZlitos(int16 value) {
+ _zlitosPieces = CLIP<int16>(value, 0, 999);
+ return _zlitosPieces;
+}
+
int16 GameState::setKeys(int16 value) {
_inventoryNumKeys = MAX<int16>(0, value);
return _inventoryNumKeys;
@@ -669,7 +679,7 @@ void GameState::clearGameFlags() {
Common::fill(&_listFlagGame[0], &_listFlagGame[NUM_GAME_FLAGS], 0);
}
-uint8 GameState::hasGameFlag(uint8 index) const {
+int16 GameState::hasGameFlag(uint8 index) const {
debug(6, "Query gameStateFlags[%u]=%u", index, _listFlagGame[index]);
return _listFlagGame[index];
}
diff --git a/engines/twine/scene/gamestate.h b/engines/twine/scene/gamestate.h
index ed11560b803..3e156a8c284 100644
--- a/engines/twine/scene/gamestate.h
+++ b/engines/twine/scene/gamestate.h
@@ -69,7 +69,7 @@ private:
* 107: Set to 1 after Twinsen kills yellow groboclone in the Citadel Island Tavern (after the Tavern has
* been closed down). Makes the Tavern open again and groboclone not appear any more.
*/
- int16 _listFlagGame[NUM_GAME_FLAGS];
+ int16 _listFlagGame[NUM_GAME_FLAGS]; // ListVarGame
// only lba1 - lba2 uses 253 gameflag
int16 _gameChapter = 0;
@@ -176,7 +176,7 @@ public:
void clearGameFlags();
- uint8 hasGameFlag(uint8 index) const;
+ int16 hasGameFlag(uint8 index) const;
void setGameFlag(uint8 index, int16 value);
@@ -184,6 +184,7 @@ public:
int16 setGas(int16 value);
int16 setLeafs(int16 value);
int16 setKashes(int16 value);
+ int16 setZlitos(int16 value);
int16 setMagicPoints(int16 val);
int16 setMaxMagicPoints();
int16 setLeafBoxes(int16 val);
diff --git a/engines/twine/scene/scene.h b/engines/twine/scene/scene.h
index b044aba7bee..7dfc81df009 100644
--- a/engines/twine/scene/scene.h
+++ b/engines/twine/scene/scene.h
@@ -209,10 +209,10 @@ public:
bool _enableGridTileRendering = true;
- uint8 _listFlagCube[NUM_SCENES_FLAGS]{0};
+ uint8 _listFlagCube[NUM_SCENES_FLAGS]{0}; // ListVarCube
- int32 _sceneNumZones = 0;
- ZoneStruct _sceneZones[NUM_MAX_ZONES];
+ int32 _sceneNumZones = 0; // NbZones
+ ZoneStruct _sceneZones[NUM_MAX_ZONES]; // ListZone
ActorStruct *getActor(int32 actorIdx); // ListObjet
diff --git a/engines/twine/script/script_life.cpp b/engines/twine/script/script_life.cpp
index a84dc24c9f4..d886ef213dd 100644
--- a/engines/twine/script/script_life.cpp
+++ b/engines/twine/script/script_life.cpp
@@ -1068,18 +1068,6 @@ int32 ScriptLife::lEND_COMPORTEMENT(TwinEEngine *engine, LifeScriptContext &ctx)
return 1; // break
}
-/**
- * Set a new value for the game flag (Paramter = Game Flag Index, Parameter = Value)
- * @note Opcode @c 0x24
- */
-int32 ScriptLife::lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx) {
- const uint8 flagIdx = ctx.stream.readByte();
- const uint8 flagValue = ctx.stream.readByte();
- debugC(3, kDebugLevels::kDebugScripts, "LIFE::SET_FLAG_GAME(%i, %i)", (int)flagIdx, (int)flagValue);
- engine->_gameState->setGameFlag(flagIdx, flagValue);
- return 0;
-}
-
/**
* Kill the actor passed as paramenter (Parameter = Actor Index)
* @note Opcode @c 0x25
diff --git a/engines/twine/script/script_life.h b/engines/twine/script/script_life.h
index 2aab2dec0cd..1bb101b12da 100644
--- a/engines/twine/script/script_life.h
+++ b/engines/twine/script/script_life.h
@@ -107,7 +107,6 @@ public:
static int32 lSET_COMPORTEMENT(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lSET_COMPORTEMENT_OBJ(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lEND_COMPORTEMENT(TwinEEngine *engine, LifeScriptContext &ctx);
- static int32 lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lKILL_OBJ(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lSUICIDE(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lUSE_ONE_LITTLE_KEY(TwinEEngine *engine, LifeScriptContext &ctx);
diff --git a/engines/twine/script/script_life_v1.cpp b/engines/twine/script/script_life_v1.cpp
index fe224bcce25..645f9b96dca 100644
--- a/engines/twine/script/script_life_v1.cpp
+++ b/engines/twine/script/script_life_v1.cpp
@@ -24,6 +24,7 @@
#include "twine/twine.h"
#include "twine/text.h"
#include "twine/audio/music.h"
+#include "twine/scene/gamestate.h"
namespace TwinE {
@@ -68,6 +69,18 @@ int32 ScriptLifeV1::lMIDI_OFF(TwinEEngine *engine, LifeScriptContext &ctx) {
return 0;
}
+/**
+ * Set a new value for the game flag (Paramter = Game Flag Index, Parameter = Value)
+ * @note Opcode @c 0x24
+ */
+int32 ScriptLifeV1::lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const uint8 flagIdx = ctx.stream.readByte();
+ const uint8 flagValue = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::SET_FLAG_GAME(%i, %i)", (int)flagIdx, (int)flagValue);
+ engine->_gameState->setGameFlag(flagIdx, flagValue);
+ return 0;
+}
+
static const ScriptLifeFunction function_map[] = {
{"END", ScriptLifeV1::lEND},
{"NOP", ScriptLifeV1::lNOP},
diff --git a/engines/twine/script/script_life_v1.h b/engines/twine/script/script_life_v1.h
index 36b9dce275b..e128aecb743 100644
--- a/engines/twine/script/script_life_v1.h
+++ b/engines/twine/script/script_life_v1.h
@@ -34,6 +34,7 @@ public:
static int32 lBUBBLE_OFF(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lPLAY_MIDI(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lMIDI_OFF(TwinEEngine *engine, LifeScriptContext &ctx);
+ static int32 lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx);
ScriptLifeV1(TwinEEngine *engine);
};
diff --git a/engines/twine/script/script_life_v2.cpp b/engines/twine/script/script_life_v2.cpp
index 5ab181fa434..55bbe3253c1 100644
--- a/engines/twine/script/script_life_v2.cpp
+++ b/engines/twine/script/script_life_v2.cpp
@@ -73,7 +73,7 @@ static const ScriptLifeFunction function_map[] = {
{"SET_COMPORTEMENT", ScriptLife::lSET_COMPORTEMENT},
{"SET_COMPORTEMENT_OBJ", ScriptLife::lSET_COMPORTEMENT_OBJ},
{"END_COMPORTEMENT", ScriptLife::lEND_COMPORTEMENT},
- {"SET_FLAG_GAME", ScriptLife::lSET_FLAG_GAME},
+ {"SET_FLAG_GAME", ScriptLifeV2::lSET_FLAG_GAME},
{"KILL_OBJ", ScriptLife::lKILL_OBJ},
{"SUICIDE", ScriptLife::lSUICIDE},
{"USE_ONE_LITTLE_KEY", ScriptLife::lUSE_ONE_LITTLE_KEY},
@@ -738,12 +738,63 @@ int32 ScriptLifeV2::lBACKGROUND(TwinEEngine *engine, LifeScriptContext &ctx) {
return -1;
}
+int32 ScriptLifeV2::lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const uint8 num = ctx.stream.readByte();
+ const int16 val = ctx.stream.readSint16LE();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::SET_FLAG_GAME(%i, %i)", (int)num, (int)val);
+ engine->_gameState->setGameFlag(num, val);
+
+ if (num == GAMEFLAG_MONEY) {
+ if (engine->_scene->_planet >= 2) {
+ engine->_gameState->setKashes(val);
+ } else {
+ engine->_gameState->setZlitos(val);
+ }
+ }
+
+ return 0;
+}
+
int32 ScriptLifeV2::lADD_VAR_GAME(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ const uint8 num = ctx.stream.readByte();
+ const int16 val = ctx.stream.readSint16LE();
+ int16 currentVal = engine->_gameState->hasGameFlag(num);
+ if ((int)currentVal + (int)val < 32767) {
+ currentVal += val;
+ } else {
+ currentVal = 32767;
+ }
+
+ if (num == GAMEFLAG_MONEY) {
+ if (engine->_scene->_planet >= 2) {
+ engine->_gameState->setKashes(currentVal);
+ } else {
+ engine->_gameState->setZlitos(currentVal);
+ }
+ }
+ engine->_gameState->setGameFlag(num, currentVal);
+ return 0;
}
int32 ScriptLifeV2::lSUB_VAR_GAME(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ const uint8 num = ctx.stream.readByte();
+ const int16 val = ctx.stream.readSint16LE();
+ int16 currentVal = engine->_gameState->hasGameFlag(num);
+ if ((int)currentVal - (int)val > -32768) {
+ currentVal -= val;
+ } else {
+ currentVal = -32768;
+ }
+
+ if (num == GAMEFLAG_MONEY) {
+ if (engine->_scene->_planet >= 2) {
+ engine->_gameState->setKashes(currentVal);
+ } else {
+ engine->_gameState->setZlitos(currentVal);
+ }
+ }
+ engine->_gameState->setGameFlag(num, currentVal);
+ return 0;
}
int32 ScriptLifeV2::lADD_VAR_CUBE(TwinEEngine *engine, LifeScriptContext &ctx) {
diff --git a/engines/twine/script/script_life_v2.h b/engines/twine/script/script_life_v2.h
index f58177b3c45..0e5d05a4676 100644
--- a/engines/twine/script/script_life_v2.h
+++ b/engines/twine/script/script_life_v2.h
@@ -110,6 +110,7 @@ public:
static int32 lNEW_SAMPLE (TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lPOS_OBJ_AROUND(TwinEEngine *engine, LifeScriptContext &ctx);
static int32 lPCX_MESS_OBJ(TwinEEngine *engine, LifeScriptContext &ctx);
+ static int32 lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx);
ScriptLifeV2(TwinEEngine *engine);
};
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 21ec973ff7f..03c95aeb00a 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -24,7 +24,9 @@
#include "common/scummsys.h"
-#define NUM_GAME_FLAGS 255
+// lba1 255 - lba2 256
+#define NUM_GAME_FLAGS 256
+#define NUM_GAME_FLAGS_LBA1 255
/** Number of colors used in the game */
#define NUMOFCOLORS 256
@@ -77,6 +79,9 @@
// Twinsun explosion
#define GAMEFLAG_VIDEO_EXPLODE2 219
+// lba2 Kashes or Zlitos
+#define GAMEFLAG_MONEY 8
+
#define OWN_ACTOR_SCENE_INDEX 0
#define IS_HERO(x) ((x) == OWN_ACTOR_SCENE_INDEX)
diff --git a/engines/twine/twine.h b/engines/twine/twine.h
index 4907591e57b..e72788e04ab 100644
--- a/engines/twine/twine.h
+++ b/engines/twine/twine.h
@@ -316,9 +316,9 @@ public:
int32 _loopInventoryItem = 0;
int32 _stepFalling = 0;
- uint32 _gameFlags;
+ uint32 _gameFlags = 0u;
Common::Platform _platform;
- bool _flagRain;
+ bool _flagRain = false;
/** Disable screen recenter */
bool _disableScreenRecenter = false;
Commit: 57690caaca87006012cfd160b47e329ffd066966
https://github.com/scummvm/scummvm/commit/57690caaca87006012cfd160b47e329ffd066966
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2024-08-14T17:29:46+02:00
Commit Message:
TWINE: LBA2: unified initSprite with lba2
Changed paths:
engines/twine/parser/sprite.h
engines/twine/scene/actor.cpp
engines/twine/scene/actor.h
engines/twine/script/script_life_v2.cpp
engines/twine/script/script_move_v2.cpp
diff --git a/engines/twine/parser/sprite.h b/engines/twine/parser/sprite.h
index 00eb32a21b7..e8bbeec5b88 100644
--- a/engines/twine/parser/sprite.h
+++ b/engines/twine/parser/sprite.h
@@ -46,7 +46,7 @@ private:
public:
bool loadFromStream(Common::SeekableReadStream &stream, bool lba1) override;
- const BoundingBox *bbox(int index) const;
+ const BoundingBox *bbox(int index) const; // PtrZvAnim3DS, PtrZvExtra, PtrZvExtraRaw
const SpriteDim *dim(int index) const;
};
diff --git a/engines/twine/scene/actor.cpp b/engines/twine/scene/actor.cpp
index 9bd3d712b57..35706fb4c23 100644
--- a/engines/twine/scene/actor.cpp
+++ b/engines/twine/scene/actor.cpp
@@ -133,13 +133,16 @@ void Actor::setBehaviour(HeroBehaviourType behaviour) {
_engine->_animations->initAnim(AnimationTypes::kStanding, AnimType::kAnimationTypeRepeat, AnimationTypes::kAnimInvalid, OWN_ACTOR_SCENE_INDEX);
}
-// InitSprite
-void Actor::initSpriteActor(int32 actorIdx) {
+void Actor::initSprite(int32 spriteNum, int32 actorIdx) {
ActorStruct *localActor = _engine->_scene->getActor(actorIdx);
- if (localActor->_staticFlags.bIsSpriteActor && localActor->_sprite != -1 && localActor->_body != localActor->_sprite) {
- const BoundingBox *spritebbox = _engine->_resources->_spriteBoundingBox.bbox(localActor->_sprite);
- localActor->_body = localActor->_sprite;
+ localActor->_sprite = spriteNum;
+ if (!localActor->_staticFlags.bIsSpriteActor) {
+ return;
+ }
+ if (spriteNum != -1 && localActor->_body != spriteNum) {
+ const BoundingBox *spritebbox = _engine->_resources->_spriteBoundingBox.bbox(spriteNum);
+ localActor->_body = spriteNum;
localActor->_boundingBox = *spritebbox;
}
}
@@ -249,7 +252,7 @@ void Actor::startInitObj(int16 actorIdx) {
actor->_body = -1;
- initSpriteActor(actorIdx);
+ initSprite(actor->_sprite, actorIdx);
_engine->_movements->initRealAngle(LBAAngles::ANGLE_0, LBAAngles::ANGLE_0, LBAAngles::ANGLE_0, &actor->realAngle);
diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index a0423bd5b8e..428e8e20341 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -314,7 +314,7 @@ public:
/** Hero anim for behaviour menu */
int16 _heroAnimIdx[4];
- void initSpriteActor(int32 actorIdx);
+ void initSprite(int32 spriteNum, int32 actorIdx);
/** Restart hero variables while opening new scenes */
void restartHeroScene();
diff --git a/engines/twine/script/script_life_v2.cpp b/engines/twine/script/script_life_v2.cpp
index 55bbe3253c1..86f54356817 100644
--- a/engines/twine/script/script_life_v2.cpp
+++ b/engines/twine/script/script_life_v2.cpp
@@ -605,8 +605,7 @@ int32 ScriptLifeV2::lSET_SPRITE(TwinEEngine *engine, LifeScriptContext &ctx) {
const int16 num = ctx.stream.readSint16LE();
debugC(3, kDebugLevels::kDebugScripts, "LIFE::lSET_SPRITE(%i)", (int)num);
if (ctx.actor->_staticFlags.bIsSpriteActor) {
- ctx.actor->_sprite = num;
- engine->_actor->initSpriteActor(ctx.actorIdx);
+ engine->_actor->initSprite(num, ctx.actorIdx);
}
return 0;
}
@@ -621,8 +620,7 @@ int32 ScriptLifeV2::lSET_FRAME_3DS(TwinEEngine *engine, LifeScriptContext &ctx)
// }
// sprite += ListAnim3DS[ptrobj->Coord.A3DS.Num].Deb;
- ctx.actor->_sprite = sprite;
- engine->_actor->initSpriteActor(ctx.actorIdx);
+ engine->_actor->initSprite(sprite, ctx.actorIdx);
}
return -1;
}
diff --git a/engines/twine/script/script_move_v2.cpp b/engines/twine/script/script_move_v2.cpp
index 2ca2533575a..e9178864654 100644
--- a/engines/twine/script/script_move_v2.cpp
+++ b/engines/twine/script/script_move_v2.cpp
@@ -149,8 +149,7 @@ int32 ScriptMoveV2::mWAIT_NB_SECOND_RND(TwinEEngine *engine, MoveScriptContext &
int32 ScriptMoveV2::mSPRITE(TwinEEngine *engine, MoveScriptContext &ctx) {
int16 num = ctx.stream.readSint16LE();
if (ctx.actor->_staticFlags.bIsSpriteActor) {
- ctx.actor->_sprite = num;
- engine->_actor->initSpriteActor(ctx.actorIdx);
+ engine->_actor->initSprite(num, ctx.actorIdx);
}
return 0;
}
Commit: a7a7a1f15fd160118f2239e095b0ff78dca5a454
https://github.com/scummvm/scummvm/commit/a7a7a1f15fd160118f2239e095b0ff78dca5a454
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2024-08-14T17:29:46+02:00
Commit Message:
TWINE: LBA2: added anim3ds parser
Changed paths:
A engines/twine/parser/anim3ds.cpp
A engines/twine/parser/anim3ds.h
engines/twine/module.mk
engines/twine/parser/anim.h
engines/twine/resources/resources.cpp
engines/twine/resources/resources.h
engines/twine/scene/actor.cpp
engines/twine/scene/actor.h
engines/twine/script/script_life_v2.cpp
engines/twine/script/script_move_v2.cpp
diff --git a/engines/twine/module.mk b/engines/twine/module.mk
index 71b8e838ada..5e4c4e35e40 100644
--- a/engines/twine/module.mk
+++ b/engines/twine/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
menu/menuoptions.o \
\
parser/anim.o \
+ parser/anim3ds.o \
parser/blocklibrary.o \
parser/body.o \
parser/entity.o \
diff --git a/engines/twine/parser/anim.h b/engines/twine/parser/anim.h
index a10b948aa21..67789194bfc 100644
--- a/engines/twine/parser/anim.h
+++ b/engines/twine/parser/anim.h
@@ -71,8 +71,8 @@ protected:
public:
bool loadFromStream(Common::SeekableReadStream &stream, bool lba1) override;
- const KeyFrame* getKeyframe(uint index) const;
- const Common::Array<KeyFrame>& getKeyframes() const;
+ const KeyFrame *getKeyframe(uint index) const;
+ const Common::Array<KeyFrame> &getKeyframes() const;
uint getNumKeyframes() const;
uint16 getLoopFrame() const;
uint16 getNumBoneframes() const;
diff --git a/engines/twine/parser/anim3ds.cpp b/engines/twine/parser/anim3ds.cpp
new file mode 100644
index 00000000000..961708b6ed4
--- /dev/null
+++ b/engines/twine/parser/anim3ds.cpp
@@ -0,0 +1,40 @@
+/* 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 "twine/parser/anim3ds.h"
+
+namespace TwinE {
+
+bool Anim3DSData::loadFromStream(Common::SeekableReadStream &stream, bool lba1) {
+ assert(!lba1);
+
+ const int n = (int)stream.size() / 8;
+ for (int i = 0; i < n; ++i) {
+ T_ANIM_3DS anim;
+ stream.read(anim.Name, 4);
+ anim.Deb = stream.readSint16LE();
+ anim.Fin = stream.readSint16LE();
+ _anims.push_back(anim);
+ }
+ return !stream.err();
+}
+
+} // namespace TwinE
diff --git a/engines/twine/parser/anim3ds.h b/engines/twine/parser/anim3ds.h
new file mode 100644
index 00000000000..342d09e4a52
--- /dev/null
+++ b/engines/twine/parser/anim3ds.h
@@ -0,0 +1,48 @@
+/* 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/>.
+ *
+ */
+
+#ifndef TWINE_PARSER_ANIM3DS_H
+#define TWINE_PARSER_ANIM3DS_H
+
+#include "twine/parser/parser.h"
+#include "twine/shared.h"
+
+namespace TwinE {
+
+struct T_ANIM_3DS {
+ char Name[4]; // Name of the animation
+ int16 Deb; // Start frame in the HQR
+ int16 Fin; // End frame in the HQR
+};
+
+class Anim3DSData : public Parser {
+private:
+ Common::Array<T_ANIM_3DS> _anims; // ListAnim3DS
+
+public:
+ bool loadFromStream(Common::SeekableReadStream &stream, bool lba1) override;
+
+ const Common::Array<T_ANIM_3DS> &getAnims() const { return _anims; }
+};
+
+} // End of namespace TwinE
+
+#endif
diff --git a/engines/twine/resources/resources.cpp b/engines/twine/resources/resources.cpp
index cd26c1b5a25..660f1b3d5a4 100644
--- a/engines/twine/resources/resources.cpp
+++ b/engines/twine/resources/resources.cpp
@@ -24,8 +24,10 @@
#include "common/tokenizer.h"
#include "common/util.h"
#include "twine/audio/sound.h"
+#include "twine/parser/anim3ds.h"
#include "twine/renderer/renderer.h"
#include "twine/renderer/screens.h"
+#include "twine/resources/hqr.h"
#include "twine/scene/animations.h"
#include "twine/scene/scene.h"
#include "twine/text.h"
@@ -59,6 +61,18 @@ void Resources::initPalettes() {
free(mainPalette);
}
+void Resources::preloadAnim3DS() {
+ const int index = HQR::numEntries(Resources::HQR_ANIM3DS_FILE) - 1;
+ _anim3DSData.loadFromHQR(Resources::HQR_ANIM3DS_FILE, index, _engine->isLBA1());
+}
+
+const T_ANIM_3DS *Resources::getAnim(int index) const {
+ if (index < 0 || index >= (int)_anim3DSData.getAnims().size()) {
+ return nullptr;
+ }
+ return &_anim3DSData.getAnims()[index];
+}
+
void Resources::preloadSprites() {
const int32 numEntries = HQR::numEntries(Resources::HQR_SPRITES_FILE);
const int32 maxSprites = _engine->isLBA1() ? 200 : NUM_SPRITES;
@@ -188,6 +202,8 @@ void Resources::initResources() {
error("Failed to parse trajectory data");
}
debug("preload %i trajectories", (int)_trajectories.getTrajectories().size());
+ } else if (_engine->isLBA2()) {
+ preloadAnim3DS();
}
preloadSprites();
diff --git a/engines/twine/resources/resources.h b/engines/twine/resources/resources.h
index 2d76cc36cb0..98575400024 100644
--- a/engines/twine/resources/resources.h
+++ b/engines/twine/resources/resources.h
@@ -24,6 +24,7 @@
#include "common/hashmap.h"
#include "common/scummsys.h"
+#include "twine/parser/anim3ds.h"
#include "twine/parser/body.h"
#include "twine/parser/holomap.h"
#include "twine/parser/sprite.h"
@@ -134,8 +135,10 @@ private:
void initPalettes();
/** Preload all sprites */
void preloadSprites();
+
/** Preload all animations */
void preloadAnimations();
+ void preloadAnim3DS();
void preloadSamples();
void loadMovieInfo();
@@ -145,6 +148,7 @@ private:
TrajectoryData _trajectories;
TextData _textData;
+ Anim3DSData _anim3DSData;
public:
Resources(TwinEEngine *engine) : _engine(engine) {}
@@ -194,6 +198,7 @@ public:
const Trajectory *getTrajectory(int index) const;
const TextEntry *getText(TextBankId textBankId, TextId index) const;
+ const T_ANIM_3DS *getAnim(int index) const;
int findSmkMovieIndex(const char *name) const;
@@ -233,6 +238,7 @@ public:
static constexpr const char *HQR_BODY_FILE = "body.hqr";
// animations
static constexpr const char *HQR_ANIM_FILE = "anim.hqr";
+ static constexpr const char *HQR_ANIM3DS_FILE = "anim3ds.hqr";
// inventory objects
static constexpr const char *HQR_INVOBJ_FILE = "invobj.hqr";
diff --git a/engines/twine/scene/actor.cpp b/engines/twine/scene/actor.cpp
index 35706fb4c23..61d28fd8d91 100644
--- a/engines/twine/scene/actor.cpp
+++ b/engines/twine/scene/actor.cpp
@@ -133,6 +133,82 @@ void Actor::setBehaviour(HeroBehaviourType behaviour) {
_engine->_animations->initAnim(AnimationTypes::kStanding, AnimType::kAnimationTypeRepeat, AnimationTypes::kAnimInvalid, OWN_ACTOR_SCENE_INDEX);
}
+void Actor::setFrame(int32 actorIdx, uint32 frame) {
+#if 0
+ // TODO: converted from asm - not yet adapted
+ ActorStruct *obj = _engine->_scene->getActor(actorIdx);
+ T_PTR_NUM tempNextBody = obj->NextBody;
+ void *tempNextTexture = obj->NextTexture;
+
+ if (frame >= obj->NbFrames) {
+ return;
+ }
+
+ obj->_body = tempNextBody;
+ obj->Texture = tempNextTexture;
+
+ T_PTR_NUM tempAnim = obj->_anim;
+ void (*TransFctAnim)() = nullptr; // Couldn't find this yet
+
+ if (TransFctAnim != nullptr) {
+ uint32 ebp = frame;
+ TransFctAnim();
+ tempAnim = (T_PTR_NUM)(void *)tempAnim.Ptr;
+ frame = ebp;
+ }
+
+ obj->Interpolator = 0;
+ obj->LastAnimStepX = 0;
+ obj->LastAnimStepY = 0;
+ obj->LastAnimStepZ = 0;
+
+ uint16 nbGroups = *((uint16 *)(tempAnim.Ptr + 2));
+
+ obj->LastAnimStepAlpha = 0;
+ obj->LastAnimStepBeta = 0;
+ obj->LastAnimStepGamma = 0;
+ obj->LastOfsIsPtr = 0;
+
+ uint32 lastOfsFrame = nbGroups * 8 + 8; // infos frame + 4 WORDs per group
+
+ obj->LastNbGroups = nbGroups;
+ obj->NextNbGroups = nbGroups;
+ obj->NbGroups = nbGroups;
+
+ lastOfsFrame *= frame;
+ uint32 timerRefHR = 0; // Replace with actual TimerRefHR
+
+ lastOfsFrame += 8; // Skip header
+
+ obj->LastTimer = timerRefHR;
+ obj->Time = timerRefHR;
+ obj->Status = 1; // STATUS_FRAME
+ obj->LastOfsFrame = lastOfsFrame;
+ obj->LastFrame = frame;
+
+ uint32 ecx = nbGroups * 2 - 2; // 2 DWORDs per group, no group 0
+ T_PTR_NUM ebpPtr = tempAnim;
+ tempAnim.Ptr = tempAnim.Ptr + lastOfsFrame + 16;
+
+ memcpy(obj->CurrentFrame, tempAnim.Ptr, ecx);
+
+ if (++frame == obj->NbFrames) {
+ uint16 time = *((uint16 *)(ebpPtr.Ptr + 8));
+ frame = 0;
+ tempAnim.Ptr = (void *)(8);
+ } else {
+ uint16 time = *((uint16 *)tempAnim.Ptr);
+ tempAnim.Ptr -= ebpPtr.Ptr;
+ tempAnim.Num += obj->LastTimer;
+ obj->NextFrame = frame;
+ obj->NextOfsFrame = (uint32)(tempAnim.Ptr);
+ obj->NextTimer = time;
+ obj->Master = *((uint16 *)(tempAnim.Ptr + 8));
+ obj->Status = 1; // STATUS_FRAME
+ }
+#endif
+}
+
void Actor::initSprite(int32 spriteNum, int32 actorIdx) {
ActorStruct *localActor = _engine->_scene->getActor(actorIdx);
diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index 428e8e20341..f05a42d439d 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -76,12 +76,12 @@ struct StaticFlagsStruct {
uint32 bIsCarrierActor : 1; // 0x004000 OBJ_CARRIER - can carry and move an obj
// take smaller value for bound, or if not set take average for bound
uint32 bUseMiniZv : 1; // 0x008000 MINI_ZV - square on smaller dimension (if 3D object)
- uint32 bHasInvalidPosition : 1; // 0x010000
- uint32 bNoElectricShock : 1; // 0x020000 NO_CHOC
- uint32 bHasSpriteAnim3D : 1; // 0x040000
- uint32 bNoPreClipping : 1; // 0x080000
- uint32 bHasZBuffer : 1; // 0x100000
- uint32 bHasZBufferInWater : 1; // 0x200000
+ uint32 bHasInvalidPosition : 1; // 0x010000 POS_INVALIDE - carrier considered as an invalid position
+ uint32 bNoElectricShock : 1; // 0x020000 NO_CHOC - does not trigger electric shock animation
+ uint32 bHasSpriteAnim3D : 1; // 0x040000 ANIM_3DS - 3DS animation (extension of 3D sprite)
+ uint32 bNoPreClipping : 1; // 0x080000 NO_PRE_CLIP - does not pre-clip the object (for large objects)
+ uint32 bHasZBuffer : 1; // 0x100000 OBJ_ZBUFFER - displays object in ZBuffer (exterior only!)
+ uint32 bHasZBufferInWater : 1; // 0x200000 OBJ_IN_WATER - displays object in ZBuffer in water (exterior only!)
};
/** Actors dynamic flags structure */
@@ -183,6 +183,14 @@ public:
int16 _actorIdx = 0; // own actor index
IVec3 _pos; // PosObjX, PosObjY, PosObjZ
+
+ // T_ANIM_3DS - Coord.A3DS
+ struct A3DSAnim {
+ int32 Num;
+ int32 Deb;
+ int32 Fin;
+ } A3DS;
+
int32 _strengthOfHit = 0;
int32 _hitBy = -1;
BonusParameter _bonusParameter;
@@ -315,6 +323,7 @@ public:
int16 _heroAnimIdx[4];
void initSprite(int32 spriteNum, int32 actorIdx);
+ void setFrame(int32 actorIdx, uint32 frame);
/** Restart hero variables while opening new scenes */
void restartHeroScene();
diff --git a/engines/twine/script/script_life_v2.cpp b/engines/twine/script/script_life_v2.cpp
index 86f54356817..bcb783a5a9c 100644
--- a/engines/twine/script/script_life_v2.cpp
+++ b/engines/twine/script/script_life_v2.cpp
@@ -22,6 +22,7 @@
#include "twine/script/script_life_v2.h"
#include "twine/audio/sound.h"
#include "twine/movies.h"
+#include "twine/parser/anim3ds.h"
#include "twine/renderer/redraw.h"
#include "twine/renderer/renderer.h"
#include "twine/renderer/screens.h"
@@ -611,18 +612,17 @@ int32 ScriptLifeV2::lSET_SPRITE(TwinEEngine *engine, LifeScriptContext &ctx) {
}
int32 ScriptLifeV2::lSET_FRAME_3DS(TwinEEngine *engine, LifeScriptContext &ctx) {
- const int sprite = ctx.stream.readByte();
+ int sprite = ctx.stream.readByte();
debugC(3, kDebugLevels::kDebugScripts, "LIFE::lSET_FRAME_3DS(%i)", (int)sprite);
if (ctx.actor->_staticFlags.bHasSpriteAnim3D) {
- // TODO:
- // if (sprite > (ListAnim3DS[ptrobj->Coord.A3DS.Num].Fin - ListAnim3DS[ptrobj->Coord.A3DS.Num].Deb)) {
- // sprite = ListAnim3DS[ptrobj->Coord.A3DS.Num].Fin - ListAnim3DS[ptrobj->Coord.A3DS.Num].Deb;
- // }
- // sprite += ListAnim3DS[ptrobj->Coord.A3DS.Num].Deb;
-
+ const T_ANIM_3DS *anim = engine->_resources->getAnim(ctx.actor->A3DS.Num);
+ if (sprite >= anim->Fin - anim->Deb) {
+ sprite = anim->Fin - anim->Deb;
+ }
+ sprite += anim->Deb;
engine->_actor->initSprite(sprite, ctx.actorIdx);
}
- return -1;
+ return 0;
}
int32 ScriptLifeV2::lIMPACT_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) {
diff --git a/engines/twine/script/script_move_v2.cpp b/engines/twine/script/script_move_v2.cpp
index e9178864654..1614c7e0240 100644
--- a/engines/twine/script/script_move_v2.cpp
+++ b/engines/twine/script/script_move_v2.cpp
@@ -20,6 +20,7 @@
*/
#include "twine/script/script_move_v2.h"
+#include "twine/resources/resources.h"
#include "twine/twine.h"
namespace TwinE {
@@ -155,11 +156,26 @@ int32 ScriptMoveV2::mSPRITE(TwinEEngine *engine, MoveScriptContext &ctx) {
}
int32 ScriptMoveV2::mSET_FRAME(TwinEEngine *engine, MoveScriptContext &ctx) {
- return -1;
+ const uint8 num = ctx.stream.readByte();
+ if (!ctx.actor->_staticFlags.bIsSpriteActor) {
+ engine->_actor->setFrame(ctx.actorIdx, num);
+ }
+ return 0;
}
int32 ScriptMoveV2::mSET_FRAME_3DS(TwinEEngine *engine, MoveScriptContext &ctx) {
- return -1;
+ int32 num = ctx.stream.readByte();
+ if (ctx.actor->_staticFlags.bHasSpriteAnim3D) {
+ const T_ANIM_3DS *anim = engine->_resources->getAnim(ctx.actor->A3DS.Num);
+ if (num > (anim->Fin - anim->Deb)) {
+ num = anim->Fin - anim->Deb;
+ }
+
+ num += anim->Deb;
+
+ engine->_actor->initSprite(num, ctx.actorIdx);
+ }
+ return 0;
}
int32 ScriptMoveV2::mSET_START_3DS(TwinEEngine *engine, MoveScriptContext &ctx) {
Commit: 8ff7ab977d536373cdf200447d82597e2377c65a
https://github.com/scummvm/scummvm/commit/8ff7ab977d536373cdf200447d82597e2377c65a
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2024-08-14T17:29:46+02:00
Commit Message:
TWINE: LBA2: added further life opcodes
Changed paths:
engines/twine/parser/anim3ds.cpp
engines/twine/script/script_life.cpp
engines/twine/script/script_life_v2.cpp
diff --git a/engines/twine/parser/anim3ds.cpp b/engines/twine/parser/anim3ds.cpp
index 961708b6ed4..dd335ec2565 100644
--- a/engines/twine/parser/anim3ds.cpp
+++ b/engines/twine/parser/anim3ds.cpp
@@ -20,6 +20,7 @@
*/
#include "twine/parser/anim3ds.h"
+#include "common/debug.h"
namespace TwinE {
@@ -27,9 +28,10 @@ bool Anim3DSData::loadFromStream(Common::SeekableReadStream &stream, bool lba1)
assert(!lba1);
const int n = (int)stream.size() / 8;
+ debug("preload %i anim3ds entries", n);
for (int i = 0; i < n; ++i) {
T_ANIM_3DS anim;
- stream.read(anim.Name, 4);
+ stream.read(anim.Name, sizeof(anim.Name));
anim.Deb = stream.readSint16LE();
anim.Fin = stream.readSint16LE();
_anims.push_back(anim);
diff --git a/engines/twine/script/script_life.cpp b/engines/twine/script/script_life.cpp
index d886ef213dd..7237bc0ab3a 100644
--- a/engines/twine/script/script_life.cpp
+++ b/engines/twine/script/script_life.cpp
@@ -1644,6 +1644,9 @@ int32 ScriptLife::lCLR_HOLO_POS(TwinEEngine *engine, LifeScriptContext &ctx) {
int32 ScriptLife::lADD_FUEL(TwinEEngine *engine, LifeScriptContext &ctx) {
const int16 value = ctx.stream.readByte();
debugC(3, kDebugLevels::kDebugScripts, "LIFE::ADD_FUEL(%i)", (int)value);
+ if (engine->isLBA2()) {
+ return 0;
+ }
engine->_gameState->addGas(value);
return 0;
}
@@ -1655,6 +1658,9 @@ int32 ScriptLife::lADD_FUEL(TwinEEngine *engine, LifeScriptContext &ctx) {
int32 ScriptLife::lSUB_FUEL(TwinEEngine *engine, LifeScriptContext &ctx) {
const int16 value = ctx.stream.readByte();
debugC(3, kDebugLevels::kDebugScripts, "LIFE::SUB_FUEL(%i)", (int)value);
+ if (engine->isLBA2()) {
+ return 0;
+ }
engine->_gameState->addGas(-value);
return 0;
}
diff --git a/engines/twine/script/script_life_v2.cpp b/engines/twine/script/script_life_v2.cpp
index bcb783a5a9c..337f8c633c8 100644
--- a/engines/twine/script/script_life_v2.cpp
+++ b/engines/twine/script/script_life_v2.cpp
@@ -641,23 +641,47 @@ int32 ScriptLifeV2::lIMPACT_POINT(TwinEEngine *engine, LifeScriptContext &ctx) {
const uint8 brickTrackId = ctx.stream.readByte();
const uint16 n = ctx.stream.readUint16LE();
debugC(3, kDebugLevels::kDebugScripts, "LIFE::lIMPACT_POINT(%i, %i)", (int)brickTrackId, (int)n);
- // int16 x0 = ListBrickTrack[brickTrackId].x;
- // int16 y0 = ListBrickTrack[brickTrackId].y;
- // int16 z0 = ListBrickTrack[brickTrackId].z;
+ // const IVec3 &pos = engine->_scene->_sceneTracks[brickTrackId];
+ // int16 x0 = pos.x;
+ // int16 y0 = pos.y;
+ // int16 z0 = pos.z;
// TODO: DoImpact(n, x0, y0, z0, ctx.actorIdx);
return -1;
}
+// ECHELLE
int32 ScriptLifeV2::lLADDER(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ const uint8 num = ctx.stream.readByte();
+ const uint8 info = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lLADDER(%i, %i)", (int)num, (int)info);
+ int n = 0;
+ while (n < engine->_scene->_sceneNumZones) {
+ ZoneStruct &zone = engine->_scene->_sceneZones[n];
+ if (zone.type == ZoneType::kLadder && zone.num == num) {
+ zone.infoData.generic.info1 = (int32)info;
+ }
+ ++n;
+ }
+ return 0;
}
+// SET_ARMURE
int32 ScriptLifeV2::lSET_ARMOR(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ const int8 armor = ctx.stream.readSByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lSET_ARMOR(%i)", (int)armor);
+ ctx.actor->_armor = (int32)armor;
+ return 0;
}
+// SET_ARMURE_OBJ
int32 ScriptLifeV2::lSET_ARMOR_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ const uint8 num = ctx.stream.readByte();
+ const int8 armor = ctx.stream.readSByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lSET_ARMOR_OBJ(%i, %i)", (int)num, (int)armor);
+ if (ActorStruct *actor = engine->_scene->getActor(num)) {
+ actor->_armor = (int32)armor;
+ }
+ return 0;
}
int32 ScriptLifeV2::lADD_LIFE_POINT_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) {
@@ -665,6 +689,10 @@ int32 ScriptLifeV2::lADD_LIFE_POINT_OBJ(TwinEEngine *engine, LifeScriptContext &
}
int32 ScriptLifeV2::lSTATE_INVENTORY(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const uint8 num = ctx.stream.readByte(); // num vargame
+ const uint8 idObj3D = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lSTATE_INVENTORY(%i, %i)", (int)num, (int)idObj3D);
+ // TODO: TabInv[num].IdObj3D = idObj3D;
return -1;
}
Commit: 617ba4154d3c8faea900ce191d92faea3421f723
https://github.com/scummvm/scummvm/commit/617ba4154d3c8faea900ce191d92faea3421f723
Author: Martin Gerhardy (martin.gerhardy at gmail.com)
Date: 2024-08-14T17:29:46+02:00
Commit Message:
TWINE: LBA2: implemented more opcodes
Changed paths:
engines/twine/audio/music.h
engines/twine/menu/interface.h
engines/twine/scene/actor.h
engines/twine/scene/scene.cpp
engines/twine/scene/scene.h
engines/twine/script/script_life.cpp
engines/twine/script/script_life_v2.cpp
engines/twine/shared.h
diff --git a/engines/twine/audio/music.h b/engines/twine/audio/music.h
index 818e3ec9b32..d580553e2a8 100644
--- a/engines/twine/audio/music.h
+++ b/engines/twine/audio/music.h
@@ -51,6 +51,12 @@ private:
Audio::SoundHandle _midiHandle;
/** Track number of the current playing music */
int32 currentMusic = -1;
+public:
+ // TODO: implement the handling
+ int32 _nextMusic = -1; // lba2: NextMusic
+ int32 _nextMusicTimer; // lba2: NextMusicTimer
+ bool _stopLastMusic = false; // lba2: StopLastMusic
+private:
/**
* Play CD music
* @param track track number to play
diff --git a/engines/twine/menu/interface.h b/engines/twine/menu/interface.h
index 1b60a59c95f..0c2696723b0 100644
--- a/engines/twine/menu/interface.h
+++ b/engines/twine/menu/interface.h
@@ -41,6 +41,7 @@ private:
public:
Interface(TwinEEngine *engine);
Common::Rect _clip { 0, 0, 0, 0 };
+ bool _animateTexture = false; // lba2: AnimateTexture
/**
* Draw button line
diff --git a/engines/twine/scene/actor.h b/engines/twine/scene/actor.h
index f05a42d439d..0b751dfb6f9 100644
--- a/engines/twine/scene/actor.h
+++ b/engines/twine/scene/actor.h
@@ -245,6 +245,8 @@ public:
uint8 _brickSound = 0U; // CodeJeu
int32 SampleAlways = 0; // lba2
uint8 SampleVolume = 0; // lba2
+ // SizeSHit contains the number of the brick under the wagon - hack
+ int16 SizeSHit; // lba2 - always square
BoundingBox _boundingBox; // Xmin, YMin, Zmin, Xmax, Ymax, Zmax
ActorMoveStruct realAngle;
diff --git a/engines/twine/scene/scene.cpp b/engines/twine/scene/scene.cpp
index bb68aded887..9191395d8a4 100644
--- a/engines/twine/scene/scene.cpp
+++ b/engines/twine/scene/scene.cpp
@@ -673,11 +673,13 @@ void Scene::initSceneVars() {
}
void Scene::playSceneMusic() {
- if (_currentSceneIdx == LBA1SceneId::Tippet_Island_Twinsun_Cafe && _engine->_gameState->hasArrivedHamalayi()) {
- _engine->_music->playTrackMusic(8);
- } else {
- _engine->_music->playMidiMusic(_sceneMusic);
+ if (_engine->isLBA1()) {
+ if (_currentSceneIdx == LBA1SceneId::Tippet_Island_Twinsun_Cafe && _engine->_gameState->hasArrivedHamalayi()) {
+ _engine->_music->playTrackMusic(8);
+ return;
+ }
}
+ _engine->_music->playMidiMusic(_sceneMusic);
}
void Scene::processEnvironmentSound() {
diff --git a/engines/twine/scene/scene.h b/engines/twine/scene/scene.h
index 7dfc81df009..d5bf6d66b7b 100644
--- a/engines/twine/scene/scene.h
+++ b/engines/twine/scene/scene.h
@@ -146,8 +146,9 @@ private:
int16 _samplePlayed = 0;
- int16 _sceneMusic = 0;
-
+public:
+ int16 _sceneMusic = 0; // CubeJingle
+private:
IVec3 _sceneHeroPos;
IVec3 _zoneHeroPos;
diff --git a/engines/twine/script/script_life.cpp b/engines/twine/script/script_life.cpp
index 7237bc0ab3a..c2fccd6dbff 100644
--- a/engines/twine/script/script_life.cpp
+++ b/engines/twine/script/script_life.cpp
@@ -924,8 +924,10 @@ int32 ScriptLife::lMESSAGE(TwinEEngine *engine, LifeScriptContext &ctx) {
}
engine->_text->drawTextProgressive(textIdx);
- if (engine->_scene->_currentSceneIdx == LBA1SceneId::Principal_Island_Library && engine->_scene->_talkingActor == 8 && textIdx == TextId::kStarWarsFanBoy) {
- engine->unlockAchievement("LBA_ACH_008");
+ if (engine->isLBA1()) {
+ if (engine->_scene->_currentSceneIdx == LBA1SceneId::Principal_Island_Library && engine->_scene->_talkingActor == 8 && textIdx == TextId::kStarWarsFanBoy) {
+ engine->unlockAchievement("LBA_ACH_008");
+ }
}
engine->_redraw->redrawEngineActions(true);
diff --git a/engines/twine/script/script_life_v2.cpp b/engines/twine/script/script_life_v2.cpp
index 337f8c633c8..fee9c3e3452 100644
--- a/engines/twine/script/script_life_v2.cpp
+++ b/engines/twine/script/script_life_v2.cpp
@@ -21,7 +21,9 @@
#include "twine/script/script_life_v2.h"
#include "twine/audio/sound.h"
+#include "twine/audio/music.h"
#include "twine/movies.h"
+#include "twine/menu/interface.h"
#include "twine/parser/anim3ds.h"
#include "twine/renderer/redraw.h"
#include "twine/renderer/renderer.h"
@@ -215,8 +217,15 @@ int32 ScriptLifeV2::lFADE_TO_PAL(TwinEEngine *engine, LifeScriptContext &ctx) {
int32 ScriptLifeV2::lPLAY_MUSIC(TwinEEngine *engine, LifeScriptContext &ctx) {
debugC(3, kDebugLevels::kDebugScripts, "LIFE::lPLAY_MUSIC()");
- // TODO: game var 157 is checked here
- return lPLAY_CD_TRACK(engine, ctx);
+ const int32 val = lPLAY_CD_TRACK(engine, ctx);
+ if (engine->isLBA2()) {
+ engine->_scene->_sceneMusic = 255;
+ engine->_music->_nextMusic = -1;
+ if (engine->_gameState->hasGameFlag(157) > 0) {
+ engine->_music->_stopLastMusic = false;
+ }
+ }
+ return val;
}
int32 ScriptLifeV2::lTRACK_TO_VAR_GAME(TwinEEngine *engine, LifeScriptContext &ctx) {
@@ -429,18 +438,32 @@ int32 ScriptLifeV2::lVAR_GAME_TO_TRACK(TwinEEngine *engine, LifeScriptContext &c
}
int32 ScriptLifeV2::lANIM_TEXTURE(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ engine->_interface->_animateTexture = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lANIM_TEXTURE(%i)", (int)engine->_interface->_animateTexture);
+ return 0;
}
int32 ScriptLifeV2::lADD_MESSAGE_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const TextId textIdx = (TextId)ctx.stream.readSint16LE();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lADD_MESSAGE_OBJ(%i)", (int)textIdx);
+ // TODO: implement me
return -1;
}
int32 ScriptLifeV2::lADD_MESSAGE(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const TextId textIdx = (TextId)ctx.stream.readSint16LE();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lADD_MESSAGE(%i)", (int)textIdx);
+ // TODO: implement me
return -1;
}
int32 ScriptLifeV2::lCAMERA_CENTER(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const int32 angle = ClampAngle(ToAngle(ctx.stream.readByte() * 1024));
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lCAMERA_CENTER(%i)", (int)angle);
+ // TODO: implement me - see centerOnActor in grid
+ // AddBetaCam = num ;
+ // CameraCenter( 2 ) ;
+ // FirstTime = AFF_ALL_FLIP ;
return -1;
}
@@ -458,6 +481,9 @@ int32 ScriptLifeV2::lNO_CHOC(TwinEEngine *engine, LifeScriptContext &ctx) {
}
int32 ScriptLifeV2::lCINEMA_MODE(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const uint8 val = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lCINEMA_MODE(%i)", (int)val);
+ // TODO: implement me
return -1;
}
@@ -576,14 +602,37 @@ int32 ScriptLifeV2::lINIT_BUGGY(TwinEEngine *engine, LifeScriptContext &ctx) {
}
int32 ScriptLifeV2::lMEMO_ARDOISE(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const uint8 num = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lMEMO_ARDOISE(%i)", (int)num);
+ if (engine->_gameState->hasGameFlag(GAMEFLAG_ARDOISE)) {
+ // TODO: implement me
+ }
return -1;
}
int32 ScriptLifeV2::lSET_CHANGE_CUBE(TwinEEngine *engine, LifeScriptContext &ctx) {
- return -1;
+ const uint8 num = ctx.stream.readByte();
+ const uint8 info = ctx.stream.readByte();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lSET_CHANGE_CUBE(%i, %i)", (int)num, (int)info);
+ int n = 0;
+ while (n < engine->_scene->_sceneNumZones) {
+ ZoneStruct &zone = engine->_scene->_sceneZones[n];
+ if (zone.type == ZoneType::kCube && zone.num == num) {
+ if (info) {
+ zone.infoData.generic.info7 |= ZONE_ON;
+ } else {
+ zone.infoData.generic.info7 &= ~ZONE_ON;
+ }
+ }
+ ++n;
+ }
+ return 0;
}
int32 ScriptLifeV2::lMESSAGE_ZOE(TwinEEngine *engine, LifeScriptContext &ctx) {
+ const int16 textIdx = ctx.stream.readSint16LE();
+ debugC(3, kDebugLevels::kDebugScripts, "LIFE::lMESSAGE_ZOE(%i)", (int)textIdx);
+ // TODO: implement me
return -1;
}
@@ -871,13 +920,13 @@ int32 ScriptLifeV2::lINVERSE_BETA(TwinEEngine *engine, LifeScriptContext &ctx) {
// to be clean
APtObj = ctx.actor;
+#endif
- // SizeSHit contains the number of the brick under the wagon
+ // SizeSHit contains the number of the brick under the wagon hack
// test front axle position
engine->_wagon->AdjustEssieuWagonAvant(ctx.actor->SizeSHit);
// test rear axle position
engine->_wagon->AdjustEssieuWagonArriere(ctx.actor->SizeSHit);
-#endif
}
// To tell an object that it is no longer being carried by me
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 03c95aeb00a..b8cc099766b 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -81,6 +81,8 @@
// lba2 Kashes or Zlitos
#define GAMEFLAG_MONEY 8
+// FLAG_ARDOISE
+#define GAMEFLAG_ARDOISE 28
#define OWN_ACTOR_SCENE_INDEX 0
#define IS_HERO(x) ((x) == OWN_ACTOR_SCENE_INDEX)
@@ -736,6 +738,7 @@ inline int32 NormalizeAngle(int32 angle) {
* @return The value as it is used at runtime
*/
inline constexpr int32 ToAngle(int32 angle) {
+ // TODO: lba2 handling of factor 4
return angle;
}
More information about the Scummvm-git-logs
mailing list