mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 18:02:05 +00:00
1632 lines
48 KiB
C++
1632 lines
48 KiB
C++
/* 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/actor.h"
|
|
#include "twine/animations.h"
|
|
#include "twine/collision.h"
|
|
#include "twine/flamovies.h"
|
|
#include "twine/gamestate.h"
|
|
#include "twine/grid.h"
|
|
#include "twine/holomap.h"
|
|
#include "twine/interface.h"
|
|
#include "twine/keyboard.h"
|
|
#include "twine/movements.h"
|
|
#include "twine/music.h"
|
|
#include "twine/redraw.h"
|
|
#include "twine/renderer.h"
|
|
#include "twine/resources.h"
|
|
#include "twine/scene.h"
|
|
#include "twine/screens.h"
|
|
#include "twine/script_life.h"
|
|
#include "twine/sound.h"
|
|
#include "twine/text.h"
|
|
|
|
namespace TwinE {
|
|
|
|
static uint8 *scriptPtr; // local script pointer
|
|
static uint8 *opcodePtr; // local opcode script pointer
|
|
|
|
static int32 drawVar1;
|
|
static char textStr[256]; // string
|
|
|
|
/** Returns:
|
|
-1 - Need implementation
|
|
0 - Completed
|
|
1 - Break script */
|
|
typedef int32 ScriptLifeFunc(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor);
|
|
|
|
struct ScriptLifeFunction {
|
|
const char *name;
|
|
ScriptLifeFunc *function;
|
|
};
|
|
|
|
#define MAPFUNC(name, func) \
|
|
{ name, func }
|
|
|
|
/** Script condition operators */
|
|
enum LifeScriptOperators {
|
|
/*==*/kEqualTo = 0,
|
|
/*> */ kGreaterThan = 1,
|
|
/*< */ kLessThan = 2,
|
|
/*>=*/kGreaterThanOrEqualTo = 3,
|
|
/*<=*/kLessThanOrEqualTo = 4,
|
|
/*!=*/kNotEqualTo = 5
|
|
};
|
|
|
|
/** Script condition command opcodes */
|
|
enum LifeScriptConditions {
|
|
/*0x00*/ kcCOL = 0,
|
|
/*0x01*/ kcCOL_OBJ = 1,
|
|
/*0x02*/ kcDISTANCE = 2,
|
|
/*0x03*/ kcZONE = 3,
|
|
/*0x04*/ kcZONE_OBJ = 4,
|
|
/*0x05*/ kcBODY = 5,
|
|
/*0x06*/ kcBODY_OBJ = 6,
|
|
/*0x07*/ kcANIM = 7,
|
|
/*0x08*/ kcANIM_OBJ = 8,
|
|
/*0x09*/ kcL_TRACK = 9,
|
|
/*0x0A*/ kcL_TRACK_OBJ = 10,
|
|
/*0x0B*/ kcFLAG_CUBE = 11,
|
|
/*0x0C*/ kcCONE_VIEW = 12,
|
|
/*0x0D*/ kcHIT_BY = 13,
|
|
/*0x0E*/ kcACTION = 14,
|
|
/*0x0F*/ kcFLAG_GAME = 15,
|
|
/*0x10*/ kcLIFE_POINT = 16,
|
|
/*0x11*/ kcLIFE_POINT_OBJ = 17,
|
|
/*0x12*/ kcNUM_LITTLE_KEYS = 18,
|
|
/*0x13*/ kcNUM_GOLD_PIECES = 19,
|
|
/*0x14*/ kcBEHAVIOUR = 20,
|
|
/*0x15*/ kcCHAPTER = 21,
|
|
/*0x16*/ kcDISTANCE_3D = 22,
|
|
/*0x17 - 23 unused */
|
|
/*0x18 - 24 unused */
|
|
/*0x19*/ kcUSE_INVENTORY = 25,
|
|
/*0x1A*/ kcCHOICE = 26,
|
|
/*0x1B*/ kcFUEL = 27,
|
|
/*0x1C*/ kcCARRIED_BY = 28,
|
|
/*0x1D*/ kcCDROM = 29
|
|
};
|
|
|
|
/** Returns:
|
|
-1 - Need implementation
|
|
1 - Condition value size (1 byte)
|
|
2 - Condition value size (2 byes) */
|
|
static int32 processLifeConditions(TwinEEngine *engine, ActorStruct *actor) {
|
|
int32 conditionOpcode, conditionValueSize;
|
|
|
|
conditionValueSize = 1;
|
|
conditionOpcode = *(scriptPtr++);
|
|
|
|
switch (conditionOpcode) {
|
|
case kcCOL:
|
|
if (actor->life <= 0) {
|
|
engine->_scene->currentScriptValue = -1;
|
|
} else {
|
|
engine->_scene->currentScriptValue = actor->collision;
|
|
}
|
|
break;
|
|
case kcCOL_OBJ: {
|
|
int32 actorIdx = *(scriptPtr++);
|
|
if (engine->_scene->sceneActors[actorIdx].life <= 0) {
|
|
engine->_scene->currentScriptValue = -1;
|
|
} else {
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneActors[actorIdx].collision;
|
|
}
|
|
} break;
|
|
case kcDISTANCE: {
|
|
ActorStruct *otherActor;
|
|
int32 actorIdx = *(scriptPtr++);
|
|
conditionValueSize = 2;
|
|
otherActor = &engine->_scene->sceneActors[actorIdx];
|
|
if (!otherActor->dynamicFlags.bIsDead) {
|
|
if (ABS(actor->y - otherActor->y) >= 1500) {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
} else {
|
|
// Returns int32, so we check for integer overflow
|
|
int32 distance = engine->_movements->getDistance2D(actor->x, actor->z, otherActor->x, otherActor->z);
|
|
if (ABS(distance) > MAX_TARGET_ACTOR_DISTANCE) {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
} else {
|
|
engine->_scene->currentScriptValue = distance;
|
|
}
|
|
}
|
|
} else {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
}
|
|
} break;
|
|
case kcZONE:
|
|
engine->_scene->currentScriptValue = actor->zone;
|
|
break;
|
|
case kcZONE_OBJ: {
|
|
int32 actorIdx = *(scriptPtr++);
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneActors[actorIdx].zone;
|
|
} break;
|
|
case kcBODY:
|
|
engine->_scene->currentScriptValue = actor->body;
|
|
break;
|
|
case kcBODY_OBJ: {
|
|
int32 actorIdx = *(scriptPtr++);
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneActors[actorIdx].body;
|
|
} break;
|
|
case kcANIM:
|
|
engine->_scene->currentScriptValue = actor->anim;
|
|
break;
|
|
case kcANIM_OBJ: {
|
|
int32 actorIdx = *(scriptPtr++);
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneActors[actorIdx].anim;
|
|
} break;
|
|
case kcL_TRACK:
|
|
engine->_scene->currentScriptValue = actor->labelIdx;
|
|
break;
|
|
case kcL_TRACK_OBJ: {
|
|
int32 actorIdx = *(scriptPtr++);
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneActors[actorIdx].labelIdx;
|
|
} break;
|
|
case kcFLAG_CUBE: {
|
|
int32 flagIdx = *(scriptPtr++);
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneFlags[flagIdx];
|
|
} break;
|
|
case kcCONE_VIEW: {
|
|
int32 newAngle;
|
|
int32 targetActorIdx;
|
|
ActorStruct *targetActor;
|
|
|
|
newAngle = 0;
|
|
targetActorIdx = *(scriptPtr++);
|
|
targetActor = &engine->_scene->sceneActors[targetActorIdx];
|
|
|
|
conditionValueSize = 2;
|
|
|
|
if (!targetActor->dynamicFlags.bIsDead) {
|
|
if (ABS(targetActor->y - actor->y) < 1500) {
|
|
newAngle = engine->_movements->getAngleAndSetTargetActorDistance(actor->x, actor->z, targetActor->x, targetActor->z);
|
|
if (ABS(engine->_movements->targetActorDistance) > MAX_TARGET_ACTOR_DISTANCE) {
|
|
engine->_movements->targetActorDistance = MAX_TARGET_ACTOR_DISTANCE;
|
|
}
|
|
} else {
|
|
engine->_movements->targetActorDistance = MAX_TARGET_ACTOR_DISTANCE;
|
|
}
|
|
|
|
if (!targetActorIdx) {
|
|
int32 heroAngle;
|
|
|
|
heroAngle = actor->angle + 0x480 - newAngle + 0x400;
|
|
heroAngle &= 0x3FF;
|
|
|
|
if (ABS(heroAngle) > 0x100) {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
} else {
|
|
engine->_scene->currentScriptValue = engine->_movements->targetActorDistance;
|
|
}
|
|
} else {
|
|
if (engine->_actor->heroBehaviour == kDiscrete) {
|
|
int32 heroAngle;
|
|
|
|
heroAngle = actor->angle + 0x480 - newAngle + 0x400;
|
|
heroAngle &= 0x3FF;
|
|
|
|
if (ABS(heroAngle) > 0x100) {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
} else {
|
|
engine->_scene->currentScriptValue = engine->_movements->targetActorDistance;
|
|
}
|
|
} else {
|
|
engine->_scene->currentScriptValue = engine->_movements->targetActorDistance;
|
|
}
|
|
}
|
|
} else {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
}
|
|
} break;
|
|
case kcHIT_BY:
|
|
engine->_scene->currentScriptValue = actor->hitBy;
|
|
break;
|
|
case kcACTION:
|
|
engine->_scene->currentScriptValue = engine->_movements->heroAction;
|
|
break;
|
|
case kcFLAG_GAME: {
|
|
int32 flagIdx = *(scriptPtr++);
|
|
if (!engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED] ||
|
|
(engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED] && flagIdx >= 28)) {
|
|
engine->_scene->currentScriptValue = engine->_gameState->gameFlags[flagIdx];
|
|
} else {
|
|
if (flagIdx == GAMEFLAG_INVENTORY_DISABLED) {
|
|
engine->_scene->currentScriptValue = engine->_gameState->gameFlags[flagIdx];
|
|
} else {
|
|
engine->_scene->currentScriptValue = 0;
|
|
}
|
|
}
|
|
} break;
|
|
case kcLIFE_POINT:
|
|
engine->_scene->currentScriptValue = actor->life;
|
|
break;
|
|
case kcLIFE_POINT_OBJ: {
|
|
int32 actorIdx = *(scriptPtr++);
|
|
engine->_scene->currentScriptValue = engine->_scene->sceneActors[actorIdx].life;
|
|
} break;
|
|
case kcNUM_LITTLE_KEYS:
|
|
engine->_scene->currentScriptValue = engine->_gameState->inventoryNumKeys;
|
|
break;
|
|
case kcNUM_GOLD_PIECES:
|
|
conditionValueSize = 2;
|
|
engine->_scene->currentScriptValue = engine->_gameState->inventoryNumKashes;
|
|
break;
|
|
case kcBEHAVIOUR:
|
|
engine->_scene->currentScriptValue = engine->_actor->heroBehaviour;
|
|
break;
|
|
case kcCHAPTER:
|
|
engine->_scene->currentScriptValue = engine->_gameState->gameChapter;
|
|
break;
|
|
case kcDISTANCE_3D: {
|
|
int32 targetActorIdx;
|
|
ActorStruct *targetActor;
|
|
|
|
targetActorIdx = *(scriptPtr++);
|
|
targetActor = &engine->_scene->sceneActors[targetActorIdx];
|
|
|
|
conditionValueSize = 2;
|
|
|
|
if (!targetActor->dynamicFlags.bIsDead) {
|
|
// Returns int32, so we check for integer overflow
|
|
int32 distance = engine->_movements->getDistance3D(actor->x, actor->y, actor->z, targetActor->x, targetActor->y, targetActor->z);
|
|
if (ABS(distance) > MAX_TARGET_ACTOR_DISTANCE) {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
} else {
|
|
engine->_scene->currentScriptValue = distance;
|
|
}
|
|
} else {
|
|
engine->_scene->currentScriptValue = MAX_TARGET_ACTOR_DISTANCE;
|
|
}
|
|
} break;
|
|
case 23: // unused
|
|
case 24:
|
|
break;
|
|
case kcUSE_INVENTORY: {
|
|
int32 item = *(scriptPtr++);
|
|
|
|
if (!engine->_gameState->gameFlags[GAMEFLAG_INVENTORY_DISABLED]) {
|
|
if (item == engine->loopInventoryItem) {
|
|
engine->_scene->currentScriptValue = 1;
|
|
} else {
|
|
if (engine->_gameState->inventoryFlags[item] == 1 && engine->_gameState->gameFlags[item] == 1) {
|
|
engine->_scene->currentScriptValue = 1;
|
|
} else {
|
|
engine->_scene->currentScriptValue = 0;
|
|
}
|
|
}
|
|
|
|
if (engine->_scene->currentScriptValue == 1) {
|
|
engine->_redraw->addOverlay(koInventoryItem, item, 0, 0, 0, koNormal, 3);
|
|
}
|
|
} else {
|
|
engine->_scene->currentScriptValue = 0;
|
|
}
|
|
} break;
|
|
case kcCHOICE:
|
|
conditionValueSize = 2;
|
|
engine->_scene->currentScriptValue = engine->_gameState->choiceAnswer;
|
|
break;
|
|
case kcFUEL:
|
|
engine->_scene->currentScriptValue = engine->_gameState->inventoryNumGas;
|
|
break;
|
|
case kcCARRIED_BY:
|
|
engine->_scene->currentScriptValue = actor->standOn;
|
|
break;
|
|
case kcCDROM:
|
|
engine->_scene->currentScriptValue = 1;
|
|
break;
|
|
default:
|
|
error("Actor condition opcode %d\n", conditionOpcode);
|
|
break;
|
|
}
|
|
|
|
return conditionValueSize;
|
|
}
|
|
|
|
/** Returns:
|
|
-1 - Need implementation
|
|
0 - Condition false
|
|
1 - Condition true */
|
|
static int32 processLifeOperators(TwinEEngine *engine, int32 valueSize) {
|
|
int32 operatorCode, conditionValue;
|
|
|
|
operatorCode = *(scriptPtr++);
|
|
|
|
if (valueSize == 1) {
|
|
conditionValue = *(scriptPtr++);
|
|
} else if (valueSize == 2) {
|
|
conditionValue = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
} else {
|
|
error("Unknown operator value size %d\n", valueSize);
|
|
return 0;
|
|
}
|
|
|
|
switch (operatorCode) {
|
|
case kEqualTo:
|
|
if (engine->_scene->currentScriptValue == conditionValue) {
|
|
return 1;
|
|
}
|
|
break;
|
|
case kGreaterThan:
|
|
if (engine->_scene->currentScriptValue > conditionValue) {
|
|
return 1;
|
|
}
|
|
break;
|
|
case kLessThan:
|
|
if (engine->_scene->currentScriptValue < conditionValue) {
|
|
return 1;
|
|
}
|
|
break;
|
|
case kGreaterThanOrEqualTo:
|
|
if (engine->_scene->currentScriptValue >= conditionValue) {
|
|
return 1;
|
|
}
|
|
break;
|
|
case kLessThanOrEqualTo:
|
|
if (engine->_scene->currentScriptValue <= conditionValue) {
|
|
return 1;
|
|
}
|
|
break;
|
|
case kNotEqualTo:
|
|
if (engine->_scene->currentScriptValue != conditionValue) {
|
|
return 1;
|
|
}
|
|
break;
|
|
default:
|
|
error("Actor operator opcode %d\n", operatorCode);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** Life script command definitions */
|
|
|
|
/* For unused opcodes */
|
|
static int32 lEMPTY(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
return 0;
|
|
}
|
|
|
|
/*0x00*/
|
|
static int32 lEND(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->positionInLifeScript = -1;
|
|
return 1; // break script
|
|
}
|
|
|
|
/*0x01*/
|
|
static int32 lNOP(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
scriptPtr++;
|
|
return 0;
|
|
}
|
|
|
|
/*0x02*/
|
|
static int32 lSNIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 valueSize = processLifeConditions(engine, actor);
|
|
if (!processLifeOperators(engine, valueSize)) {
|
|
*opcodePtr = 13; // SWIF
|
|
}
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
|
|
return 0;
|
|
}
|
|
|
|
/*0x03*/
|
|
static int32 lOFFSET(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // offset
|
|
return 0;
|
|
}
|
|
|
|
/*0x04*/
|
|
static int32 lNEVERIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 valueSize = processLifeConditions(engine, actor);
|
|
processLifeOperators(engine, valueSize);
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
|
|
return 0;
|
|
}
|
|
|
|
/*0x06*/
|
|
static int32 lNO_IF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
return 0;
|
|
}
|
|
|
|
/*0x0A*/
|
|
static int32 lLABEL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
scriptPtr++;
|
|
return 0;
|
|
}
|
|
|
|
/*0x0B*/
|
|
static int32 lRETURN(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
return 1; // break script
|
|
}
|
|
|
|
/*0x0C*/
|
|
static int32 lIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 valueSize = processLifeConditions(engine, actor);
|
|
if (!processLifeOperators(engine, valueSize)) {
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
|
|
} else {
|
|
scriptPtr += 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x0D*/
|
|
static int32 lSWIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 valueSize = processLifeConditions(engine, actor);
|
|
if (!processLifeOperators(engine, valueSize)) {
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
|
|
} else {
|
|
scriptPtr += 2;
|
|
*opcodePtr = 2; // SNIF
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x0E*/
|
|
static int32 lONEIF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 valueSize = processLifeConditions(engine, actor);
|
|
if (!processLifeOperators(engine, valueSize)) {
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
|
|
} else {
|
|
scriptPtr += 2;
|
|
*opcodePtr = 4; // NEVERIF
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x0F*/
|
|
static int32 lELSE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // offset
|
|
return 0;
|
|
}
|
|
|
|
/*0x11*/
|
|
static int32 lBODY(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 bodyIdx = *(scriptPtr);
|
|
engine->_actor->initModelActor(bodyIdx, actorIdx);
|
|
scriptPtr++;
|
|
return 0;
|
|
}
|
|
|
|
/*0x12*/
|
|
static int32 lBODY_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
int32 otherBodyIdx = *(scriptPtr++);
|
|
engine->_actor->initModelActor(otherBodyIdx, otherActorIdx);
|
|
return 0;
|
|
}
|
|
|
|
/*0x13*/
|
|
static int32 lANIM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
AnimationTypes animIdx = (AnimationTypes)*(scriptPtr++);
|
|
engine->_animations->initAnim(animIdx, 0, 0, actorIdx);
|
|
return 0;
|
|
}
|
|
|
|
/*0x14*/
|
|
static int32 lANIM_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
AnimationTypes otherAnimIdx = (AnimationTypes)*(scriptPtr++);
|
|
engine->_animations->initAnim(otherAnimIdx, 0, 0, otherActorIdx);
|
|
return 0;
|
|
}
|
|
|
|
/*0x15*/
|
|
static int32 lSET_LIFE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->positionInLifeScript = *((int16 *)scriptPtr); // offset
|
|
scriptPtr += 2;
|
|
return 0;
|
|
}
|
|
|
|
/*0x16*/
|
|
static int32 lSET_LIFE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
engine->_scene->sceneActors[otherActorIdx].positionInLifeScript = *((int16 *)scriptPtr); // offset
|
|
scriptPtr += 2;
|
|
return 0;
|
|
}
|
|
|
|
/*0x17*/
|
|
static int32 lSET_TRACK(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->positionInMoveScript = *((int16 *)scriptPtr); // offset
|
|
scriptPtr += 2;
|
|
return 0;
|
|
}
|
|
|
|
/*0x18*/
|
|
static int32 lSET_TRACK_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
engine->_scene->sceneActors[otherActorIdx].positionInMoveScript = *((int16 *)scriptPtr); // offset
|
|
scriptPtr += 2;
|
|
return 0;
|
|
}
|
|
|
|
/*0x19*/
|
|
static int32 lMESSAGE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 textIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->freezeTime();
|
|
if (engine->_text->showDialogueBubble) {
|
|
engine->_redraw->drawBubble(actorIdx);
|
|
}
|
|
engine->_text->setFontCrossColor(actor->talkColor);
|
|
engine->_scene->talkingActor = actorIdx;
|
|
engine->_text->drawTextFullscreen(textIdx);
|
|
engine->unfreezeTime();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x1A*/
|
|
static int32 lFALLABLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 flag = *(scriptPtr++);
|
|
actor->staticFlags.bCanFall = flag & 1;
|
|
return 0;
|
|
}
|
|
|
|
/*0x1B*/
|
|
static int32 lSET_DIRMODE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 controlMode = *(scriptPtr++);
|
|
|
|
actor->controlMode = controlMode;
|
|
if (controlMode == kFollow) {
|
|
actor->followedActor = *(scriptPtr++);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x1C*/
|
|
static int32 lSET_DIRMODE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
int32 controlMode = *(scriptPtr++);
|
|
|
|
engine->_scene->sceneActors[otherActorIdx].controlMode = controlMode;
|
|
if (controlMode == kFollow) {
|
|
engine->_scene->sceneActors[otherActorIdx].followedActor = *(scriptPtr++);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x1D*/
|
|
static int32 lCAM_FOLLOW(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 followedActorIdx;
|
|
followedActorIdx = *(scriptPtr++);
|
|
|
|
if (engine->_scene->currentlyFollowedActor != followedActorIdx) {
|
|
engine->_grid->newCameraX = engine->_scene->sceneActors[followedActorIdx].x >> 9;
|
|
engine->_grid->newCameraY = engine->_scene->sceneActors[followedActorIdx].y >> 8;
|
|
engine->_grid->newCameraZ = engine->_scene->sceneActors[followedActorIdx].z >> 9;
|
|
|
|
engine->_scene->currentlyFollowedActor = followedActorIdx;
|
|
engine->_redraw->reqBgRedraw = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x1E*/
|
|
static int32 lSET_BEHAVIOUR(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 behavior = *(scriptPtr++);
|
|
|
|
engine->_animations->initAnim(kStanding, 0, 255, 0);
|
|
engine->_actor->setBehaviour(behavior);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x1F*/
|
|
static int32 lSET_FLAG_CUBE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 flagIdx = *(scriptPtr++);
|
|
int32 flagValue = *(scriptPtr++);
|
|
|
|
engine->_scene->sceneFlags[flagIdx] = flagValue;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x20*/
|
|
static int32 lCOMPORTEMENT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
scriptPtr++;
|
|
return 0;
|
|
}
|
|
|
|
/*0x21*/
|
|
static int32 lSET_COMPORTEMENT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->positionInLifeScript = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
return 0;
|
|
}
|
|
|
|
/*0x22*/
|
|
static int32 lSET_COMPORTEMENT_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
|
|
engine->_scene->sceneActors[otherActorIdx].positionInLifeScript = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x23*/
|
|
static int32 lEND_COMPORTEMENT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
return 1; // break
|
|
}
|
|
|
|
/*0x24*/
|
|
static int32 lSET_FLAG_GAME(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 flagIdx = *(scriptPtr++);
|
|
int32 flagValue = *(scriptPtr++);
|
|
|
|
engine->_gameState->gameFlags[flagIdx] = flagValue;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x25*/
|
|
static int32 lKILL_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
|
|
engine->_actor->processActorCarrier(otherActorIdx);
|
|
engine->_scene->sceneActors[otherActorIdx].dynamicFlags.bIsDead = 1;
|
|
engine->_scene->sceneActors[otherActorIdx].entity = -1;
|
|
engine->_scene->sceneActors[otherActorIdx].zone = -1;
|
|
engine->_scene->sceneActors[otherActorIdx].life = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x26*/
|
|
static int32 lSUICIDE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_actor->processActorCarrier(actorIdx);
|
|
actor->dynamicFlags.bIsDead = 1;
|
|
actor->entity = -1;
|
|
actor->zone = -1;
|
|
actor->life = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x27*/
|
|
static int32 lUSE_ONE_LITTLE_KEY(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_gameState->inventoryNumKeys--;
|
|
|
|
if (engine->_gameState->inventoryNumKeys < 0) {
|
|
engine->_gameState->inventoryNumKeys = 0;
|
|
}
|
|
|
|
engine->_redraw->addOverlay(koSprite, SPRITEHQR_KEY, 0, 0, 0, koFollowActor, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x28*/
|
|
static int32 lGIVE_GOLD_PIECES(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int16 kashes, i, hideRange;
|
|
int16 oldNumKashes = engine->_gameState->inventoryNumKashes;
|
|
|
|
hideRange = 0;
|
|
|
|
kashes = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->_gameState->inventoryNumKashes -= kashes;
|
|
if (engine->_gameState->inventoryNumKashes < 0) {
|
|
engine->_gameState->inventoryNumKashes = 0;
|
|
}
|
|
|
|
engine->_redraw->addOverlay(koSprite, SPRITEHQR_KASHES, 10, 15, 0, koNormal, 3);
|
|
|
|
for (i = 0; i < OVERLAY_MAX_ENTRIES; i++) {
|
|
OverlayListStruct *overlay = &engine->_redraw->overlayList[i];
|
|
if (overlay->info0 != -1 && overlay->type == koNumberRange) {
|
|
overlay->info0 = engine->_collision->getAverageValue(overlay->info1, overlay->info0, 100, overlay->lifeTime - engine->lbaTime - 50);
|
|
overlay->info1 = engine->_gameState->inventoryNumKashes;
|
|
overlay->lifeTime = engine->lbaTime + 150;
|
|
hideRange = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!hideRange) {
|
|
engine->_redraw->addOverlay(koNumberRange, oldNumKashes, 50, 20, engine->_gameState->inventoryNumKashes, koNormal, 3);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x29*/
|
|
static int32 lEND_LIFE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->positionInLifeScript = -1;
|
|
return 1; // break;
|
|
}
|
|
|
|
/*0x2A*/
|
|
static int32 lSTOP_L_TRACK(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->pausedTrackPtr = actor->currentLabelPtr;
|
|
actor->positionInMoveScript = -1;
|
|
return 0;
|
|
}
|
|
|
|
/*0x2B*/
|
|
static int32 lRESTORE_L_TRACK(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->positionInMoveScript = actor->pausedTrackPtr;
|
|
return 0;
|
|
}
|
|
|
|
/*0x2C*/
|
|
static int32 lMESSAGE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
int32 textIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->freezeTime();
|
|
if (engine->_text->showDialogueBubble) {
|
|
engine->_redraw->drawBubble(otherActorIdx);
|
|
}
|
|
engine->_text->setFontCrossColor(engine->_scene->sceneActors[otherActorIdx].talkColor);
|
|
engine->_scene->talkingActor = otherActorIdx;
|
|
engine->_text->drawTextFullscreen(textIdx);
|
|
engine->unfreezeTime();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x2D*/
|
|
static int32 lINC_CHAPTER(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_gameState->gameChapter++;
|
|
return 0;
|
|
}
|
|
|
|
/*0x2E*/
|
|
static int32 lFOUND_OBJECT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 item = *(scriptPtr++);
|
|
|
|
engine->freezeTime();
|
|
engine->_gameState->processFoundItem(item);
|
|
engine->unfreezeTime();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x2F*/
|
|
static int32 lSET_DOOR_LEFT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 distance = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
actor->angle = 0x300;
|
|
actor->x = actor->lastX - distance;
|
|
actor->dynamicFlags.bIsSpriteMoving = 0;
|
|
actor->speed = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x30*/
|
|
static int32 lSET_DOOR_RIGHT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 distance = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
actor->angle = 0x100;
|
|
actor->x = actor->lastX + distance;
|
|
actor->dynamicFlags.bIsSpriteMoving = 0;
|
|
actor->speed = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x31*/
|
|
static int32 lSET_DOOR_UP(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 distance = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
actor->angle = 0x200;
|
|
actor->z = actor->lastZ - distance;
|
|
actor->dynamicFlags.bIsSpriteMoving = 0;
|
|
actor->speed = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x32*/
|
|
static int32 lSET_DOOR_DOWN(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 distance = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
actor->angle = 0;
|
|
actor->z = actor->lastZ + distance;
|
|
actor->dynamicFlags.bIsSpriteMoving = 0;
|
|
actor->speed = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x33*/
|
|
static int32 lGIVE_BONUS(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 flag = *(scriptPtr++);
|
|
|
|
if (actor->bonusParameter & 0x1F0) {
|
|
engine->_actor->processActorExtraBonus(actorIdx);
|
|
}
|
|
|
|
if (flag != 0) {
|
|
actor->bonusParameter |= 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x34*/
|
|
static int32 lCHANGE_CUBE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 sceneIdx = *(scriptPtr++);
|
|
engine->_scene->needChangeScene = sceneIdx;
|
|
engine->_scene->heroPositionType = kScene;
|
|
return 0;
|
|
}
|
|
|
|
/*0x35*/
|
|
static int32 lOBJ_COL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 collision = *(scriptPtr++);
|
|
if (collision != 0) {
|
|
actor->staticFlags.bComputeCollisionWithObj = 1;
|
|
} else {
|
|
actor->staticFlags.bComputeCollisionWithObj = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x36*/
|
|
static int32 lBRICK_COL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 collision = *(scriptPtr++);
|
|
|
|
actor->staticFlags.bComputeCollisionWithBricks = 0;
|
|
actor->staticFlags.bComputeLowCollision = 0;
|
|
|
|
if (collision == 1) {
|
|
actor->staticFlags.bComputeCollisionWithBricks = 1;
|
|
} else if (collision == 2) {
|
|
actor->staticFlags.bComputeCollisionWithBricks = 1;
|
|
actor->staticFlags.bComputeLowCollision = 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x37*/
|
|
static int32 lOR_IF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 valueSize = processLifeConditions(engine, actor);
|
|
if (processLifeOperators(engine, valueSize)) {
|
|
scriptPtr = actor->lifeScript + *((int16 *)scriptPtr); // condition offset
|
|
} else {
|
|
scriptPtr += 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x38*/
|
|
static int32 lINVISIBLE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
actor->staticFlags.bIsHidden = *(scriptPtr++);
|
|
return 0;
|
|
}
|
|
|
|
/*0x39*/
|
|
static int32 lZOOM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->zoomScreen = *(scriptPtr++);
|
|
|
|
if (engine->zoomScreen && !engine->_redraw->drawInGameTransBox && engine->cfgfile.SceZoom) {
|
|
engine->_screens->fadeToBlack(engine->_screens->mainPaletteRGBA);
|
|
engine->initMCGA();
|
|
engine->_screens->setBackPal();
|
|
engine->_screens->lockPalette = 1;
|
|
} else if (!engine->zoomScreen && engine->_redraw->drawInGameTransBox) {
|
|
engine->_screens->fadeToBlack(engine->_screens->mainPaletteRGBA);
|
|
engine->initSVGA();
|
|
engine->_screens->setBackPal();
|
|
engine->_screens->lockPalette = 1;
|
|
engine->_redraw->reqBgRedraw = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x3A*/
|
|
static int32 lPOS_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 trackIdx = *(scriptPtr++);
|
|
|
|
engine->_renderer->destX = engine->_scene->sceneTracks[trackIdx].x;
|
|
engine->_renderer->destY = engine->_scene->sceneTracks[trackIdx].y;
|
|
engine->_renderer->destZ = engine->_scene->sceneTracks[trackIdx].z;
|
|
|
|
actor->x = engine->_renderer->destX;
|
|
actor->y = engine->_renderer->destY;
|
|
actor->z = engine->_renderer->destZ;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x3B*/
|
|
static int32 lSET_MAGIC_LEVEL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_gameState->magicLevelIdx = *(scriptPtr++);
|
|
engine->_gameState->inventoryMagicPoints = engine->_gameState->magicLevelIdx * 20;
|
|
return 0;
|
|
}
|
|
|
|
/*0x3C*/
|
|
static int32 lSUB_MAGIC_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_gameState->inventoryMagicPoints = *(scriptPtr++);
|
|
if (engine->_gameState->inventoryMagicPoints < 0) {
|
|
engine->_gameState->inventoryMagicPoints = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x3D*/
|
|
static int32 lSET_LIFE_POINT_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
static int32 lifeValue = *(scriptPtr++);
|
|
|
|
engine->_scene->sceneActors[otherActorIdx].life = lifeValue;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x3E*/
|
|
static int32 lSUB_LIFE_POINT_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
static int32 lifeValue = *(scriptPtr++);
|
|
|
|
engine->_scene->sceneActors[otherActorIdx].life -= lifeValue;
|
|
|
|
if (engine->_scene->sceneActors[otherActorIdx].life < 0) {
|
|
engine->_scene->sceneActors[otherActorIdx].life = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x3F*/
|
|
static int32 lHIT_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
int32 strengthOfHit = *(scriptPtr++);
|
|
engine->_actor->hitActor(actorIdx, otherActorIdx, strengthOfHit, engine->_scene->sceneActors[otherActorIdx].angle);
|
|
return 0;
|
|
}
|
|
|
|
/*0x40*/
|
|
static int32 lPLAY_FLA(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
const char *movie = (const char *)scriptPtr;
|
|
int32 nameSize = strlen(movie);
|
|
scriptPtr += nameSize + 1;
|
|
|
|
engine->_flaMovies->playFlaMovie(movie);
|
|
engine->setPalette(engine->_screens->paletteRGBA);
|
|
engine->_screens->clearScreen();
|
|
engine->flip();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x41*/
|
|
static int32 lPLAY_MIDI(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 midiIdx = *(scriptPtr++);
|
|
engine->_music->playMidiMusic(midiIdx, 0); // TODO: improve this
|
|
return 0;
|
|
}
|
|
|
|
/*0x42*/
|
|
static int32 lINC_CLOVER_BOX(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
if (engine->_gameState->inventoryNumLeafsBox < 10) {
|
|
engine->_gameState->inventoryNumLeafsBox++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x43*/
|
|
static int32 lSET_USED_INVENTORY(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 item = *(scriptPtr++);
|
|
if (item < 24) {
|
|
engine->_gameState->inventoryFlags[item] = 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x44*/
|
|
static int32 lADD_CHOICE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 choiceIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
engine->_gameState->gameChoices[engine->_gameState->numChoices++] = choiceIdx;
|
|
return 0;
|
|
}
|
|
|
|
/*0x45*/
|
|
static int32 lASK_CHOICE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 choiceIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->freezeTime();
|
|
if (engine->_text->showDialogueBubble) {
|
|
engine->_redraw->drawBubble(actorIdx);
|
|
}
|
|
engine->_text->setFontCrossColor(actor->talkColor);
|
|
engine->_gameState->processGameChoices(choiceIdx);
|
|
engine->_gameState->numChoices = 0;
|
|
engine->unfreezeTime();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x46*/
|
|
static int32 lBIG_MESSAGE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 textIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->freezeTime();
|
|
engine->_text->textClipFull();
|
|
if (engine->_text->showDialogueBubble) {
|
|
engine->_redraw->drawBubble(actorIdx);
|
|
}
|
|
engine->_text->setFontCrossColor(actor->talkColor);
|
|
engine->_scene->talkingActor = actorIdx;
|
|
engine->_text->drawTextFullscreen(textIdx);
|
|
engine->_text->textClipSmall();
|
|
engine->unfreezeTime();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x47*/
|
|
static int32 lINIT_PINGOUIN(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 pingouinActor = *(scriptPtr++);
|
|
engine->_scene->sceneActors[pingouinActor].dynamicFlags.bIsDead = 1;
|
|
engine->_scene->mecaPinguinIdx = pingouinActor;
|
|
engine->_scene->sceneActors[pingouinActor].entity = -1;
|
|
engine->_scene->sceneActors[pingouinActor].zone = -1;
|
|
return 0;
|
|
}
|
|
|
|
/*0x48*/
|
|
static int32 lSET_HOLO_POS(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
static int32 location = *(scriptPtr++);
|
|
|
|
engine->_holomap->setHolomapPosition(location);
|
|
if (engine->_gameState->gameFlags[InventoryItems::kiHolomap]) {
|
|
engine->_redraw->addOverlay(koInventoryItem, 0, 0, 0, 0, koNormal, 3);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x49*/
|
|
static int32 lCLR_HOLO_POS(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
static int32 location = *(scriptPtr++);
|
|
engine->_holomap->clearHolomapPosition(location);
|
|
return 0;
|
|
}
|
|
|
|
/*0x4A*/
|
|
static int32 lADD_FUEL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_gameState->inventoryNumGas += *(scriptPtr++);
|
|
if (engine->_gameState->inventoryNumGas > 100) {
|
|
engine->_gameState->inventoryNumGas = 100;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x4B*/
|
|
static int32 lSUB_FUEL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_gameState->inventoryNumGas -= *(scriptPtr++);
|
|
if (engine->_gameState->inventoryNumGas < 0) {
|
|
engine->_gameState->inventoryNumGas = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x4C*/
|
|
static int32 lSET_GRM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_grid->cellingGridIdx = *(scriptPtr++);
|
|
engine->_grid->initCellingGrid(engine->_grid->cellingGridIdx);
|
|
return 0;
|
|
}
|
|
|
|
/*0x4D*/
|
|
static int32 lSAY_MESSAGE(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int16 textEntry = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->_redraw->addOverlay(koText, textEntry, 0, 0, actorIdx, koFollowActor, 2);
|
|
|
|
engine->freezeTime();
|
|
engine->_text->initVoxToPlay(textEntry);
|
|
engine->unfreezeTime();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*04E*/
|
|
static int32 lSAY_MESSAGE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
int16 textEntry = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->_redraw->addOverlay(koText, textEntry, 0, 0, otherActorIdx, koFollowActor, 2);
|
|
|
|
engine->freezeTime();
|
|
engine->_text->initVoxToPlay(textEntry);
|
|
engine->unfreezeTime();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x4F*/
|
|
static int32 lFULL_POINT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_scene->sceneHero->life = 50;
|
|
engine->_gameState->inventoryMagicPoints = engine->_gameState->magicLevelIdx * 20;
|
|
return 0;
|
|
}
|
|
|
|
/*0x50*/
|
|
static int32 lBETA(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 newAngle = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
actor->angle = newAngle;
|
|
engine->_movements->clearRealAngle(actor);
|
|
return 0;
|
|
}
|
|
|
|
/*0x51*/
|
|
static int32 lGRM_OFF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
if (engine->_grid->cellingGridIdx != -1) {
|
|
engine->_grid->useCellingGrid = -1;
|
|
engine->_grid->cellingGridIdx = -1;
|
|
engine->_grid->createGridMap();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x52*/
|
|
static int32 lFADE_PAL_RED(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_screens->fadePalRed(engine->_screens->mainPaletteRGBA);
|
|
engine->_screens->useAlternatePalette = 0;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x53*/
|
|
static int32 lFADE_ALARM_RED(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_hqrdepack->hqrGetEntry(engine->_screens->palette, Resources::HQR_RESS_FILE, RESSHQR_ALARMREDPAL);
|
|
engine->_screens->convertPalToRGBA(engine->_screens->palette, engine->_screens->paletteRGBA);
|
|
engine->_screens->fadePalRed(engine->_screens->paletteRGBA);
|
|
engine->_screens->useAlternatePalette = 1;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x54*/
|
|
static int32 lFADE_ALARM_PAL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_hqrdepack->hqrGetEntry(engine->_screens->palette, Resources::HQR_RESS_FILE, RESSHQR_ALARMREDPAL);
|
|
engine->_screens->convertPalToRGBA(engine->_screens->palette, engine->_screens->paletteRGBA);
|
|
engine->_screens->adjustCrossPalette(engine->_screens->paletteRGBA, engine->_screens->mainPaletteRGBA);
|
|
engine->_screens->useAlternatePalette = 0;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x55*/
|
|
static int32 lFADE_RED_PAL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_screens->fadeRedPal(engine->_screens->mainPaletteRGBA);
|
|
engine->_screens->useAlternatePalette = 0;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x56*/
|
|
static int32 lFADE_RED_ALARM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_hqrdepack->hqrGetEntry(engine->_screens->palette, Resources::HQR_RESS_FILE, RESSHQR_ALARMREDPAL);
|
|
engine->_screens->convertPalToRGBA(engine->_screens->palette, engine->_screens->paletteRGBA);
|
|
engine->_screens->fadeRedPal(engine->_screens->paletteRGBA);
|
|
engine->_screens->useAlternatePalette = 1;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x57*/
|
|
static int32 lFADE_PAL_ALARM(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_hqrdepack->hqrGetEntry(engine->_screens->palette, Resources::HQR_RESS_FILE, RESSHQR_ALARMREDPAL);
|
|
engine->_screens->convertPalToRGBA(engine->_screens->palette, engine->_screens->paletteRGBA);
|
|
engine->_screens->adjustCrossPalette(engine->_screens->mainPaletteRGBA, engine->_screens->paletteRGBA);
|
|
engine->_screens->useAlternatePalette = 1;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x58*/
|
|
static int32 lEXPLODE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
ActorStruct *otherActor = &engine->_scene->sceneActors[otherActorIdx];
|
|
|
|
engine->_extra->addExtraExplode(otherActor->x, otherActor->y, otherActor->z); // RECHECK this
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x59*/
|
|
static int32 lBUBBLE_ON(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_text->showDialogueBubble = 1;
|
|
return 0;
|
|
}
|
|
|
|
/*0x5A*/
|
|
static int32 lBUBBLE_OFF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_text->showDialogueBubble = 1;
|
|
return 0;
|
|
}
|
|
|
|
/*0x5B*/
|
|
static int32 lASK_CHOICE_OBJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 otherActorIdx = *(scriptPtr++);
|
|
int32 choiceIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
engine->freezeTime();
|
|
if (engine->_text->showDialogueBubble) {
|
|
engine->_redraw->drawBubble(otherActorIdx);
|
|
}
|
|
engine->_text->setFontCrossColor(engine->_scene->sceneActors[otherActorIdx].talkColor);
|
|
engine->_gameState->processGameChoices(choiceIdx);
|
|
engine->_gameState->numChoices = 0;
|
|
engine->unfreezeTime();
|
|
engine->_redraw->redrawEngineActions(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x5C*/
|
|
static int32 lSET_DARK_PAL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->freezeTime();
|
|
engine->_hqrdepack->hqrGetEntry(engine->_screens->palette, Resources::HQR_RESS_FILE, RESSHQR_DARKPAL);
|
|
if (!engine->_screens->lockPalette) {
|
|
engine->_screens->convertPalToRGBA(engine->_screens->palette, engine->_screens->paletteRGBA);
|
|
engine->setPalette(engine->_screens->paletteRGBA);
|
|
}
|
|
engine->_screens->useAlternatePalette = 1;
|
|
engine->unfreezeTime();
|
|
return 0;
|
|
}
|
|
|
|
/*0x5D*/
|
|
static int32 lSET_NORMAL_PAL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_screens->useAlternatePalette = 0;
|
|
if (!engine->_screens->lockPalette) {
|
|
engine->setPalette(engine->_screens->mainPaletteRGBA);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*0x5E*/
|
|
static int32 lMESSAGE_SENDELL(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 tmpFlagDisplayText;
|
|
|
|
engine->freezeTime();
|
|
engine->_screens->fadeToBlack(engine->_screens->paletteRGBA);
|
|
engine->_screens->loadImage(25);
|
|
engine->_text->textClipFull();
|
|
engine->_text->setFontCrossColor(15);
|
|
engine->_text->newGameVar4 = 0;
|
|
tmpFlagDisplayText = engine->cfgfile.FlagDisplayText;
|
|
engine->cfgfile.FlagDisplayText = 1;
|
|
engine->_text->drawTextFullscreen(6);
|
|
engine->_text->newGameVar4 = 1;
|
|
engine->_text->textClipSmall();
|
|
engine->_screens->fadeToBlack(engine->_screens->paletteRGBACustom);
|
|
engine->_screens->clearScreen();
|
|
engine->setPalette(engine->_screens->paletteRGBA);
|
|
engine->cfgfile.FlagDisplayText = tmpFlagDisplayText;
|
|
|
|
do {
|
|
engine->readKeys();
|
|
} while (engine->_keyboard.internalKeyCode || engine->_keyboard.skippedKey);
|
|
|
|
engine->unfreezeTime();
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x5F*/
|
|
static int32 lANIM_SET(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
AnimationTypes animIdx = (AnimationTypes)*(scriptPtr++);
|
|
|
|
actor->anim = kAnimNone;
|
|
actor->previousAnimIdx = -1;
|
|
engine->_animations->initAnim(animIdx, 0, 0, actorIdx);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x60*/
|
|
static int32 lHOLOMAP_TRAJ(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
scriptPtr++; // TODO
|
|
return -1;
|
|
}
|
|
|
|
/*0x61*/
|
|
static int32 lGAME_OVER(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_scene->sceneHero->dynamicFlags.bAnimEnded = 1;
|
|
engine->_scene->sceneHero->life = 0;
|
|
engine->_gameState->inventoryNumLeafs = 0;
|
|
return 1; // break
|
|
}
|
|
|
|
/*0x62*/
|
|
static int32 lTHE_END(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->quitGame = 1;
|
|
engine->_gameState->inventoryNumLeafs = 0;
|
|
engine->_scene->sceneHero->life = 50;
|
|
engine->_gameState->inventoryMagicPoints = 80;
|
|
engine->_scene->currentSceneIdx = 113;
|
|
engine->_actor->heroBehaviour = engine->_actor->previousHeroBehaviour;
|
|
engine->_scene->newHeroX = -1;
|
|
engine->_scene->sceneHero->angle = engine->_actor->previousHeroAngle;
|
|
engine->_gameState->saveGame();
|
|
return 1; // break;
|
|
}
|
|
|
|
/*0x63*/
|
|
static int32 lMIDI_OFF(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_music->stopMidiMusic();
|
|
return 0;
|
|
}
|
|
|
|
/*0x64*/
|
|
static int32 lPLAY_CD_TRACK(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 track = *(scriptPtr++);
|
|
engine->_music->playTrackMusic(track);
|
|
return 0;
|
|
}
|
|
|
|
/*0x65*/
|
|
static int32 lPROJ_ISO(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_renderer->setOrthoProjection(311, 240, 512);
|
|
engine->_renderer->setBaseTranslation(0, 0, 0);
|
|
engine->_renderer->setBaseRotation(0, 0, 0);
|
|
engine->_renderer->setLightVector(engine->_scene->alphaLight, engine->_scene->betaLight, 0);
|
|
return 0;
|
|
}
|
|
|
|
/*0x66*/
|
|
static int32 lPROJ_3D(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->_screens->copyScreen(engine->frontVideoBuffer, engine->workVideoBuffer);
|
|
engine->flip();
|
|
engine->_scene->changeRoomVar10 = 0;
|
|
|
|
engine->_renderer->setCameraPosition(320, 240, 128, 1024, 1024);
|
|
engine->_renderer->setCameraAngle(0, 1500, 0, 25, -128, 0, 13000);
|
|
engine->_renderer->setLightVector(896, 950, 0);
|
|
|
|
engine->_text->initTextBank(1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x67*/
|
|
static int32 lTEXT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
int32 textSize, textBoxRight;
|
|
int32 textIdx = *((int16 *)scriptPtr);
|
|
scriptPtr += 2;
|
|
|
|
if (drawVar1 < 440) {
|
|
if (engine->cfgfile.Version == USA_VERSION) {
|
|
if (!textIdx) {
|
|
textIdx = 16;
|
|
}
|
|
}
|
|
|
|
engine->_text->getMenuText(textIdx, textStr, sizeof(textStr));
|
|
textSize = textBoxRight = engine->_text->getTextSize(textStr);
|
|
engine->_text->setFontColor(15);
|
|
engine->_text->drawText(0, drawVar1, textStr);
|
|
if (textSize > 639) {
|
|
textBoxRight = 639;
|
|
}
|
|
|
|
drawVar1 += 40;
|
|
engine->copyBlockPhys(0, drawVar1, textBoxRight, drawVar1);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*0x68*/
|
|
static int32 lCLEAR_TEXT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
drawVar1 = 0;
|
|
engine->_interface->drawSplittedBox(0, 0, 639, 240, 0);
|
|
engine->copyBlockPhys(0, 0, 639, 240);
|
|
return 0;
|
|
}
|
|
|
|
/*0x69*/
|
|
static int32 lBRUTAL_EXIT(TwinEEngine *engine, int32 actorIdx, ActorStruct *actor) {
|
|
engine->quitGame = 0;
|
|
return 1; // break
|
|
}
|
|
|
|
static const ScriptLifeFunction function_map[] = {
|
|
/*0x00*/ MAPFUNC("END", lEND),
|
|
/*0x01*/ MAPFUNC("NOP", lNOP),
|
|
/*0x02*/ MAPFUNC("SNIF", lSNIF),
|
|
/*0x03*/ MAPFUNC("OFFSET", lOFFSET),
|
|
/*0x04*/ MAPFUNC("NEVERIF", lNEVERIF),
|
|
/*0x05*/ MAPFUNC("", lEMPTY), // unused
|
|
/*0x06*/ MAPFUNC("NO_IF", lNO_IF),
|
|
/*0x07*/ MAPFUNC("", lEMPTY), // unused
|
|
/*0x08*/ MAPFUNC("", lEMPTY), // unused
|
|
/*0x09*/ MAPFUNC("", lEMPTY), // unused
|
|
/*0x0A*/ MAPFUNC("LABEL", lLABEL),
|
|
/*0x0B*/ MAPFUNC("RETURN", lRETURN),
|
|
/*0x0C*/ MAPFUNC("IF", lIF),
|
|
/*0x0D*/ MAPFUNC("SWIF", lSWIF),
|
|
/*0x0E*/ MAPFUNC("ONEIF", lONEIF),
|
|
/*0x0F*/ MAPFUNC("ELSE", lELSE),
|
|
/*0x10*/ MAPFUNC("ENDIF", lEMPTY), // unused
|
|
/*0x11*/ MAPFUNC("BODY", lBODY),
|
|
/*0x12*/ MAPFUNC("BODY_OBJ", lBODY_OBJ),
|
|
/*0x13*/ MAPFUNC("ANIM", lANIM),
|
|
/*0x14*/ MAPFUNC("ANIM_OBJ", lANIM_OBJ),
|
|
/*0x15*/ MAPFUNC("SET_LIFE", lSET_LIFE),
|
|
/*0x16*/ MAPFUNC("SET_LIFE_OBJ", lSET_LIFE_OBJ),
|
|
/*0x17*/ MAPFUNC("SET_TRACK", lSET_TRACK),
|
|
/*0x18*/ MAPFUNC("SET_TRACK_OBJ", lSET_TRACK_OBJ),
|
|
/*0x19*/ MAPFUNC("MESSAGE", lMESSAGE),
|
|
/*0x1A*/ MAPFUNC("FALLABLE", lFALLABLE),
|
|
/*0x1B*/ MAPFUNC("SET_DIRMODE", lSET_DIRMODE),
|
|
/*0x1C*/ MAPFUNC("SET_DIRMODE_OBJ", lSET_DIRMODE_OBJ),
|
|
/*0x1D*/ MAPFUNC("CAM_FOLLOW", lCAM_FOLLOW),
|
|
/*0x1E*/ MAPFUNC("SET_BEHAVIOUR", lSET_BEHAVIOUR),
|
|
/*0x1F*/ MAPFUNC("SET_FLAG_CUBE", lSET_FLAG_CUBE),
|
|
/*0x20*/ MAPFUNC("COMPORTEMENT", lCOMPORTEMENT),
|
|
/*0x21*/ MAPFUNC("SET_COMPORTEMENT", lSET_COMPORTEMENT),
|
|
/*0x22*/ MAPFUNC("SET_COMPORTEMENT_OBJ", lSET_COMPORTEMENT_OBJ),
|
|
/*0x23*/ MAPFUNC("END_COMPORTEMENT", lEND_COMPORTEMENT),
|
|
/*0x24*/ MAPFUNC("SET_FLAG_GAME", lSET_FLAG_GAME),
|
|
/*0x25*/ MAPFUNC("KILL_OBJ", lKILL_OBJ),
|
|
/*0x26*/ MAPFUNC("SUICIDE", lSUICIDE),
|
|
/*0x27*/ MAPFUNC("USE_ONE_LITTLE_KEY", lUSE_ONE_LITTLE_KEY),
|
|
/*0x28*/ MAPFUNC("GIVE_GOLD_PIECES", lGIVE_GOLD_PIECES),
|
|
/*0x29*/ MAPFUNC("END_LIFE", lEND_LIFE),
|
|
/*0x2A*/ MAPFUNC("STOP_L_TRACK", lSTOP_L_TRACK),
|
|
/*0x2B*/ MAPFUNC("RESTORE_L_TRACK", lRESTORE_L_TRACK),
|
|
/*0x2C*/ MAPFUNC("MESSAGE_OBJ", lMESSAGE_OBJ),
|
|
/*0x2D*/ MAPFUNC("INC_CHAPTER", lINC_CHAPTER),
|
|
/*0x2E*/ MAPFUNC("FOUND_OBJECT", lFOUND_OBJECT),
|
|
/*0x2F*/ MAPFUNC("SET_DOOR_LEFT", lSET_DOOR_LEFT),
|
|
/*0x30*/ MAPFUNC("SET_DOOR_RIGHT", lSET_DOOR_RIGHT),
|
|
/*0x31*/ MAPFUNC("SET_DOOR_UP", lSET_DOOR_UP),
|
|
/*0x32*/ MAPFUNC("SET_DOOR_DOWN", lSET_DOOR_DOWN),
|
|
/*0x33*/ MAPFUNC("GIVE_BONUS", lGIVE_BONUS),
|
|
/*0x34*/ MAPFUNC("CHANGE_CUBE", lCHANGE_CUBE),
|
|
/*0x35*/ MAPFUNC("OBJ_COL", lOBJ_COL),
|
|
/*0x36*/ MAPFUNC("BRICK_COL", lBRICK_COL),
|
|
/*0x37*/ MAPFUNC("OR_IF", lOR_IF),
|
|
/*0x38*/ MAPFUNC("INVISIBLE", lINVISIBLE),
|
|
/*0x39*/ MAPFUNC("ZOOM", lZOOM),
|
|
/*0x3A*/ MAPFUNC("POS_POINT", lPOS_POINT),
|
|
/*0x3B*/ MAPFUNC("SET_MAGIC_LEVEL", lSET_MAGIC_LEVEL),
|
|
/*0x3C*/ MAPFUNC("SUB_MAGIC_POINT", lSUB_MAGIC_POINT),
|
|
/*0x3D*/ MAPFUNC("SET_LIFE_POINT_OBJ", lSET_LIFE_POINT_OBJ),
|
|
/*0x3E*/ MAPFUNC("SUB_LIFE_POINT_OBJ", lSUB_LIFE_POINT_OBJ),
|
|
/*0x3F*/ MAPFUNC("HIT_OBJ", lHIT_OBJ),
|
|
/*0x40*/ MAPFUNC("PLAY_FLA", lPLAY_FLA),
|
|
/*0x41*/ MAPFUNC("PLAY_MIDI", lPLAY_MIDI),
|
|
/*0x42*/ MAPFUNC("INC_CLOVER_BOX", lINC_CLOVER_BOX),
|
|
/*0x43*/ MAPFUNC("SET_USED_INVENTORY", lSET_USED_INVENTORY),
|
|
/*0x44*/ MAPFUNC("ADD_CHOICE", lADD_CHOICE),
|
|
/*0x45*/ MAPFUNC("ASK_CHOICE", lASK_CHOICE),
|
|
/*0x46*/ MAPFUNC("BIG_MESSAGE", lBIG_MESSAGE),
|
|
/*0x47*/ MAPFUNC("INIT_PINGOUIN", lINIT_PINGOUIN),
|
|
/*0x48*/ MAPFUNC("SET_HOLO_POS", lSET_HOLO_POS),
|
|
/*0x49*/ MAPFUNC("CLR_HOLO_POS", lCLR_HOLO_POS),
|
|
/*0x4A*/ MAPFUNC("ADD_FUEL", lADD_FUEL),
|
|
/*0x4B*/ MAPFUNC("SUB_FUEL", lSUB_FUEL),
|
|
/*0x4C*/ MAPFUNC("SET_GRM", lSET_GRM),
|
|
/*0x4D*/ MAPFUNC("SAY_MESSAGE", lSAY_MESSAGE),
|
|
/*0x4E*/ MAPFUNC("SAY_MESSAGE_OBJ", lSAY_MESSAGE_OBJ),
|
|
/*0x4F*/ MAPFUNC("FULL_POINT", lFULL_POINT),
|
|
/*0x50*/ MAPFUNC("BETA", lBETA),
|
|
/*0x51*/ MAPFUNC("GRM_OFF", lGRM_OFF),
|
|
/*0x52*/ MAPFUNC("FADE_PAL_RED", lFADE_PAL_RED),
|
|
/*0x53*/ MAPFUNC("FADE_ALARM_RED", lFADE_ALARM_RED),
|
|
/*0x54*/ MAPFUNC("FADE_ALARM_PAL", lFADE_ALARM_PAL),
|
|
/*0x55*/ MAPFUNC("FADE_RED_PAL", lFADE_RED_PAL),
|
|
/*0x56*/ MAPFUNC("FADE_RED_ALARM", lFADE_RED_ALARM),
|
|
/*0x57*/ MAPFUNC("FADE_PAL_ALARM", lFADE_PAL_ALARM),
|
|
/*0x58*/ MAPFUNC("EXPLODE_OBJ", lEXPLODE_OBJ),
|
|
/*0x59*/ MAPFUNC("BUBBLE_ON", lBUBBLE_ON),
|
|
/*0x5A*/ MAPFUNC("BUBBLE_OFF", lBUBBLE_OFF),
|
|
/*0x5B*/ MAPFUNC("ASK_CHOICE_OBJ", lASK_CHOICE_OBJ),
|
|
/*0x5C*/ MAPFUNC("SET_DARK_PAL", lSET_DARK_PAL),
|
|
/*0x5D*/ MAPFUNC("SET_NORMAL_PAL", lSET_NORMAL_PAL),
|
|
/*0x5E*/ MAPFUNC("MESSAGE_SENDELL", lMESSAGE_SENDELL),
|
|
/*0x5F*/ MAPFUNC("ANIM_SET", lANIM_SET),
|
|
/*0x60*/ MAPFUNC("HOLOMAP_TRAJ", lHOLOMAP_TRAJ),
|
|
/*0x61*/ MAPFUNC("GAME_OVER", lGAME_OVER),
|
|
/*0x62*/ MAPFUNC("THE_END", lTHE_END),
|
|
/*0x63*/ MAPFUNC("MIDI_OFF", lMIDI_OFF),
|
|
/*0x64*/ MAPFUNC("PLAY_CD_TRACK", lPLAY_CD_TRACK),
|
|
/*0x65*/ MAPFUNC("PROJ_ISO", lPROJ_ISO),
|
|
/*0x66*/ MAPFUNC("PROJ_3D", lPROJ_3D),
|
|
/*0x67*/ MAPFUNC("TEXT", lTEXT),
|
|
/*0x68*/ MAPFUNC("CLEAR_TEXT", lCLEAR_TEXT),
|
|
/*0x69*/ MAPFUNC("BRUTAL_EXIT", lBRUTAL_EXIT)};
|
|
|
|
ScriptLife::ScriptLife(TwinEEngine *engine) : _engine(engine) {
|
|
scriptPtr = nullptr;
|
|
opcodePtr = nullptr;
|
|
drawVar1 = 0;
|
|
textStr[0] = '\0';
|
|
}
|
|
|
|
void ScriptLife::processLifeScript(int32 actorIdx) {
|
|
int32 end, scriptOpcode;
|
|
ActorStruct *actor;
|
|
|
|
actor = &_engine->_scene->sceneActors[actorIdx];
|
|
scriptPtr = actor->lifeScript + actor->positionInLifeScript;
|
|
|
|
end = -2;
|
|
|
|
do {
|
|
opcodePtr = scriptPtr;
|
|
scriptOpcode = *(scriptPtr++);
|
|
|
|
if (scriptOpcode >= 0 && scriptOpcode < ARRAYSIZE(function_map)) {
|
|
end = function_map[scriptOpcode].function(_engine, actorIdx, actor);
|
|
} else {
|
|
error("Actor %d with wrong offset/opcode - Offset: %d\n", actorIdx, actor->positionInLifeScript);
|
|
}
|
|
|
|
if (end < 0) { // show error message
|
|
warning("Actor %d Life script [%s] not implemented\n", actorIdx, function_map[scriptOpcode].name);
|
|
}
|
|
|
|
} while (end != 1);
|
|
}
|
|
|
|
} // namespace TwinE
|