moreover getBlack() didn't always work correctly for some reason. If IHNM uses different colors we will switch to variables, but that could be addressed later or at least when someone will start to work on it more time than now. svn-id: r16647
1564 lines
38 KiB
C++
1564 lines
38 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2004-2005 The ScummVM project
|
|
*
|
|
* The ReInherit Engine is (C)2000-2003 by Daniel Balsom.
|
|
*
|
|
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
|
|
// Scripting module script function component
|
|
|
|
#include "saga/saga.h"
|
|
|
|
#include "saga/gfx.h"
|
|
#include "saga/actor.h"
|
|
#include "saga/animation.h"
|
|
#include "saga/console.h"
|
|
#include "saga/events.h"
|
|
#include "saga/font.h"
|
|
#include "saga/interface.h"
|
|
#include "saga/music.h"
|
|
#include "saga/objectdata.h"
|
|
#include "saga/render.h"
|
|
#include "saga/sound.h"
|
|
#include "saga/sndres.h"
|
|
|
|
#include "saga/script.h"
|
|
#include "saga/objectmap.h"
|
|
|
|
#include "saga/scene.h"
|
|
|
|
namespace Saga {
|
|
|
|
#define OPCODE(x) {&Script::x, #x}
|
|
|
|
void Script::setupScriptFuncList(void) {
|
|
static const ScriptFunctionDescription scriptFunctionsList[SCRIPT_FUNCTION_MAX] = {
|
|
OPCODE(sfPutString),
|
|
OPCODE(sfWait),
|
|
OPCODE(sfTakeObject),
|
|
OPCODE(sfIsCarried),
|
|
OPCODE(sfStatusBar),
|
|
OPCODE(sfMainMode),
|
|
OPCODE(sfScriptWalkTo),
|
|
OPCODE(sfScriptDoAction),
|
|
OPCODE(sfSetActorFacing),
|
|
OPCODE(sfStartBgdAnim),
|
|
OPCODE(sfStopBgdAnim),
|
|
OPCODE(sfLockUser),
|
|
OPCODE(sfPreDialog),
|
|
OPCODE(sfKillActorThreads),
|
|
OPCODE(sfFaceTowards),
|
|
OPCODE(sfSetFollower),
|
|
OPCODE(sfScriptGotoScene),
|
|
OPCODE(SF_setObjImage),
|
|
OPCODE(SF_setObjName),
|
|
OPCODE(SF_getObjImage),
|
|
OPCODE(SF_getNumber),
|
|
OPCODE(sfScriptOpenDoor),
|
|
OPCODE(sfScriptCloseDoor),
|
|
OPCODE(sfSetBgdAnimSpeed),
|
|
OPCODE(SF_cycleColors),
|
|
OPCODE(sfDoCenterActor),
|
|
OPCODE(sfStartBgdAnimSpeed),
|
|
OPCODE(sfScriptWalkToAsync),
|
|
OPCODE(SF_enableZone),
|
|
OPCODE(sfSetActorState),
|
|
OPCODE(sfScriptMoveTo),
|
|
OPCODE(SF_sceneEq),
|
|
OPCODE(SF_dropObject),
|
|
OPCODE(sfFinishBgdAnim),
|
|
OPCODE(sfSwapActors),
|
|
OPCODE(sfSimulSpeech),
|
|
OPCODE(sfScriptWalk),
|
|
OPCODE(sfCycleFrames),
|
|
OPCODE(sfSetFrame),
|
|
OPCODE(sfSetPortrait),
|
|
OPCODE(sfSetProtagPortrait),
|
|
OPCODE(sfChainBgdAnim),
|
|
OPCODE(SF_scriptSpecialWalk),
|
|
OPCODE(sfPlaceActor),
|
|
OPCODE(SF_checkUserInterrupt),
|
|
OPCODE(SF_walkRelative),
|
|
OPCODE(SF_moveRelative),
|
|
OPCODE(SF_simulSpeech2),
|
|
OPCODE(sfPlacard),
|
|
OPCODE(sfPlacardOff),
|
|
OPCODE(SF_setProtagState),
|
|
OPCODE(sfResumeBgdAnim),
|
|
OPCODE(SF_throwActor),
|
|
OPCODE(sfWaitWalk),
|
|
OPCODE(SF_sceneID),
|
|
OPCODE(SF_changeActorScene),
|
|
OPCODE(SF_climb),
|
|
OPCODE(sfSetDoorState),
|
|
OPCODE(SF_setActorZ),
|
|
OPCODE(SF_text),
|
|
OPCODE(SF_getActorX),
|
|
OPCODE(SF_getActorY),
|
|
OPCODE(SF_eraseDelta),
|
|
OPCODE(sfPlayMusic),
|
|
OPCODE(SF_pickClimbOutPos),
|
|
OPCODE(SF_tossRif),
|
|
OPCODE(SF_showControls),
|
|
OPCODE(SF_showMap),
|
|
OPCODE(SF_puzzleWon),
|
|
OPCODE(sfEnableEscape),
|
|
OPCODE(sfPlaySound),
|
|
OPCODE(SF_playLoopedSound),
|
|
OPCODE(SF_getDeltaFrame),
|
|
OPCODE(SF_showProtect),
|
|
OPCODE(SF_protectResult),
|
|
OPCODE(sfRand),
|
|
OPCODE(SF_fadeMusic),
|
|
OPCODE(SF_playVoice)
|
|
};
|
|
_scriptFunctionsList = scriptFunctionsList;
|
|
}
|
|
|
|
// Script function #0 (0x00)
|
|
// Print a debugging message
|
|
void Script::sfPutString(SCRIPTFUNC_PARAMS) {
|
|
const char *str;
|
|
str = thread->_strings->getString(thread->pop());
|
|
|
|
_vm->_console->DebugPrintf("sfPutString: %s\n",str);
|
|
debug(0, "sfPutString: %s", str);
|
|
}
|
|
|
|
// Script function #1 (0x01) blocking
|
|
// Param1: time in ticks
|
|
void Script::sfWait(SCRIPTFUNC_PARAMS) {
|
|
int16 time;
|
|
time = thread->pop();
|
|
|
|
if (!_skipSpeeches) {
|
|
thread->waitDelay(ticksToMSec(time)); // put thread to sleep
|
|
}
|
|
}
|
|
|
|
// Script function #2 (0x02)
|
|
void Script::sfTakeObject(SCRIPTFUNC_PARAMS) {
|
|
uint16 objectId = thread->pop();
|
|
ObjectData *obj;
|
|
obj = _vm->_actor->getObj(objectId);
|
|
if (obj->sceneNumber != ITE_SCENE_INV) {
|
|
obj->sceneNumber = ITE_SCENE_INV;
|
|
//_vm->_interface->addToInventory(index); TODO: do it
|
|
}
|
|
}
|
|
|
|
// Script function #3 (0x03)
|
|
// Check if an object is carried.
|
|
void Script::sfIsCarried(SCRIPTFUNC_PARAMS) {
|
|
uint16 objectId = thread->pop();
|
|
ObjectData *obj;
|
|
obj = _vm->_actor->getObj(objectId);
|
|
|
|
thread->_returnValue = (obj->sceneNumber == ITE_SCENE_INV) ? 1 : 0;
|
|
}
|
|
|
|
// Script function #4 (0x04) nonblocking
|
|
// Set the command display to the specified text string
|
|
// Param1: dialogue index of string
|
|
void Script::sfStatusBar(SCRIPTFUNC_PARAMS) {
|
|
int16 stringIndex = thread->pop();
|
|
|
|
_vm->_interface->setStatusText(thread->_strings->getString(stringIndex));
|
|
}
|
|
|
|
// Script function #5 (0x05)
|
|
void Script::sfMainMode(SCRIPTFUNC_PARAMS) {
|
|
_vm->_actor->_centerActor = _vm->_actor->_protagonist;
|
|
showVerb();
|
|
_vm->_interface->activate();
|
|
_vm->_interface->setMode(kPanelInventory);
|
|
setPointerVerb();
|
|
}
|
|
|
|
// Script function #6 (0x06) blocking
|
|
// Param1: actor id
|
|
// Param2: actor x
|
|
// Param3: actor y
|
|
void Script::sfScriptWalkTo(SCRIPTFUNC_PARAMS) {
|
|
uint16 actorId;
|
|
Location actorLocation;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
actorLocation.x = thread->pop();
|
|
actorLocation.y = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actorLocation.z = actor->location.z;
|
|
|
|
actor->flags &= ~kFollower;
|
|
|
|
if (_vm->_actor->actorWalkTo(actorId, actorLocation)) {
|
|
thread->waitWalk(actor);
|
|
}
|
|
}
|
|
|
|
// Script function #7 (0x07)
|
|
// Param1: actor id
|
|
// Param2: action
|
|
// Param3: theObject
|
|
// Param4: withObject
|
|
void Script::sfScriptDoAction(SCRIPTFUNC_PARAMS) {
|
|
uint16 objectId;
|
|
uint16 action;
|
|
uint16 theObject;
|
|
uint16 withObject;
|
|
int16 scriptEntryPointNumber;
|
|
int16 moduleNumber;
|
|
ActorData *actor;
|
|
ObjectData *obj;
|
|
const HitZone *hitZone;
|
|
EVENT event;
|
|
|
|
objectId = thread->pop();
|
|
action = thread->pop();
|
|
theObject = thread->pop();
|
|
withObject = thread->pop();
|
|
|
|
switch (objectTypeId(objectId)) {
|
|
case kGameObjectObject:
|
|
obj = _vm->_actor->getObj(objectId);
|
|
scriptEntryPointNumber = obj->scriptEntrypointNumber;
|
|
if (scriptEntryPointNumber <= 0) {
|
|
return;
|
|
}
|
|
moduleNumber = 0;
|
|
break;
|
|
case kGameObjectActor:
|
|
actor = _vm->_actor->getActor(objectId);
|
|
scriptEntryPointNumber = actor->scriptEntrypointNumber;
|
|
if (scriptEntryPointNumber <= 0) {
|
|
return;
|
|
}
|
|
if (actor->flags & (kProtagonist | kFollower)) {
|
|
moduleNumber = 0;
|
|
} else {
|
|
moduleNumber = _vm->_scene->getScriptModuleNumber();
|
|
}
|
|
break;
|
|
case kGameObjectHitZone:
|
|
case kGameObjectStepZone:
|
|
if (objectTypeId(objectId) == kGameObjectHitZone) {
|
|
hitZone = _vm->_scene->_objectMap->getHitZone(objectIdToIndex(objectId));
|
|
} else {
|
|
hitZone = _vm->_scene->_actionMap->getHitZone(objectIdToIndex(objectId));
|
|
}
|
|
scriptEntryPointNumber = hitZone->getScriptNumber();
|
|
moduleNumber = _vm->_scene->getScriptModuleNumber();
|
|
break;
|
|
default:
|
|
error("Script::sfScriptDoAction wrong object type");
|
|
}
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = SCRIPT_EVENT;
|
|
event.op = EVENT_EXEC_NONBLOCKING;
|
|
event.time = 0;
|
|
event.param = moduleNumber;
|
|
event.param2 = scriptEntryPointNumber;
|
|
event.param3 = action; // Action
|
|
event.param4 = theObject; // Object
|
|
event.param5 = theObject; // With Object
|
|
event.param6 = objectId;
|
|
|
|
_vm->_events->queue(&event);
|
|
}
|
|
|
|
// Script function #8 (0x08) nonblocking
|
|
// Param1: actor id
|
|
// Param2: actor orientation
|
|
void Script::sfSetActorFacing(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
int actorDirection;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
actorDirection = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actor->facingDirection = actor->actionDirection = actorDirection;
|
|
actor->targetObject = ID_NOTHING;
|
|
}
|
|
|
|
// Script function #9 (0x09)
|
|
void Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) {
|
|
int16 animId = thread->pop();
|
|
int16 cycles = thread->pop();
|
|
|
|
_vm->_anim->setCycles(animId, cycles);
|
|
_vm->_anim->play(animId, kRepeatSpeed);
|
|
|
|
debug(1, "sfStartBgdAnim(%d, %d)", animId, cycles);
|
|
}
|
|
|
|
// Script function #10 (0x0A)
|
|
void Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) {
|
|
int16 animId = thread->pop();
|
|
|
|
_vm->_anim->stop(animId);
|
|
|
|
debug(1, "sfStopBgdAnim(%d)", animId);
|
|
}
|
|
|
|
// Script function #11 (0x0B) nonblocking
|
|
// If the parameter is true, the user interface is disabled while script
|
|
// continues to run. If the parameter is false, the user interface is
|
|
// reenabled.
|
|
// Param1: boolean
|
|
void Script::sfLockUser(SCRIPTFUNC_PARAMS) {
|
|
int16 lock;
|
|
|
|
lock = thread->pop();
|
|
|
|
if (lock) {
|
|
_vm->_interface->deactivate();
|
|
} else {
|
|
_vm->_interface->activate();
|
|
}
|
|
|
|
}
|
|
|
|
// Script function #12 (0x0C)
|
|
// Disables mouse input, etc.
|
|
void Script::sfPreDialog(SCRIPTFUNC_PARAMS) {
|
|
_vm->_interface->deactivate();
|
|
; // clear converse text
|
|
if (_vm->_interface->isInMainMode())
|
|
_vm->_interface->setMode(kPanelConverse);
|
|
else
|
|
; // display zero text
|
|
_vm->_interface->setMode(kPanelNull);
|
|
|
|
debug(1, "stub: SF_preDialog()");
|
|
}
|
|
|
|
// Script function #13 (0x0D)
|
|
void Script::sfKillActorThreads(SCRIPTFUNC_PARAMS) {
|
|
ScriptThread *anotherThread;
|
|
ScriptThreadList::iterator threadIterator;
|
|
int16 actorId;
|
|
|
|
actorId = thread->pop();
|
|
|
|
|
|
for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
|
|
anotherThread = threadIterator.operator->();
|
|
if ((anotherThread != thread) && (anotherThread->_threadVars[kThreadVarActor] == actorId)) {
|
|
thread->_flags &= ~kTFlagWaiting;
|
|
thread->_flags |= kTFlagAborted;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Script function #14 (0x0E)
|
|
// Param1: actor id
|
|
// Param2: object id
|
|
void Script::sfFaceTowards(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
int16 targetObject;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
targetObject = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actor->targetObject = targetObject;
|
|
}
|
|
|
|
// Script function #15 (0x0F)
|
|
// Param1: actor id
|
|
// Param2: target object
|
|
void Script::sfSetFollower(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
int16 targetObject;
|
|
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
targetObject = thread->pop();
|
|
|
|
debug(1, "sfSetFollower(%d, %d) [%d]", actorId, targetObject, _vm->_actor->actorIdToIndex(actorId));
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actor->targetObject = targetObject;
|
|
if (targetObject != ID_NOTHING) {
|
|
actor->flags |= kFollower;
|
|
actor->actorFlags &= ~kActorNoFollow;
|
|
} else {
|
|
actor->flags &= ~kFollower;
|
|
}
|
|
}
|
|
|
|
static struct SceneSubstitutes {
|
|
int sceneId;
|
|
const char *message;
|
|
const char *name;
|
|
const char *image;
|
|
} sceneSubstitutes[] = {
|
|
{
|
|
7,
|
|
"Tycho says he knows much about the northern lands. Can Rif convince "
|
|
"the Dog to share this knowledge?",
|
|
"The Home of Tycho Northpaw",
|
|
"tycho.bbm"
|
|
},
|
|
|
|
{
|
|
27,
|
|
"The scene of the crime may hold many clues, but will the servants of "
|
|
"the Sanctuary trust Rif?",
|
|
"The Sanctuary of the Orb",
|
|
"sanctuar.bbm"
|
|
},
|
|
|
|
{
|
|
5,
|
|
"The Rats hold many secrets that could guide Rif on his quest -- assuming "
|
|
"he can get past the doorkeeper.",
|
|
"The Rat Complex",
|
|
"ratdoor.bbm"
|
|
},
|
|
|
|
{
|
|
2,
|
|
"The Ferrets enjoy making things and have the materials to do so. How can "
|
|
"that help Rif?",
|
|
"The Ferret Village",
|
|
"ferrets.bbm"
|
|
},
|
|
|
|
{
|
|
67,
|
|
"What aid can the noble King of the Elks provide to Rif and his companions?",
|
|
"The Realm of the Forest King",
|
|
"elkenter.bbm"
|
|
},
|
|
|
|
{
|
|
3,
|
|
"The King holds Rif's sweetheart hostage. Will the Boar provide any "
|
|
"assistance to Rif?",
|
|
"The Great Hall of the Boar King",
|
|
"boarhall.bbm"
|
|
}
|
|
};
|
|
|
|
// Script function #16 (0x10)
|
|
void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) {
|
|
int16 sceneNumber;
|
|
int16 entrance;
|
|
|
|
sceneNumber = thread->pop();
|
|
entrance = thread->pop();
|
|
if (sceneNumber < 0) {
|
|
//TODO: quit from game at all
|
|
}
|
|
|
|
// This is used for latter demos where all places on world map except
|
|
// Tent Faire are substituted with LBM picture and short description
|
|
// TODO: implement
|
|
for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++)
|
|
if (sceneSubstitutes[i].sceneId == sceneNumber)
|
|
debug(0, "Scene %d substitute exists", sceneNumber);
|
|
|
|
// _vm->_scene->loadScene(sceneNumber, BY_SCENE, _vm->_scene->SC_defaultScene, NULL, (sceneNumber = RID_ITE_ENDCREDIT_SCENE_1) ? SCENE_FADE : SCENE_NOFADE, entrance);
|
|
|
|
//TODO: placard stuff
|
|
_pendingVerb = kVerbNone;
|
|
_currentObject[0] = _currentObject[1] = ID_NOTHING;
|
|
showVerb();
|
|
}
|
|
|
|
// Script function #17 (0x11)
|
|
void Script::SF_setObjImage(SCRIPTFUNC_PARAMS) {
|
|
error("Not implemented");
|
|
/* int16 obj_param = getSWord(thread->pop());
|
|
int16 sprite_param = getSWord(thread->pop());
|
|
|
|
|
|
int index = obj_param & 0x1FFF;
|
|
|
|
if (index >= ARRAYSIZE(ObjectTable)) {
|
|
return FAILURE;
|
|
}
|
|
|
|
ObjectTable[index].spritelistRn = sprite_param + 9;
|
|
_vm->_interface->draw();
|
|
*/
|
|
}
|
|
|
|
// Script function #18 (0x12)
|
|
void Script::SF_setObjName(SCRIPTFUNC_PARAMS) {
|
|
error("Not implemented");
|
|
|
|
/* int obj_param = getSWord(thread->pop());
|
|
int name_param = getSWord(thread->pop());
|
|
|
|
int index = obj_param & 0x1FFF;
|
|
|
|
if (index >= ARRAYSIZE(ObjectTable)) {
|
|
return FAILURE;
|
|
}
|
|
|
|
ObjectTable[index].nameIndex = name_param;*/
|
|
}
|
|
|
|
// Script function #19 (0x13)
|
|
void Script::SF_getObjImage(SCRIPTFUNC_PARAMS) {
|
|
error("Not implemented");
|
|
|
|
/* int param = getSWord(thread->pop());
|
|
int index = param & 0x1FFF;
|
|
|
|
if (index >= ARRAYSIZE(ObjectTable)) {
|
|
thread->retVal = 0;
|
|
return FAILURE;
|
|
}
|
|
|
|
thread->retVal = ObjectTable[index].spritelistRn;*/
|
|
}
|
|
|
|
// Script function #20 (0x14)
|
|
void Script::SF_getNumber(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_getNumber(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #21 (0x15)
|
|
// Param1: door #
|
|
void Script::sfScriptOpenDoor(SCRIPTFUNC_PARAMS) {
|
|
int16 doorNumber;
|
|
doorNumber = thread->pop();
|
|
|
|
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
|
//todo: it
|
|
} else {
|
|
_vm->_scene->setDoorState(doorNumber, 0);
|
|
}
|
|
}
|
|
|
|
// Script function #22 (0x16)
|
|
// Param1: door #
|
|
void Script::sfScriptCloseDoor(SCRIPTFUNC_PARAMS) {
|
|
int16 doorNumber;
|
|
doorNumber = thread->pop();
|
|
|
|
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
|
//todo: it
|
|
} else {
|
|
_vm->_scene->setDoorState(doorNumber, 0xff);
|
|
}
|
|
}
|
|
|
|
// Script function #23 (0x17)
|
|
void Script::sfSetBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
|
|
int16 animId = thread->pop();
|
|
int16 speed = thread->pop();
|
|
|
|
_vm->_anim->setFrameTime(animId, ticksToMSec(speed));
|
|
debug(1, "sfSetBgdAnimSpeed(%d, %d)", animId, speed);
|
|
|
|
}
|
|
|
|
// Script function #24 (0x18)
|
|
void Script::SF_cycleColors(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_cycleColors(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #25 (0x19)
|
|
// Param1: actor id
|
|
void Script::sfDoCenterActor(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
actorId = thread->pop();
|
|
|
|
_vm->_actor->_centerActor = _vm->_actor->getActor(actorId);
|
|
}
|
|
|
|
// Script function #26 (0x1A) nonblocking
|
|
// Starts the specified animation
|
|
void Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) {
|
|
int16 animId = thread->pop();
|
|
int16 cycles = thread->pop();
|
|
int16 speed = thread->pop();
|
|
|
|
_vm->_anim->setCycles(animId, cycles);
|
|
_vm->_anim->play(animId, ticksToMSec(speed));
|
|
|
|
debug(1, "sfStartBgdAnimSpeed(%d, %d, %d)", animId, cycles, speed);
|
|
}
|
|
|
|
// Script function #27 (0x1B) nonblocking
|
|
// Param1: actor id
|
|
// Param2: actor x
|
|
// Param3: actor y
|
|
void Script::sfScriptWalkToAsync(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
Location actorLocation;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
actorLocation.x = thread->pop();
|
|
actorLocation.y = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actorLocation.z = actor->location.z;
|
|
|
|
actor->flags &= ~kFollower;
|
|
|
|
_vm->_actor->actorWalkTo(actorId, actorLocation);
|
|
}
|
|
|
|
// Script function #28 (0x1C)
|
|
void Script::SF_enableZone(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_enableZone(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #29 (0x1D)
|
|
// Param1: actor id
|
|
// Param2: current action
|
|
void Script::sfSetActorState(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
int currentAction;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
currentAction = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
|
|
if ((currentAction >= kActionWalkToPoint) && (currentAction <= kActionWalkToPoint)) {
|
|
wakeUpActorThread(kWaitTypeWalk, actor);
|
|
}
|
|
actor->currentAction = currentAction;
|
|
actor->actorFlags &= ~kActorBackwards;
|
|
|
|
}
|
|
|
|
// Script function #30 (0x1E) nonblocking
|
|
// Param1: actor id
|
|
// Param2: actor pos x
|
|
// Param3: actor pos y
|
|
void Script::sfScriptMoveTo(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
Location actorLocation;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
actorLocation.x = thread->pop();
|
|
actorLocation.y = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
|
|
actor->location.x = actorLocation.x;
|
|
actor->location.y = actorLocation.y;
|
|
}
|
|
|
|
// Script function #31 (0x21)
|
|
void Script::SF_sceneEq(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
|
|
if (_vm->_scene->getSceneLUT(param) == _vm->_scene->currentSceneNumber())
|
|
thread->_returnValue = 1;
|
|
else
|
|
thread->_returnValue = 0;
|
|
}
|
|
|
|
// Script function #32 (0x20)
|
|
void Script::SF_dropObject(SCRIPTFUNC_PARAMS) {
|
|
error("Not implemented");
|
|
|
|
/* ScriptDataWord obj_param = thread->pop();
|
|
ScriptDataWord sprite_param = thread->pop();
|
|
ScriptDataWord x_param = thread->pop();
|
|
ScriptDataWord y_param = thread->pop();
|
|
|
|
int index = obj_param & 0x1FFF;
|
|
|
|
if (index >= ARRAYSIZE(ObjectTable)) {
|
|
return FAILURE;
|
|
}
|
|
|
|
if (ObjectTable[index].sceneIndex == -1) {
|
|
_vm->_interface->removeFromInventory(index);
|
|
}
|
|
|
|
ObjectTable[index].sceneIndex = _vm->_scene->currentSceneNumber();
|
|
ObjectTable[index].spritelistRn = 9 + sprite_param;
|
|
ObjectTable[index].x = x_param;
|
|
ObjectTable[index].y = y_param;
|
|
*/
|
|
}
|
|
|
|
// Script function #33 (0x21)
|
|
void Script::sfFinishBgdAnim(SCRIPTFUNC_PARAMS) {
|
|
int16 animId = thread->pop();
|
|
|
|
_vm->_anim->finish(animId);
|
|
|
|
debug(1, "sfFinishBgdAnim(%d)", animId);
|
|
}
|
|
|
|
// Script function #34 (0x22)
|
|
// Param1: actor id 1
|
|
// Param2: actor id 2
|
|
void Script::sfSwapActors(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId1;
|
|
int16 actorId2;
|
|
ActorData *actor1;
|
|
ActorData *actor2;
|
|
Location location;
|
|
|
|
actorId1 = thread->pop();
|
|
actorId2 = thread->pop();
|
|
|
|
actor1 = _vm->_actor->getActor(actorId1);
|
|
actor2 = _vm->_actor->getActor(actorId2);
|
|
location = actor1->location;
|
|
actor1->location = actor2->location;
|
|
actor2->location = location;
|
|
|
|
|
|
if (actor1->flags & kProtagonist) {
|
|
actor1->flags &= ~kProtagonist;
|
|
actor2->flags |= kProtagonist;
|
|
_vm->_actor->_protagonist = _vm->_actor->_centerActor = actor2;
|
|
} else {
|
|
if (actor2->flags & kProtagonist) {
|
|
actor2->flags &= ~kProtagonist;
|
|
actor1->flags |= kProtagonist;
|
|
_vm->_actor->_protagonist = _vm->_actor->_centerActor = actor1;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Script function #35 (0x23)
|
|
// Param1: string rid
|
|
// Param2: actorscount
|
|
// Param3: actor id1
|
|
///....
|
|
// Param3: actor idN
|
|
void Script::sfSimulSpeech(SCRIPTFUNC_PARAMS) {
|
|
int16 stringId;
|
|
int16 actorsCount;
|
|
int i;
|
|
uint16 actorsIds[ACTOR_SPEECH_ACTORS_MAX];
|
|
const char *string;
|
|
|
|
stringId = thread->pop();
|
|
actorsCount = thread->pop();
|
|
|
|
if (actorsCount > ACTOR_SPEECH_ACTORS_MAX)
|
|
error("sfSimulSpeech actorsCount=0x%X exceed ACTOR_SPEECH_ACTORS_MAX", actorsCount);
|
|
|
|
for (i = 0; i < actorsCount; i++)
|
|
actorsIds[i] = thread->pop();
|
|
|
|
string = thread->_strings->getString(stringId);
|
|
|
|
_vm->_actor->simulSpeech(string, actorsIds, actorsCount, 0);
|
|
}
|
|
|
|
// Script function #36 (0x24) ?
|
|
// Param1: actor id
|
|
// Param2: actor x
|
|
// Param3: actor y
|
|
// Param4: actor walk flag
|
|
void Script::sfScriptWalk(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
Location actorLocation;
|
|
ActorData *actor;
|
|
uint16 walkFlags;
|
|
|
|
actorId = thread->pop();
|
|
actorLocation.x = thread->pop();
|
|
actorLocation.y = thread->pop();
|
|
walkFlags = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actorLocation.z = actor->location.z;
|
|
|
|
_vm->_actor->realLocation(actorLocation, ID_NOTHING, walkFlags);
|
|
|
|
actor->flags &= ~kFollower;
|
|
|
|
if (_vm->_actor->actorWalkTo(actorId, actorLocation) && !(walkFlags & kWalkAsync)) {
|
|
thread->waitWalk(actor);
|
|
}
|
|
|
|
if (walkFlags & kWalkBackPedal) {
|
|
actor->actorFlags |= kActorBackwards;
|
|
}
|
|
|
|
actor->actorFlags = (actor->actorFlags & ~kActorFacingMask) | (walkFlags & kActorFacingMask);
|
|
}
|
|
|
|
// Script function #37 (0x25) nonblocking
|
|
// Param1: actor id
|
|
// Param2: flags telling how to cycle the frames
|
|
// Param3: cycle frame number
|
|
// Param4: cycle delay
|
|
void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
int flags;
|
|
int cycleFrameSequence;
|
|
int cycleDelay;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
flags = thread->pop();
|
|
cycleFrameSequence = thread->pop();
|
|
cycleDelay = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
|
|
if (flags & kCyclePong) {
|
|
actor->currentAction = kActionPongFrames;
|
|
} else {
|
|
actor->currentAction = kActionCycleFrames;
|
|
}
|
|
|
|
actor->actorFlags &= ~(kActorContinuous | kActorRandom | kActorBackwards);
|
|
|
|
if (!(flags & kCycleOnce)) {
|
|
actor->actorFlags |= kActorContinuous;
|
|
}
|
|
if (flags & kCycleRandom) {
|
|
actor->actorFlags |= kActorRandom;
|
|
}
|
|
if (flags & kCycleReverse) {
|
|
actor->actorFlags |= kActorBackwards;
|
|
}
|
|
|
|
actor->cycleFrameSequence = cycleFrameSequence;
|
|
actor->cycleTimeCount = 0;
|
|
actor->cycleDelay = cycleDelay;
|
|
actor->actionCycle = 0;
|
|
|
|
}
|
|
|
|
// Script function #38 (0x26) nonblocking
|
|
// Param1: actor id
|
|
// Param2: frame type
|
|
// Param3: frame offset
|
|
void Script::sfSetFrame(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
int frameType;
|
|
int frameOffset;
|
|
ActorData *actor;
|
|
ActorFrameRange *frameRange;
|
|
|
|
actorId = thread->pop();
|
|
frameType = thread->pop();
|
|
frameOffset = thread->pop();
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
|
|
frameRange = _vm->_actor->getActorFrameRange(actorId, frameType);
|
|
|
|
if (frameRange->frameCount <= frameOffset) {
|
|
// frameRange = _vm->_actor->getActorFrameRange(actorId, frameType);
|
|
|
|
error("Wrong frameOffset 0x%X", frameOffset);
|
|
}
|
|
actor->frameNumber = frameRange->frameIndex + frameOffset;
|
|
|
|
if (actor->currentAction != kActionFall) {
|
|
actor->currentAction = kActionFreeze;
|
|
}
|
|
}
|
|
|
|
// Script function #39 (0x27)
|
|
// Sets the right-hand portrait
|
|
void Script::sfSetPortrait(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
|
|
_vm->_interface->setRightPortrait(param);
|
|
}
|
|
|
|
// Script function #40 (0x28)
|
|
// Sets the left-hand portrait
|
|
void Script::sfSetProtagPortrait(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
|
|
_vm->_interface->setLeftPortrait(param);
|
|
}
|
|
|
|
// Script function #41 (0x29) nonblocking
|
|
// Links the specified animations for playback
|
|
|
|
// Param1: ?
|
|
// Param2: total linked frame count
|
|
// Param3: animation id link target
|
|
// Param4: animation id link source
|
|
void Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) {
|
|
int16 animId1 = thread->pop();
|
|
int16 animId = thread->pop();
|
|
int16 cycles = thread->pop();
|
|
int16 speed = thread->pop();
|
|
|
|
if (speed >= 0) {
|
|
_vm->_anim->setCycles(animId, cycles);
|
|
_vm->_anim->stop(animId);
|
|
_vm->_anim->setFrameTime(animId, ticksToMSec(speed));
|
|
}
|
|
|
|
_vm->_anim->link(animId1, animId);
|
|
debug(1, "sfChainBgdAnim(%d, %d, %d, %d)", animId1, animId, cycles, speed);
|
|
}
|
|
|
|
// Script function #42 (0x2A)
|
|
void Script::SF_scriptSpecialWalk(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_scriptSpecialWalk(%d, %d, %d, %d)", param1, param2, param3, param4);
|
|
}
|
|
|
|
// Script function #43 (0x2B) nonblocking
|
|
// Param1: actor id
|
|
// Param2: actor x
|
|
// Param3: actor y
|
|
// Param4: actor direction
|
|
// Param5: actor action
|
|
// Param6: actor frame number
|
|
void Script::sfPlaceActor(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
Location actorLocation;
|
|
int actorDirection;
|
|
int frameType;
|
|
int frameOffset;
|
|
ActorData *actor;
|
|
ActorFrameRange *frameRange;
|
|
|
|
actorId = thread->pop();
|
|
actorLocation.x = thread->pop();
|
|
actorLocation.y = thread->pop();
|
|
actorDirection = thread->pop();
|
|
frameType = thread->pop();
|
|
frameOffset = thread->pop();
|
|
|
|
debug(1, "sfPlaceActor(%d, %d, %d, %d, %d, %d)", actorId, actorLocation.x,
|
|
actorLocation.y, actorDirection, frameType, frameOffset);
|
|
|
|
if (_vm->getGameType() == GType_IHNM) {
|
|
warning("Actors aren't implemented for IHNM yet");
|
|
return;
|
|
}
|
|
|
|
actor = _vm->_actor->getActor(actorId);
|
|
actor->location.x = actorLocation.x;
|
|
actor->location.y = actorLocation.y;
|
|
actor->facingDirection = actor->actionDirection = actorDirection;
|
|
|
|
if (frameType >= 0) {
|
|
frameRange = _vm->_actor->getActorFrameRange(actorId, frameType);
|
|
|
|
if (frameRange->frameCount <= frameOffset)
|
|
error("Wrong frameOffset 0x%X", frameOffset);
|
|
|
|
actor->frameNumber = frameRange->frameIndex + frameOffset;
|
|
actor->currentAction = kActionFreeze;
|
|
} else {
|
|
actor->currentAction = kActionWait;
|
|
}
|
|
|
|
actor->targetObject = ID_NOTHING;
|
|
|
|
}
|
|
|
|
// Script function #44 (0x2C) nonblocking
|
|
// Checks to see if the user has interrupted a currently playing
|
|
// game cinematic. Pushes a zero or positive value if the game
|
|
// has not been interrupted.
|
|
void Script::SF_checkUserInterrupt(SCRIPTFUNC_PARAMS) {
|
|
thread->_returnValue = (_skipSpeeches == true);
|
|
|
|
}
|
|
|
|
// Script function #45 (0x2D)
|
|
void Script::SF_walkRelative(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_walkRelative(%d, %d, %d, %d, %d)", param1, param2, param3, param4, param5);
|
|
}
|
|
|
|
// Script function #46 (0x2E)
|
|
void Script::SF_moveRelative(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_moveRelative(%d, %d, %d, %d, %d)", param1, param2, param3, param4, param5);
|
|
}
|
|
|
|
// Script function #47 (0x2F)
|
|
void Script::SF_simulSpeech2(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_simulSpeech2(), %d args", nArgs);
|
|
}
|
|
|
|
static TEXTLIST_ENTRY *placardTextEntry;
|
|
|
|
// Script function #48 (0x30)
|
|
// Param1: string rid
|
|
void Script::sfPlacard(SCRIPTFUNC_PARAMS) {
|
|
int stringId;
|
|
SURFACE *back_buf = _vm->_gfx->getBackBuffer();
|
|
static PALENTRY cur_pal[PAL_ENTRIES];
|
|
PALENTRY *pal;
|
|
EVENT event;
|
|
EVENT *q_event;
|
|
|
|
thread->wait(kWaitTypePlacard);
|
|
|
|
_vm->_interface->rememberMode();
|
|
_vm->_interface->setMode(kPanelPlacard);
|
|
|
|
stringId = thread->pop();
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = CURSOR_EVENT;
|
|
event.op = EVENT_HIDE;
|
|
|
|
q_event = _vm->_events->queue(&event);
|
|
|
|
_vm->_gfx->getCurrentPal(cur_pal);
|
|
|
|
event.type = IMMEDIATE_EVENT;
|
|
event.code = PAL_EVENT;
|
|
event.op = EVENT_PALTOBLACK;
|
|
event.time = 0;
|
|
event.duration = kNormalFadeDuration;
|
|
event.data = cur_pal;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = INTERFACE_EVENT;
|
|
event.op = EVENT_CLEAR_STATUS;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = GRAPHICS_EVENT;
|
|
event.op = EVENT_SETFLAG;
|
|
event.param = RF_PLACARD;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = GRAPHICS_EVENT;
|
|
event.op = EVENT_FILL_RECT;
|
|
event.data = back_buf;
|
|
event.param = 138;
|
|
event.param2 = 0;
|
|
event.param3 = _vm->getSceneHeight();
|
|
event.param4 = 0;
|
|
event.param5 = _vm->getDisplayWidth();
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
// Put the text in the center of the viewport, assuming it will fit on
|
|
// one line. If we cannot make that assumption we'll need to extend
|
|
// the text drawing function so that it can center text around a point.
|
|
// It doesn't end up in exactly the same spot as the original did it,
|
|
// but it's close enough for now at least.
|
|
|
|
TEXTLIST_ENTRY text_entry;
|
|
SCENE_INFO scene_info;
|
|
|
|
_vm->_scene->getInfo(&scene_info);
|
|
|
|
text_entry.color = kITEColorBrightWhite;
|
|
text_entry.effect_color = kITEColorBlack;
|
|
text_entry.text_x = _vm->getDisplayWidth() / 2;
|
|
text_entry.text_y = (_vm->getSceneHeight() - _vm->_font->getHeight(MEDIUM_FONT_ID)) / 2;
|
|
text_entry.font_id = MEDIUM_FONT_ID;
|
|
text_entry.flags = FONT_OUTLINE | FONT_CENTERED;
|
|
text_entry.string = thread->_strings->getString(stringId);
|
|
|
|
placardTextEntry = _vm->textAddEntry(scene_info.text_list, &text_entry);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = TEXT_EVENT;
|
|
event.op = EVENT_DISPLAY;
|
|
event.data = placardTextEntry;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
_vm->_scene->getBGPal(&pal);
|
|
|
|
event.type = IMMEDIATE_EVENT;
|
|
event.code = PAL_EVENT;
|
|
event.op = EVENT_BLACKTOPAL;
|
|
event.time = 0;
|
|
event.duration = kNormalFadeDuration;
|
|
event.data = pal;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = SCRIPT_EVENT;
|
|
event.op = EVENT_THREAD_WAKE;
|
|
event.param = kWaitTypePlacard;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
}
|
|
|
|
// Script function #49 (0x31)
|
|
void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) {
|
|
static PALENTRY cur_pal[PAL_ENTRIES];
|
|
PALENTRY *pal;
|
|
EVENT event;
|
|
EVENT *q_event;
|
|
|
|
thread->wait(kWaitTypePlacard);
|
|
|
|
_vm->_interface->restoreMode();
|
|
|
|
_vm->_gfx->getCurrentPal(cur_pal);
|
|
|
|
event.type = IMMEDIATE_EVENT;
|
|
event.code = PAL_EVENT;
|
|
event.op = EVENT_PALTOBLACK;
|
|
event.time = 0;
|
|
event.duration = kNormalFadeDuration;
|
|
event.data = cur_pal;
|
|
|
|
q_event = _vm->_events->queue(&event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = GRAPHICS_EVENT;
|
|
event.op = EVENT_CLEARFLAG;
|
|
event.param = RF_PLACARD;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = TEXT_EVENT;
|
|
event.op = EVENT_REMOVE;
|
|
event.data = placardTextEntry;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
_vm->_scene->getBGPal(&pal);
|
|
|
|
event.type = IMMEDIATE_EVENT;
|
|
event.code = PAL_EVENT;
|
|
event.op = EVENT_BLACKTOPAL;
|
|
event.time = 0;
|
|
event.duration = kNormalFadeDuration;
|
|
event.data = pal;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = CURSOR_EVENT;
|
|
event.op = EVENT_SHOW;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
event.type = ONESHOT_EVENT;
|
|
event.code = SCRIPT_EVENT;
|
|
event.op = EVENT_THREAD_WAKE;
|
|
event.param = kWaitTypePlacard;
|
|
|
|
q_event = _vm->_events->chain(q_event, &event);
|
|
|
|
}
|
|
|
|
// Script function #50 (0x32)
|
|
void Script::SF_setProtagState(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_setProtagState(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #51 (0x33)
|
|
void Script::sfResumeBgdAnim(SCRIPTFUNC_PARAMS) {
|
|
int16 animId = thread->pop();
|
|
int16 cycles = thread->pop();
|
|
|
|
_vm->_anim->resume(animId, cycles);
|
|
debug(1, "sfResumeBgdAnimSpeed(%d, %d)", animId, cycles);
|
|
|
|
}
|
|
|
|
// Script function #52 (0x34)
|
|
void Script::SF_throwActor(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_throwActor(%d, %d, %d, %d, %d, %d)", param1, param2, param3, param4, param5, param6);
|
|
}
|
|
|
|
// Script function #53 (0x35)
|
|
// Param1: actor id
|
|
// Param2: target object
|
|
void Script::sfWaitWalk(SCRIPTFUNC_PARAMS) {
|
|
int16 actorId;
|
|
ActorData *actor;
|
|
|
|
actorId = thread->pop();
|
|
actor = _vm->_actor->getActor(actorId);
|
|
|
|
if ((actor->currentAction == kActionWalkToPoint) ||
|
|
(actor->currentAction == kActionWalkToLink) ||
|
|
(actor->currentAction == kActionFall)) {
|
|
thread->waitWalk(actor);
|
|
}
|
|
}
|
|
|
|
// Script function #54 (0x36)
|
|
void Script::SF_sceneID(SCRIPTFUNC_PARAMS) {
|
|
thread->_returnValue = _vm->_scene->currentSceneNumber();
|
|
}
|
|
|
|
// Script function #55 (0x37)
|
|
void Script::SF_changeActorScene(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_changeActorScene(%d, %d)", param1, param2);
|
|
}
|
|
|
|
// Script function #56 (0x38)
|
|
void Script::SF_climb(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_climb(%d, %d, %d, %d)", param1, param2, param3, param4);
|
|
}
|
|
|
|
// Script function #57 (0x39)
|
|
// Param1: door #
|
|
// Param2: door state
|
|
void Script::sfSetDoorState(SCRIPTFUNC_PARAMS) {
|
|
int16 doorNumber;
|
|
int16 doorState;
|
|
doorNumber = thread->pop();
|
|
doorState = thread->pop();
|
|
|
|
if (_vm->_scene->getFlags() & kSceneFlagISO) {
|
|
//todo: it
|
|
} else {
|
|
_vm->_scene->setDoorState(doorNumber, doorState);
|
|
}
|
|
}
|
|
|
|
// Script function #58 (0x3A)
|
|
void Script::SF_setActorZ(SCRIPTFUNC_PARAMS) {
|
|
thread->pop();
|
|
thread->pop();
|
|
|
|
//debug(1, "stub: SF_setActorZ(%d, %d)", param1, param2);
|
|
}
|
|
|
|
// Script function #59 (0x3B)
|
|
void Script::SF_text(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_text(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #60 (0x3C)
|
|
void Script::SF_getActorX(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
|
|
debug(1, "stub: SF_getActorX(%d)", param);
|
|
}
|
|
|
|
// Script function #61 (0x3D)
|
|
void Script::SF_getActorY(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
|
|
debug(1, "stub: SF_getActorY(%d)", param);
|
|
}
|
|
|
|
// Script function #62 (0x3E)
|
|
void Script::SF_eraseDelta(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_eraseDelta(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #63 (0x3F)
|
|
void Script::sfPlayMusic(SCRIPTFUNC_PARAMS) {
|
|
if (_vm->getGameType() == GType_ITE) {
|
|
int16 param = thread->pop() + 9;
|
|
|
|
if (param >= 9 && param <= 34)
|
|
_vm->_music->play(param);
|
|
else
|
|
_vm->_music->stop();
|
|
} else {
|
|
int16 param1 = thread->pop();
|
|
int16 param2 = thread->pop();
|
|
|
|
debug(1, "Stub: sfPlayMusic(%d, %d)", param1, param2);
|
|
}
|
|
|
|
}
|
|
|
|
// Script function #64 (0x40)
|
|
void Script::SF_pickClimbOutPos(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_pickClimbOutPos(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #65 (0x41)
|
|
void Script::SF_tossRif(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_tossRif(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #66 (0x42)
|
|
void Script::SF_showControls(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_showControls(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #67 (0x43)
|
|
void Script::SF_showMap(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_showMap(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #68 (0x44)
|
|
void Script::SF_puzzleWon(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_puzzleWon(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #69 (0x45)
|
|
void Script::sfEnableEscape(SCRIPTFUNC_PARAMS) {
|
|
if (thread->pop())
|
|
_abortEnabled = true;
|
|
else {
|
|
_skipSpeeches = false;
|
|
_abortEnabled = false;
|
|
}
|
|
}
|
|
|
|
static struct {
|
|
int res;
|
|
int vol;
|
|
} sfxTable[] = {
|
|
{ FX_DOOR_OPEN, 127 },
|
|
{ FX_DOOR_CLOSE, 127 },
|
|
{ FX_RUSH_WATER, 63 }, // Floppy volume: 127
|
|
{ FX_RUSH_WATER, 26 }, // Floppy volume: 40
|
|
{ FX_CRICKET, 64 },
|
|
{ FX_PORTICULLIS, 84 }, // Floppy volume: 127
|
|
{ FX_CLOCK_1, 64 },
|
|
{ FX_CLOCK_2, 64 },
|
|
{ FX_DAM_MACHINE, 64 },
|
|
{ FX_DAM_MACHINE, 40 },
|
|
{ FX_HUM1, 64 },
|
|
{ FX_HUM2, 64 },
|
|
{ FX_HUM3, 64 },
|
|
{ FX_HUM4, 64 },
|
|
{ FX_WATER_LOOP_S, 32 }, // Floppy volume: 64
|
|
{ FX_SURF, 42 }, // Floppy volume: 127
|
|
{ FX_SURF, 32 }, // Floppy volume: 64
|
|
{ FX_FIRELOOP, 64 }, // Floppy volume: 96
|
|
{ FX_SCRAPING, 84 }, // Floppy volume: 127
|
|
{ FX_BEE_SWARM, 64 }, // Floppy volume: 96
|
|
{ FX_BEE_SWARM, 26 }, // Floppy volume: 40
|
|
{ FX_SQUEAKBOARD, 64 },
|
|
{ FX_KNOCK, 127 },
|
|
{ FX_COINS, 32 }, // Floppy volume: 48
|
|
{ FX_STORM, 84 }, // Floppy volume: 127
|
|
{ FX_DOOR_CLOSE_2, 84 }, // Floppy volume: 127
|
|
{ FX_ARCWELD, 84 }, // Floppy volume: 127
|
|
{ FX_RETRACT_ORB, 127 },
|
|
{ FX_DRAGON, 127 },
|
|
{ FX_SNORES, 127 },
|
|
{ FX_SPLASH, 127 },
|
|
{ FX_LOBBY_DOOR, 127 },
|
|
{ FX_CHIRP_LOOP, 26 }, // Floppy volume: 40
|
|
{ FX_DOOR_CREAK, 96 },
|
|
{ FX_SPOON_DIG, 64 },
|
|
{ FX_CROW, 96 },
|
|
{ FX_COLDWIND, 42 }, // Floppy volume: 64
|
|
{ FX_TOOL_SND_1, 96 },
|
|
{ FX_TOOL_SND_2, 127 },
|
|
{ FX_TOOL_SND_3, 64 },
|
|
{ FX_DOOR_METAL, 96 },
|
|
{ FX_WATER_LOOP_S, 32 },
|
|
{ FX_WATER_LOOP_L, 32 }, // Floppy volume: 64
|
|
{ FX_DOOR_OPEN_2, 127 },
|
|
{ FX_JAIL_DOOR, 64 },
|
|
{ FX_KILN_FIRE, 53 }, // Floppy volume: 80
|
|
|
|
// Only in the CD version
|
|
{ FX_CROWD_01, 64 },
|
|
{ FX_CROWD_02, 64 },
|
|
{ FX_CROWD_03, 64 },
|
|
{ FX_CROWD_04, 64 },
|
|
{ FX_CROWD_05, 64 },
|
|
{ FX_CROWD_06, 64 },
|
|
{ FX_CROWD_07, 64 },
|
|
{ FX_CROWD_08, 64 },
|
|
{ FX_CROWD_09, 64 },
|
|
{ FX_CROWD_10, 64 },
|
|
{ FX_CROWD_11, 64 },
|
|
{ FX_CROWD_12, 64 },
|
|
{ FX_CROWD_13, 64 },
|
|
{ FX_CROWD_14, 64 },
|
|
{ FX_CROWD_15, 64 },
|
|
{ FX_CROWD_16, 64 },
|
|
{ FX_CROWD_17, 64 }
|
|
};
|
|
|
|
// Script function #70 (0x46)
|
|
void Script::sfPlaySound(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
int res;
|
|
|
|
if (param < ARRAYSIZE(sfxTable)) {
|
|
res = sfxTable[param].res;
|
|
if (_vm->getFeatures() & GF_CD_FX)
|
|
res -= 14;
|
|
|
|
_vm->_sndRes->playSound(res, sfxTable[param].vol, false);
|
|
} else {
|
|
_vm->_sound->stopSound();
|
|
}
|
|
|
|
}
|
|
|
|
// Script function #71 (0x47)
|
|
void Script::SF_playLoopedSound(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_playLoopedSound(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #72 (0x48)
|
|
void Script::SF_getDeltaFrame(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_getDeltaFrame(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #73 (0x49)
|
|
void Script::SF_showProtect(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_showProtect(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #74 (0x4A)
|
|
void Script::SF_protectResult(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_protectResult(), %d args", nArgs);
|
|
}
|
|
|
|
// Script function #75 (0x4d)
|
|
void Script::sfRand(SCRIPTFUNC_PARAMS) {
|
|
int16 param = thread->pop();
|
|
|
|
thread->_returnValue = _vm->_rnd.getRandomNumber(param - 1);
|
|
}
|
|
|
|
// Script function #76 (0x4c)
|
|
void Script::SF_fadeMusic(SCRIPTFUNC_PARAMS) {
|
|
debug(1, "stub: SF_fadeMusic()");
|
|
}
|
|
|
|
// Script function #77 (0x4d)
|
|
void Script::SF_playVoice(SCRIPTFUNC_PARAMS) {
|
|
for (int i = 0; i < nArgs; i++)
|
|
thread->pop();
|
|
|
|
debug(1, "stub: SF_playVoice(), %d args", nArgs);
|
|
}
|
|
|
|
void Script::finishDialog(int replyID, int flags, int bitOffset) {
|
|
byte *addr;
|
|
|
|
if (_conversingThread) {
|
|
_vm->_interface->setMode(kPanelNull);
|
|
|
|
_conversingThread->_flags &= ~kTFlagWaiting;
|
|
|
|
_conversingThread->push(replyID);
|
|
|
|
if (flags & kReplyOnce) {
|
|
addr = _conversingThread->_staticBase + (bitOffset >> 3);
|
|
*addr |= (1 << (bitOffset & 7));
|
|
}
|
|
}
|
|
|
|
_conversingThread = NULL;
|
|
wakeUpThreads(kWaitTypeDialogBegin);
|
|
}
|
|
|
|
} // End of namespace Saga
|