/* 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 . * */ #include "twine/scene/grid.h" #include "twine/scene/collision.h" #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/scene/animations.h" #include "twine/parser/anim3ds.h" #include "twine/renderer/redraw.h" #include "twine/renderer/renderer.h" #include "twine/renderer/screens.h" #include "twine/resources/resources.h" #include "twine/scene/actor.h" #include "twine/scene/buggy.h" #include "twine/scene/movements.h" #include "twine/scene/wagon.h" #include "twine/script/script_move_v2.h" #include "twine/shared.h" #include "twine/twine.h" namespace TwinE { static const ScriptLifeFunction function_map[] = { {"END", ScriptLife::lEND}, {"NOP", ScriptLife::lNOP}, {"SNIF", ScriptLife::lSNIF}, {"OFFSET", ScriptLife::lOFFSET}, {"NEVERIF", ScriptLife::lNEVERIF}, {"", ScriptLife::lEMPTY}, // unused {"NO_IF", ScriptLife::lNO_IF}, {"", ScriptLife::lEMPTY}, // unused {"", ScriptLife::lEMPTY}, // unused {"", ScriptLife::lEMPTY}, // unused {"PALETTE", ScriptLifeV2::lPALETTE}, {"RETURN", ScriptLife::lRETURN}, {"IF", ScriptLife::lIF}, {"SWIF", ScriptLife::lSWIF}, {"ONEIF", ScriptLife::lONEIF}, {"ELSE", ScriptLife::lELSE}, {"ENDIF", ScriptLife::lEMPTY}, // End of a conditional statement (e.g. IF) {"BODY", ScriptLife::lBODY}, {"BODY_OBJ", ScriptLife::lBODY_OBJ}, {"ANIM", ScriptLife::lANIM}, {"ANIM_OBJ", ScriptLife::lANIM_OBJ}, {"SET_CAMERA", ScriptLifeV2::lSET_CAMERA}, {"CAMERA_CENTER", ScriptLifeV2::lCAMERA_CENTER}, {"SET_TRACK", ScriptLife::lSET_TRACK}, {"SET_TRACK_OBJ", ScriptLife::lSET_TRACK_OBJ}, {"MESSAGE", ScriptLife::lMESSAGE}, {"FALLABLE", ScriptLife::lFALLABLE}, {"SET_DIRMODE", ScriptLife::lSET_DIRMODE}, {"SET_DIRMODE_OBJ", ScriptLife::lSET_DIRMODE_OBJ}, {"CAM_FOLLOW", ScriptLife::lCAM_FOLLOW}, {"SET_BEHAVIOUR", ScriptLife::lSET_BEHAVIOUR}, {"SET_FLAG_CUBE", ScriptLife::lSET_FLAG_CUBE}, {"COMPORTEMENT", ScriptLife::lCOMPORTEMENT}, {"SET_COMPORTEMENT", ScriptLife::lSET_COMPORTEMENT}, {"SET_COMPORTEMENT_OBJ", ScriptLife::lSET_COMPORTEMENT_OBJ}, {"END_COMPORTEMENT", ScriptLife::lEND_COMPORTEMENT}, {"SET_FLAG_GAME", ScriptLifeV2::lSET_FLAG_GAME}, {"KILL_OBJ", ScriptLife::lKILL_OBJ}, {"SUICIDE", ScriptLife::lSUICIDE}, {"USE_ONE_LITTLE_KEY", ScriptLife::lUSE_ONE_LITTLE_KEY}, {"GIVE_GOLD_PIECES", ScriptLife::lGIVE_GOLD_PIECES}, {"END_LIFE", ScriptLife::lEND_LIFE}, {"STOP_L_TRACK", ScriptLife::lSTOP_L_TRACK}, {"RESTORE_L_TRACK", ScriptLife::lRESTORE_L_TRACK}, {"MESSAGE_OBJ", ScriptLife::lMESSAGE_OBJ}, {"INC_CHAPTER", ScriptLife::lINC_CHAPTER}, {"FOUND_OBJECT", ScriptLife::lFOUND_OBJECT}, {"SET_DOOR_LEFT", ScriptLife::lSET_DOOR_LEFT}, {"SET_DOOR_RIGHT", ScriptLife::lSET_DOOR_RIGHT}, {"SET_DOOR_UP", ScriptLife::lSET_DOOR_UP}, {"SET_DOOR_DOWN", ScriptLife::lSET_DOOR_DOWN}, {"GIVE_BONUS", ScriptLife::lGIVE_BONUS}, {"CHANGE_CUBE", ScriptLife::lCHANGE_CUBE}, {"OBJ_COL", ScriptLife::lOBJ_COL}, {"BRICK_COL", ScriptLife::lBRICK_COL}, {"OR_IF", ScriptLife::lOR_IF}, {"INVISIBLE", ScriptLife::lINVISIBLE}, {"SHADOW_OBJ", ScriptLifeV2::lSHADOW_OBJ}, {"POS_POINT", ScriptLife::lPOS_POINT}, {"SET_MAGIC_LEVEL", ScriptLife::lSET_MAGIC_LEVEL}, {"SUB_MAGIC_POINT", ScriptLife::lSUB_MAGIC_POINT}, {"SET_LIFE_POINT_OBJ", ScriptLife::lSET_LIFE_POINT_OBJ}, {"SUB_LIFE_POINT_OBJ", ScriptLife::lSUB_LIFE_POINT_OBJ}, {"HIT_OBJ", ScriptLife::lHIT_OBJ}, {"PLAY_ACF", ScriptLifeV2::lPLAY_ACF}, {"ECLAIR", ScriptLifeV2::lECLAIR}, {"INC_CLOVER_BOX", ScriptLife::lINC_CLOVER_BOX}, {"SET_USED_INVENTORY", ScriptLife::lSET_USED_INVENTORY}, {"ADD_CHOICE", ScriptLife::lADD_CHOICE}, {"ASK_CHOICE", ScriptLife::lASK_CHOICE}, {"INIT_BUGGY", ScriptLifeV2::lINIT_BUGGY}, {"MEMO_ARDOISE", ScriptLifeV2::lMEMO_ARDOISE}, {"SET_HOLO_POS", ScriptLife::lSET_HOLO_POS}, {"CLR_HOLO_POS", ScriptLife::lCLR_HOLO_POS}, {"ADD_FUEL", ScriptLife::lADD_FUEL}, {"SUB_FUEL", ScriptLife::lSUB_FUEL}, {"SET_GRM", ScriptLife::lSET_GRM}, {"SET_CHANGE_CUBE", ScriptLifeV2::lSET_CHANGE_CUBE}, {"MESSAGE_ZOE", ScriptLifeV2::lMESSAGE_ZOE}, // lSAY_MESSAGE {"FULL_POINT", ScriptLife::lFULL_POINT}, {"BETA", ScriptLife::lBETA}, {"FADE_TO_PAL", ScriptLifeV2::lFADE_TO_PAL}, {"ACTION", ScriptLifeV2::lACTION}, {"SET_FRAME", ScriptLifeV2::lSET_FRAME}, {"SET_SPRITE", ScriptLifeV2::lSET_SPRITE}, {"SET_FRAME_3DS", ScriptLifeV2::lSET_FRAME_3DS}, {"IMPACT_OBJ", ScriptLifeV2::lIMPACT_OBJ}, {"IMPACT_POINT", ScriptLifeV2::lIMPACT_POINT}, {"ADD_MESSAGE", ScriptLifeV2::lADD_MESSAGE}, {"BUBBLE", ScriptLifeV2::lBUBBLE}, {"NO_CHOC", ScriptLifeV2::lNO_CHOC}, {"ASK_CHOICE_OBJ", ScriptLife::lASK_CHOICE_OBJ}, {"CINEMA_MODE", ScriptLifeV2::lCINEMA_MODE}, {"SAVE_HERO", ScriptLifeV2::lSAVE_HERO}, {"RESTORE_HERO", ScriptLifeV2::lRESTORE_HERO}, {"ANIM_SET", ScriptLife::lANIM_SET}, {"RAIN", ScriptLifeV2::lRAIN}, // LM_PLUIE {"GAME_OVER", ScriptLife::lGAME_OVER}, {"THE_END", ScriptLife::lTHE_END}, {"ESCALATOR", ScriptLifeV2::lESCALATOR}, {"PLAY_MUSIC", ScriptLifeV2::lPLAY_MUSIC}, {"TRACK_TO_VAR_GAME", ScriptLifeV2::lTRACK_TO_VAR_GAME}, {"VAR_GAME_TO_TRACK", ScriptLifeV2::lVAR_GAME_TO_TRACK}, {"ANIM_TEXTURE", ScriptLifeV2::lANIM_TEXTURE}, {"ADD_MESSAGE_OBJ", ScriptLifeV2::lADD_MESSAGE_OBJ}, {"BRUTAL_EXIT", ScriptLife::lBRUTAL_EXIT}, {"REM", ScriptLife::lEMPTY}, // unused {"LADDER", ScriptLifeV2::lLADDER}, {"SET_ARMOR", ScriptLifeV2::lSET_ARMOR}, {"SET_ARMOR_OBJ", ScriptLifeV2::lSET_ARMOR_OBJ}, {"ADD_LIFE_POINT_OBJ", ScriptLifeV2::lADD_LIFE_POINT_OBJ}, {"STATE_INVENTORY", ScriptLifeV2::lSTATE_INVENTORY}, {"AND_IF", ScriptLifeV2::lAND_IF}, {"SWITCH", ScriptLifeV2::lSWITCH}, {"OR_CASE", ScriptLifeV2::lOR_CASE}, {"CASE", ScriptLifeV2::lCASE}, {"DEFAULT", ScriptLife::lEMPTY}, // unused {"BREAK", ScriptLifeV2::lBREAK}, {"END_SWITCH", ScriptLife::lEMPTY}, // unused {"SET_HIT_ZONE", ScriptLifeV2::lSET_HIT_ZONE}, {"SAVE_COMPORTEMENT", ScriptLifeV2::lSAVE_COMPORTEMENT}, {"RESTORE_COMPORTEMENT", ScriptLifeV2::lRESTORE_COMPORTEMENT}, {"SAMPLE", ScriptLifeV2::lSAMPLE}, {"SAMPLE_RND", ScriptLifeV2::lSAMPLE_RND}, {"SAMPLE_ALWAYS", ScriptLifeV2::lSAMPLE_ALWAYS}, {"SAMPLE_STOP", ScriptLifeV2::lSAMPLE_STOP}, {"REPEAT_SAMPLE", ScriptLifeV2::lREPEAT_SAMPLE}, {"BACKGROUND", ScriptLifeV2::lBACKGROUND}, {"ADD_VAR_GAME", ScriptLifeV2::lADD_VAR_GAME}, {"SUB_VAR_GAME", ScriptLifeV2::lSUB_VAR_GAME}, {"ADD_VAR_CUBE", ScriptLifeV2::lADD_VAR_CUBE}, {"SUB_VAR_CUBE", ScriptLifeV2::lSUB_VAR_CUBE}, {"NOP", ScriptLife::lEMPTY}, // unused {"SET_RAIL", ScriptLifeV2::lSET_RAIL}, {"INVERSE_BETA", ScriptLifeV2::lINVERSE_BETA}, {"NO_BODY", ScriptLifeV2::lNO_BODY}, {"GIVE_GOLD_PIECES", ScriptLife::lGIVE_GOLD_PIECES}, {"STOP_L_TRACK_OBJ", ScriptLifeV2::lSTOP_L_TRACK_OBJ}, {"RESTORE_L_TRACK_OBJ", ScriptLifeV2::lRESTORE_L_TRACK_OBJ}, {"SAVE_COMPORTEMENT_OBJ", ScriptLifeV2::lSAVE_COMPORTEMENT_OBJ}, {"RESTORE_COMPORTEMENT_OBJ", ScriptLifeV2::lRESTORE_COMPORTEMENT_OBJ}, {"SPY", ScriptLife::lEMPTY}, // unused {"DEBUG", ScriptLife::lEMPTY}, // unused {"DEBUG_OBJ", ScriptLife::lEMPTY}, // unused {"POPCORN", ScriptLife::lEMPTY}, // unused {"FLOW_POINT", ScriptLifeV2::lFLOW_POINT}, {"FLOW_OBJ", ScriptLifeV2::lFLOW_OBJ}, {"SET_ANIM_DIAL", ScriptLifeV2::lSET_ANIM_DIAL}, {"PCX", ScriptLifeV2::lPCX}, {"END_MESSAGE", ScriptLifeV2::lEND_MESSAGE}, {"END_MESSAGE_OBJ", ScriptLifeV2::lEND_MESSAGE_OBJ}, {"PARM_SAMPLE", ScriptLifeV2::lPARM_SAMPLE}, {"NEW_SAMPLE", ScriptLifeV2::lNEW_SAMPLE}, {"POS_OBJ_AROUND", ScriptLifeV2::lPOS_OBJ_AROUND}, {"PCX_MESS_OBJ", ScriptLifeV2::lPCX_MESS_OBJ} }; int32 ScriptLifeV2::lPALETTE(TwinEEngine *engine, LifeScriptContext &ctx) { const int32 palIndex = engine->_screens->mapLba2Palette(ctx.stream.readByte()); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::PALETTE(%i)", palIndex); engine->saveTimer(false); HQR::getPaletteEntry(engine->_screens->_ptrPal, Resources::HQR_RESS_FILE, palIndex); engine->setPalette(engine->_screens->_ptrPal); engine->_screens->_flagPalettePcx = true; engine->restoreTimer(); return 0; } int32 ScriptLifeV2::lFADE_TO_PAL(TwinEEngine *engine, LifeScriptContext &ctx) { const int32 palIndex = engine->_screens->mapLba2Palette(ctx.stream.readByte()); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::FADE_TO_PAL(%i)", palIndex); engine->saveTimer(false); HQR::getPaletteEntry(engine->_screens->_ptrPal, Resources::HQR_RESS_FILE, palIndex); engine->_screens->fadeToPal(engine->_screens->_ptrPal); engine->_screens->_flagPalettePcx = true; if (palIndex == 3) { // Black palette? engine->_screens->_flagFade = true; } engine->restoreTimer(); return 0; } int32 ScriptLifeV2::lPLAY_MUSIC(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lPLAY_MUSIC()"); const int32 val = lPLAY_CD_TRACK(engine, ctx); if (engine->isLBA2()) { engine->_scene->_cubeJingle = 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) { const int32 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lTRACK_TO_VAR_GAME(%i)", (int)num); engine->_gameState->setGameFlag(num, MAX(0, ctx.actor->_labelTrack)); return 0; } #define TM_END 0 #define TM_NOP 1 #define TM_BODY 2 #define TM_ANIM 3 #define TM_GOTO_POINT 4 #define TM_WAIT_ANIM 5 #define TM_LOOP 6 #define TM_ANGLE 7 #define TM_POS_POINT 8 #define TM_LABEL 9 #define TM_GOTO 10 #define TM_STOP 11 #define TM_GOTO_SYM_POINT 12 #define TM_WAIT_NB_ANIM 13 #define TM_SAMPLE 14 #define TM_GOTO_POINT_3D 15 #define TM_SPEED 16 #define TM_BACKGROUND 17 #define TM_WAIT_NB_SECOND 18 #define TM_NO_BODY 19 #define TM_BETA 20 #define TM_OPEN_LEFT 21 #define TM_OPEN_RIGHT 22 #define TM_OPEN_UP 23 #define TM_OPEN_DOWN 24 #define TM_CLOSE 25 #define TM_WAIT_DOOR 26 #define TM_SAMPLE_RND 27 #define TM_SAMPLE_ALWAYS 28 #define TM_SAMPLE_STOP 29 #define TM_PLAY_ACF 30 #define TM_REPEAT_SAMPLE 31 #define TM_SIMPLE_SAMPLE 32 #define TM_FACE_TWINSEN 33 #define TM_ANGLE_RND 34 #define TM_REM 35 #define TM_WAIT_NB_DIZIEME 36 #define TM_DO 37 #define TM_SPRITE 38 #define TM_WAIT_NB_SECOND_RND 39 #define TM_AFF_TIMER 40 #define TM_SET_FRAME 41 #define TM_SET_FRAME_3DS 42 #define TM_SET_START_3DS 43 #define TM_SET_END_3DS 44 #define TM_START_ANIM_3DS 45 #define TM_STOP_ANIM_3DS 46 #define TM_WAIT_ANIM_3DS 47 #define TM_WAIT_FRAME_3DS 48 #define TM_WAIT_NB_DIZIEME_RND 49 #define TM_DECALAGE 50 #define TM_FREQUENCE 51 #define TM_VOLUME 52 // Allows forcing a track to a label instead of an offset (basically, like in the tool!) int16 ScriptLifeV2::searchOffsetTrack(ActorStruct *ptrobj, uint8 label) { uint8 *ptrtrack; int16 offsettrack = 0; uint8 macro; for (;;) { ptrtrack = ptrobj->_ptrTrack + offsettrack; macro = *ptrtrack++; offsettrack++; switch (macro) { case TM_LABEL: if (*ptrtrack == label) { ptrobj->_labelTrack = label; /* label */ ptrobj->_offsetLabelTrack = (int16)(offsettrack - 1); return ((int16)(offsettrack - 1)); } offsettrack++; break; case TM_BODY: case TM_GOTO_POINT: case TM_GOTO_POINT_3D: case TM_GOTO_SYM_POINT: case TM_POS_POINT: case TM_BACKGROUND: case TM_SET_FRAME: case TM_SET_FRAME_3DS: case TM_SET_START_3DS: case TM_SET_END_3DS: case TM_START_ANIM_3DS: case TM_WAIT_FRAME_3DS: case TM_VOLUME: offsettrack++; break; case TM_ANIM: case TM_SAMPLE: case TM_SAMPLE_RND: case TM_SAMPLE_ALWAYS: case TM_SAMPLE_STOP: case TM_REPEAT_SAMPLE: case TM_SIMPLE_SAMPLE: case TM_WAIT_NB_ANIM: case TM_ANGLE: case TM_FACE_TWINSEN: case TM_OPEN_LEFT: case TM_OPEN_RIGHT: case TM_OPEN_UP: case TM_OPEN_DOWN: case TM_BETA: case TM_GOTO: case TM_SPEED: case TM_SPRITE: case TM_DECALAGE: case TM_FREQUENCE: offsettrack += 2; break; case TM_ANGLE_RND: case TM_LOOP: offsettrack += 4; break; case TM_WAIT_NB_SECOND: case TM_WAIT_NB_SECOND_RND: case TM_WAIT_NB_DIZIEME: case TM_WAIT_NB_DIZIEME_RND: offsettrack += 5; break; case TM_PLAY_ACF: { char *ptr, c; char string[256]; int32 n; ptr = string; n = 0; do { c = *ptrtrack++; *ptr++ = c; n++; } while (c != 0); offsettrack += n; break; } case TM_END: return -1; // label not found } } return -1; } void ScriptLifeV2::cleanTrack(ActorStruct *ptrobj) { if (ptrobj->_offsetTrack != -1) { ptrobj->_workFlags.bTRACK_MASTER_ROT = 0; uint8 *ptrtrack = ptrobj->_ptrTrack + ptrobj->_offsetTrack; switch (*ptrtrack) { case TM_FACE_TWINSEN: *(int16 *)(ptrtrack + 1) = -1; break; case TM_WAIT_NB_ANIM: *(uint8 *)(ptrtrack + 2) = 0; break; case TM_WAIT_NB_SECOND: case TM_WAIT_NB_DIZIEME: case TM_WAIT_NB_SECOND_RND: case TM_WAIT_NB_DIZIEME_RND: *(uint32 *)(ptrtrack + 2) = 0; break; case TM_ANGLE: *(int16 *)(ptrtrack + 1) &= 0x7FFF; break; case TM_ANGLE_RND: *(int16 *)(ptrtrack + 3) = -1; break; case TM_LOOP: *(ptrtrack + 2) = *(ptrtrack + 1); break; } } } int32 ScriptLifeV2::lVAR_GAME_TO_TRACK(TwinEEngine *engine, LifeScriptContext &ctx) { cleanTrack(ctx.actor); const uint8 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lVAR_GAME_TO_TRACK(%i)", (int)num); ctx.actor->_offsetTrack = searchOffsetTrack(ctx.actor, engine->_gameState->hasGameFlag(num)); // Shielding against bug of the traveling merchant if (ctx.actor->_offsetTrack < 0) { ctx.actor->_offsetTrack = searchOffsetTrack(ctx.actor, 0); } return 0; } int32 ScriptLifeV2::lANIM_TEXTURE(TwinEEngine *engine, LifeScriptContext &ctx) { engine->_interface->_animateTexture = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lANIM_TEXTURE(%i)", (int)engine->_interface->_animateTexture); return 0; } int32 ScriptLifeV2::lADD_MESSAGE_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { const int32 actorIdx = ctx.stream.readByte(); const TextId textIdx = (TextId)ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lADD_MESSAGE_OBJ(%i, %i)", (int)actorIdx, (int)textIdx); if (engine->_scene->getActor(actorIdx)->_lifePoint > 0) { engine->saveTimer(false); engine->testRestoreModeSVGA(true); if (engine->_text->_showDialogueBubble) { engine->_redraw->drawBubble(actorIdx); } engine->_text->setFontCrossColor(engine->_scene->getActor(actorIdx)->_talkColor); engine->_scene->_talkingActor = (int16)actorIdx; engine->setPalette(engine->_screens->_ptrPal); engine->_text->drawTextProgressive(textIdx); engine->_redraw->drawScene(true); engine->restoreTimer(); } return 0; } int32 ScriptLifeV2::lADD_MESSAGE(TwinEEngine *engine, LifeScriptContext &ctx) { const TextId textIdx = (TextId)ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lADD_MESSAGE(%i)", (int)textIdx); engine->saveTimer(false); engine->testRestoreModeSVGA(true); if (engine->_text->_showDialogueBubble) { engine->_redraw->drawBubble(ctx.actorIdx); } engine->_text->setFontCrossColor(ctx.actor->_talkColor); engine->_scene->_talkingActor = (int16)ctx.actorIdx; engine->setPalette(engine->_screens->_ptrPal); engine->_text->drawTextProgressive(textIdx); engine->_redraw->drawScene(true); engine->restoreTimer(); return 0; } int32 ScriptLifeV2::lCAMERA_CENTER(TwinEEngine *engine, LifeScriptContext &ctx) { const int32 angle = ClampAngle(ToAngle(ctx.stream.readByte() * 1024)); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lCAMERA_CENTER(%i)", (int)angle); engine->_grid->_addBetaCam = angle; engine->_grid->centerOnActor(engine->_scene->getActor(2)); engine->_redraw->_firstTime = true; return 0; } int32 ScriptLifeV2::lBUBBLE(TwinEEngine *engine, LifeScriptContext &ctx) { engine->_text->_showDialogueBubble = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::BUBBLE(%s)", engine->_text->_showDialogueBubble ? "true" : "false"); return 0; } int32 ScriptLifeV2::lNO_CHOC(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 val = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lNO_CHOC(%i)", (int)val); ctx.actor->_flags.bNoElectricShock = val; return 0; } int32 ScriptLifeV2::lCINEMA_MODE(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lCINEMA_MODE(%i)", (int)num); if (num != engine->_scene->_cinemaMode) { engine->_scene->_cinemaMode = num; if (!num) { engine->_redraw->_firstTime = true; // TODO: DureeCycleCinema = BoundRegleTrois( 1, 500, 39, ClipWindowYMin ) ; } else { // TODO: DureeCycleCinema = BoundRegleTrois( 1, 500, 39, 39-ClipWindowYMin ) ; engine->_gameState->setGameFlag(GAMEFLAG_ESC, 0); } // TODO: DebCycleCinema = ClipWindowYMin ; // TODO: LastYCinema = ClipWindowYMin ; // TODO: TimerCinema = TimerRefHR ; } return 0; } int32 ScriptLifeV2::lSAVE_HERO(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::SAVE_HERO()"); engine->_actor->_saveHeroBehaviour = engine->_actor->_heroBehaviour; ActorStruct *actor = engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX); actor->_saveGenBody = actor->_genBody; return 0; } int32 ScriptLifeV2::lRESTORE_HERO(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::RESTORE_HERO()"); engine->_actor->setBehaviour(engine->_actor->_saveHeroBehaviour); ActorStruct *actor = engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX); engine->_actor->initBody(actor->_saveGenBody, OWN_ACTOR_SCENE_INDEX); return 0; } int32 ScriptLifeV2::lRAIN(TwinEEngine *engine, LifeScriptContext &ctx) { const int32 num = (int)ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lRAIN(%i)", (int)num); int32 n = engine->_redraw->addOverlay(OverlayType::koRain, 0, 0, 0, 0, OverlayPosType::koNormal, 1); if (n != -1) { // Rain n/10s engine->_redraw->overlayList[n].timerEnd = engine->timerRef + engine->toSeconds(num / 10); engine->_flagRain = true; engine->_sound->startRainSample(); } return 0; } int32 ScriptLifeV2::lESCALATOR(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint8 info1 = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lESCALATOR(%i, %i)", (int)num, (int)info1); for (int n = 0; n < engine->_scene->_sceneNumZones; n++) { ZoneStruct &zone = engine->_scene->_sceneZones[n]; if (zone.type == ZoneType::kEscalator && zone.num == num) { zone.infoData.generic.info1 = info1; } } return 0; } int32 ScriptLifeV2::lSET_CAMERA(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint8 info7 = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSET_CAMERA(%i, %i)", (int)num, (int)info7); for (int n = 0; n < engine->_scene->_sceneNumZones; n++) { ZoneStruct &zone = engine->_scene->_sceneZones[n]; if (zone.type == ZoneType::kCamera && zone.num == num) { zone.infoData.generic.info7 = info7; if (info7) zone.infoData.generic.info7 |= ZONE_ON; else zone.infoData.generic.info7 &= ~(ZONE_ON); zone.infoData.generic.info7 &= ~(ZONE_ACTIVE); } } return 0; } int32 ScriptLifeV2::lPLAY_ACF(TwinEEngine *engine, LifeScriptContext &ctx) { engine->saveTimer(false); int strIdx = 0; char movie[64]; do { const byte c = ctx.stream.readByte(); movie[strIdx++] = c; if (c == '\0') { break; } if (strIdx >= ARRAYSIZE(movie)) { error("Max string size exceeded for acf name"); } } while (true); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lPLAY_ACF(%s)", movie); if (!engine->_screens->_flagFade) { // TODO: FadeToBlackAndSamples( PtrPal ) ; } engine->_screens->_flagFade = true; engine->_movie->playMovie(movie); // TODO: lba2 is doing more stuff here - reset the cinema mode, init the scene and palette stuff // if (CubeMode==CUBE_INTERIEUR) InitGrille( NumCube ) ; // RazListPartFlow() ; // ChoicePalette() ; engine->setPalette(engine->_screens->_ptrPal); engine->_screens->_flagFade = true; engine->restoreTimer(); engine->_redraw->_firstTime = true; return -1; } int32 ScriptLifeV2::lSHADOW_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { const int actorIdx = ctx.stream.readByte(); const bool castShadow = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::SHADOW_OBJ(%i, %s)", actorIdx, castShadow ? "true" : "false"); ActorStruct *actor = engine->_scene->getActor(actorIdx); if (actor->_lifePoint > 0) { actor->_flags.bNoShadow = !castShadow; } return 0; } int32 ScriptLifeV2::lECLAIR(TwinEEngine *engine, LifeScriptContext &ctx) { const int32 num = (int)ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lECLAIR(%i)", (int)num); int32 n = engine->_redraw->addOverlay(OverlayType::koFlash, 0, 0, 0, 0, OverlayPosType::koNormal, 1); if (n != -1) { // Eclair n/10s engine->_redraw->overlayList[n].timerEnd = engine->timerRef + engine->toSeconds(num / 10); } return 0; } int32 ScriptLifeV2::lINIT_BUGGY(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lINIT_BUGGY(%i)", (int)num); engine->_buggy->initBuggy(ctx.actorIdx, num); return 0; } int32 ScriptLifeV2::lMEMO_ARDOISE(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "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) { const uint8 num = ctx.stream.readByte(); const uint8 info = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "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 TextId textIdx = (TextId)ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lMESSAGE_ZOE(%i)", (int)textIdx); engine->_scene->_talkingActor = OWN_ACTOR_SCENE_INDEX; ActorStruct *hero = engine->_scene->getActor(OWN_ACTOR_SCENE_INDEX); int32 oldColor = hero->_talkColor; hero->_talkColor = 1; // COUL_ZOE engine->saveTimer(false); engine->testRestoreModeSVGA(true); engine->_text->setFontCrossColor(hero->_talkColor); engine->setPalette(engine->_screens->_ptrPal); engine->_text->drawTextProgressive(textIdx); engine->_redraw->drawScene(true); engine->restoreTimer(); hero->_talkColor = oldColor; return 0; } int32 ScriptLifeV2::lACTION(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::ACTION()"); engine->_movements->setActionNormal(true); return 0; } int32 ScriptLifeV2::lSET_FRAME(TwinEEngine *engine, LifeScriptContext &ctx) { const int frame = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSET_FRAME(%i)", (int)frame); if (!ctx.actor->_flags.bSprite3D) { engine->_actor->setFrame(ctx.actorIdx, frame); } return 0; } int32 ScriptLifeV2::lSET_SPRITE(TwinEEngine *engine, LifeScriptContext &ctx) { const int16 num = ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSET_SPRITE(%i)", (int)num); if (ctx.actor->_flags.bSprite3D) { engine->_actor->initSprite(num, ctx.actorIdx); } return 0; } int32 ScriptLifeV2::lSET_FRAME_3DS(TwinEEngine *engine, LifeScriptContext &ctx) { int sprite = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSET_FRAME_3DS(%i)", (int)sprite); if (ctx.actor->_flags.bHasSpriteAnim3D) { 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 0; } int32 ScriptLifeV2::lIMPACT_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint16 n = ctx.stream.readUint16LE(); const int16 y = ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lIMPACT_OBJ(%i, %i, %i)", (int)num, (int)n, (int)y); ActorStruct *otherActor = engine->_scene->getActor(num); if (otherActor->_lifePoint > 0) { engine->_collision->doImpact(n, otherActor->posObj().x, otherActor->posObj().y + y, otherActor->posObj().z, num); } return 0; } int32 ScriptLifeV2::lIMPACT_POINT(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 brickTrackId = ctx.stream.readByte(); const uint16 n = ctx.stream.readUint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lIMPACT_POINT(%i, %i)", (int)brickTrackId, (int)n); const IVec3 &pos = engine->_scene->_sceneTracks[brickTrackId]; engine->_collision->doImpact(n, pos.x, pos.y, pos.z, ctx.actorIdx); return 0; } // ECHELLE int32 ScriptLifeV2::lLADDER(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint8 info = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "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) { const int8 armor = ctx.stream.readSByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "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) { const uint8 num = ctx.stream.readByte(); const int8 armor = ctx.stream.readSByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "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) { const uint8 num = ctx.stream.readByte(); const uint8 life = ctx.stream.readByte(); ActorStruct *actor = engine->_scene->getActor(num); if (actor->_workFlags.bIsDead) { actor->_workFlags.bIsDead = false; engine->_actor->initBody(BodyType::btNormal, num); engine->_animations->initAnim(AnimationTypes::kStanding, AnimType::kAnimationTypeRepeat, AnimationTypes::kStanding, num); } actor->setLife(actor->_lifePoint + life); return 0; } 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::kDebugScriptsLife, "LIFE::lSTATE_INVENTORY(%i, %i)", (int)num, (int)idObj3D); // TODO: TabInv[num].IdObj3D = idObj3D; return -1; } int32 ScriptLifeV2::lAND_IF(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lSWITCH(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lOR_CASE(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lCASE(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lDEFAULT(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lBREAK(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lEND_SWITCH(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lSET_HIT_ZONE(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint8 info1 = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSET_HIT_ZONE(%i, %i)", (int)num, (int)info1); for (int n = 0; n < engine->_scene->_sceneNumZones; n++) { ZoneStruct &zone = engine->_scene->_sceneZones[n]; if (zone.type == ZoneType::kHit && zone.num == num) { zone.infoData.generic.info1 = info1; } } return 0; } int32 ScriptLifeV2::lSAVE_COMPORTEMENT(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSAVE_COMPORTEMENT()"); ctx.actor->_saveOffsetLife = ctx.actor->_offsetLife; return 0; } int32 ScriptLifeV2::lRESTORE_COMPORTEMENT(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lRESTORE_COMPORTEMENT()"); ctx.actor->_offsetLife = ctx.actor->_saveOffsetLife; return 0; } int32 ScriptLifeV2::lSAMPLE(TwinEEngine *engine, LifeScriptContext &ctx) { const uint16 sampleIdx = ctx.stream.readUint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSAMPLE(%i)", (int)sampleIdx); engine->_sound->mixSample3D(sampleIdx, 0x1000, 1, ctx.actor->posObj(), ctx.actorIdx); return 0; } int32 ScriptLifeV2::lSAMPLE_RND(TwinEEngine *engine, LifeScriptContext &ctx) { const uint16 sampleIdx = ctx.stream.readUint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSAMPLE_RND(%i)", (int)sampleIdx); int32 frequency = 0x800 + engine->getRandomNumber(0x800); engine->_sound->mixSample3D(sampleIdx, frequency, 1, ctx.actor->posObj(), ctx.actorIdx); return 0; } int32 ScriptLifeV2::lSAMPLE_ALWAYS(TwinEEngine *engine, LifeScriptContext &ctx) { const uint16 sampleIdx = ctx.stream.readUint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSAMPLE_ALWAYS(%i)", (int)sampleIdx); if (!engine->_sound->isSamplePlaying(sampleIdx)) { engine->_sound->mixSample3D(sampleIdx, 0x1000, 1, ctx.actor->posObj(), ctx.actorIdx); } return 0; } int32 ScriptLifeV2::lSAMPLE_STOP(TwinEEngine *engine, LifeScriptContext &ctx) { const uint16 sampleIdx = ctx.stream.readUint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSAMPLE_STOP(%i)", (int)sampleIdx); engine->_sound->stopSample(sampleIdx); return 0; } int32 ScriptLifeV2::lREPEAT_SAMPLE(TwinEEngine *engine, LifeScriptContext &ctx) { const uint16 sampleIdx = ctx.stream.readUint16LE(); const uint8 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lREPEAT_SAMPLE(%i, %i)", (int)sampleIdx, (int)num); engine->_sound->mixSample3D(sampleIdx, 0x1000, num, ctx.actor->posObj(), ctx.actorIdx); return 0; } int32 ScriptLifeV2::lBACKGROUND(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 val = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lBACKGROUND(%i)", (int)val); if (val != 0) { if (!ctx.actor->_flags.bIsBackgrounded) { ctx.actor->_flags.bIsBackgrounded = 1; if (ctx.actor->_workFlags.bWasDrawn) { engine->_redraw->_firstTime = true; } } } else { if (ctx.actor->_flags.bIsBackgrounded) { ctx.actor->_flags.bIsBackgrounded = 0; if (ctx.actor->_workFlags.bWasDrawn) { engine->_redraw->_firstTime = true; } } } return 0; } int32 ScriptLifeV2::lSET_FLAG_GAME(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const int16 val = ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "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) { const uint8 num = ctx.stream.readByte(); const int16 val = ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lADD_VAR_GAME(%i, %i)", (int)num, (int)val); 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) { const uint8 num = ctx.stream.readByte(); const int16 val = ctx.stream.readSint16LE(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lADD_VAR_GAME(%i, %i)", (int)num, (int)val); 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) { const uint8 num = ctx.stream.readByte(); const uint8 amount = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lADD_VAR_CUBE(%i, %i)", (int)num, (int)amount); uint8 ¤t = engine->_scene->_listFlagCube[num]; if ((int16)current + (int16)amount < 255) { current += amount; } else { current = 255; } return 0; } int32 ScriptLifeV2::lSUB_VAR_CUBE(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint8 amount = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSUB_VAR_CUBE(%i, %i)", (int)num, (int)amount); uint8 ¤t = engine->_scene->_listFlagCube[num]; if ((int16)current - (int16)amount > 0) { current -= amount; } else { current = 0; } return 0; } int32 ScriptLifeV2::lSET_RAIL(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); const uint8 info1 = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lSET_RAIL(%i, %i)", (int)num, (int)info1); for (int n = 0; n < engine->_scene->_sceneNumZones; n++) { ZoneStruct &zone = engine->_scene->_sceneZones[n]; if (zone.type == ZoneType::kRail && zone.num == num) { zone.infoData.generic.info1 = info1; } } return 0; } int32 ScriptLifeV2::lINVERSE_BETA(TwinEEngine *engine, LifeScriptContext &ctx) { ctx.actor->_beta = ClampAngle(ctx.actor->_beta + LBAAngles::ANGLE_180); if (ctx.actor->_move == ControlMode::kWagon) { #if 0 // TODO: ctx.actor->Info1 = 1; // reinit speed wagon // to be clean APtObj = ctx.actor; #endif // 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); } // To tell an object that it is no longer being carried by me engine->_actor->checkCarrier(ctx.actorIdx); return -1; } int32 ScriptLifeV2::lNO_BODY(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lNO_BODY()"); engine->_actor->initBody(BodyType::btNone, ctx.actorIdx); return 0; } int32 ScriptLifeV2::lSTOP_L_TRACK_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lRESTORE_L_TRACK_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lSAVE_COMPORTEMENT_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lRESTORE_COMPORTEMENT_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lSPY(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lDEBUG(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lDEBUG_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lPOPCORN(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lPOPCORN()"); // empty on purpose return 0; } int32 ScriptLifeV2::lFLOW_POINT(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lFLOW_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lSET_ANIM_DIAL(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lPCX(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lEND_MESSAGE(TwinEEngine *engine, LifeScriptContext &ctx) { debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lEND_MESSAGE()"); // empty on purpose return 0; } int32 ScriptLifeV2::lEND_MESSAGE_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { const uint8 num = ctx.stream.readByte(); debugC(3, kDebugLevels::kDebugScriptsLife, "LIFE::lEND_MESSAGE_OBJ(%i)", (int)num); return 0; } int32 ScriptLifeV2::lPARM_SAMPLE(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lNEW_SAMPLE(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lPOS_OBJ_AROUND(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } int32 ScriptLifeV2::lPCX_MESS_OBJ(TwinEEngine *engine, LifeScriptContext &ctx) { return -1; } ScriptLifeV2::ScriptLifeV2(TwinEEngine *engine) : ScriptLife(engine, function_map, ARRAYSIZE(function_map)) { } } // namespace TwinE