mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-07 10:21:31 +00:00
3968 lines
107 KiB
C++
3968 lines
107 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 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
|
|
* aint32 with this program; if not, write to the Free Software
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#include "common/debug.h"
|
|
|
|
#include "saga2/saga2.h"
|
|
#include "saga2/fta.h"
|
|
#include "saga2/script.h"
|
|
#include "saga2/actor.h"
|
|
#include "saga2/speech.h"
|
|
#include "saga2/assign.h"
|
|
#include "saga2/intrface.h"
|
|
#include "saga2/document.h"
|
|
#include "saga2/motion.h"
|
|
#include "saga2/sensor.h"
|
|
#include "saga2/magic.h"
|
|
#include "saga2/uidialog.h"
|
|
#include "saga2/mission.h"
|
|
#include "saga2/band.h"
|
|
#include "saga2/tromode.h"
|
|
#include "saga2/automap.h"
|
|
#include "saga2/videobox.h"
|
|
#include "saga2/display.h"
|
|
#include "saga2/transit.h"
|
|
#include "saga2/contain.h"
|
|
#include "saga2/tile.h"
|
|
#include "saga2/tilemode.h"
|
|
|
|
void drawMainDisplay();
|
|
|
|
#define MONOLOG(s) {debugC(2, kDebugScripts, "cfunc: " #s );}
|
|
#define OBJLOG(s) {debugC(2, kDebugScripts, "cfunc: [%s]." #s , (((ObjectData *)thisThread->_thisObject)->obj)->objName() );}
|
|
|
|
namespace Saga2 {
|
|
|
|
extern WorldMapData *mapList; // master map data array
|
|
|
|
/* ============================================================================ *
|
|
CFunc helper functions
|
|
* ============================================================================ */
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Convert string ID to string text
|
|
|
|
inline char *STRING(int strNum) {
|
|
return (char *)thisThread->strAddress(strNum);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// SPrintf-like formatting of strings, except that it works on
|
|
// SAGA arglists.
|
|
|
|
int stringf(char *buffer, long maxlen, int formatStr, int16 *args) {
|
|
char *fmt = STRING(formatStr);
|
|
char *bufEnd = buffer + maxlen - 1;
|
|
char dbuf[16], // temp buffer for digits
|
|
*dptr;
|
|
|
|
// While there is room in the buffer
|
|
while (buffer < bufEnd && *fmt != '\0') {
|
|
// Format string character
|
|
if (*fmt == '%') {
|
|
if (fmt[1] == 'd') { // If it's %d
|
|
// Convert numeric argument to string
|
|
snprintf(dbuf, 15, "%d", *args++);
|
|
|
|
// Copy string to buffer (if it fits)
|
|
for (dptr = dbuf; *dptr && buffer < bufEnd;) {
|
|
*buffer++ = *dptr++;
|
|
}
|
|
} else if (fmt[1] == 'x') { // If it's %x
|
|
// Convert numeric argument to string
|
|
snprintf(dbuf, 15, "%x", *args++);
|
|
|
|
// Copy string to buffer (if it fits)
|
|
for (dptr = dbuf; *dptr && buffer < bufEnd;) {
|
|
*buffer++ = *dptr++;
|
|
}
|
|
} else if (fmt[1] == 's') { // If it's %s
|
|
// Obtain SAGA string, copy to buffer (if it fits)
|
|
for (dptr = STRING(*args++); *dptr && buffer < bufEnd;) {
|
|
*buffer++ = *dptr++;
|
|
}
|
|
} else if (fmt[1] == 'n') { // If it's %n (object name)
|
|
GameObject *obj = GameObject::objectAddress(*args++);
|
|
|
|
// Obtain SAGA string, copy to buffer (if it fits)
|
|
for (const char *dptr1 = obj->objName(); *dptr1 && buffer < bufEnd;) {
|
|
*buffer++ = *dptr1++;
|
|
}
|
|
} else {
|
|
// Write the character after the '%' to the buffer
|
|
*buffer++ = fmt[1];
|
|
}
|
|
fmt += 2;
|
|
} else *buffer++ = *fmt++;
|
|
}
|
|
|
|
*buffer++ = '\0';
|
|
|
|
// Return the number of characters written to the buffer
|
|
return buffer - (bufEnd - (maxlen - 1));
|
|
}
|
|
|
|
/* ============================================================================ *
|
|
Script C-Function call tables
|
|
* ============================================================================ */
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns the id of this object
|
|
// GameObject id "c" thisID( void );
|
|
|
|
int16 scriptGameObjectThisID(int16 *args) {
|
|
OBJLOG(ThisID);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->thisID();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Recharges this object
|
|
// void "c" recharge( void );
|
|
|
|
int16 scriptGameObjectRecharge(int16 *args) {
|
|
OBJLOG(Recharge);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->recharge();
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// this returns the type of charge this item should have
|
|
// none, red, violet, etc...
|
|
// int "c" getChargeType( void );
|
|
|
|
int16 scriptGameObjectGetChargeType(int16 *args) {
|
|
OBJLOG(GetChargeType);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->getChargeType();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Move an object to a new location. (optional 4th parameter
|
|
// is for actor facing, only used by actors)
|
|
// void "c" move( int u, int v, int z, ... );
|
|
|
|
int16 scriptActorMove(int16 *args) {
|
|
OBJLOG(Move);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
// Move the object to a new location
|
|
obj->move(TilePoint(args[0], args[1], args[2]));
|
|
|
|
// If optional 4th parameter is present, then set actor facing
|
|
if (thisThread->_argCount > 3 && isActor(obj)) {
|
|
Actor *a = (Actor *)obj;
|
|
|
|
a->_currentFacing = args[3];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Move object relative to another object (optional 4th
|
|
// parameter is for actor facing, only used by actors)
|
|
// void "c" moveRel( GameObject id baseObj, int angle, int distance, ... );
|
|
|
|
extern const StaticTilePoint dirTable[8];
|
|
|
|
int16 scriptActorMoveRel(int16 *args) {
|
|
OBJLOG(MoveRel);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj,
|
|
*baseObj = GameObject::objectAddress(args[0]);
|
|
Location l;
|
|
TilePoint tp;
|
|
|
|
l._context = baseObj->IDParent();
|
|
tp = baseObj->getLocation();
|
|
|
|
// Add offset for angle and distance
|
|
tp += (dirTable[args[1] & 7] * args[2]) / 3;
|
|
|
|
// Move the object to a new location
|
|
*(TilePoint *)&l = tp;
|
|
obj->move(l);
|
|
|
|
// If optional 4th parameter is present, then set actor facing
|
|
if (thisThread->_argCount > 3 && isActor(obj)) {
|
|
Actor *a = (Actor *)obj;
|
|
|
|
a->_currentFacing = args[3];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Transfer object to a new context. (optional 4th parameter
|
|
// is for actor facing, only used by actors)
|
|
// void "c" transfer( GameObject id context, int u, int v, int z, ... );
|
|
|
|
int16 scriptActorTransfer(int16 *args) {
|
|
OBJLOG(Transfer);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
// Move the object to a new location
|
|
if ((isObject(args[0])
|
|
&& (GameObject::protoAddress(args[0])->containmentSet()
|
|
& ProtoObj::isContainer))
|
|
|| isActor(args[0])) {
|
|
ObjectID targetID = args[0];
|
|
GameObject *target = GameObject::objectAddress(targetID);
|
|
TilePoint targetSlot;
|
|
|
|
// If it's an actor we're moving to, then "place" the object rather than
|
|
// using the explicit coordinates specified
|
|
if (target->getAvailableSlot(obj, &targetSlot)) {
|
|
uint16 cSet = target->proto()->containmentSet();
|
|
|
|
obj->move(Location(targetSlot, targetID));
|
|
if ((cSet & (ProtoObj::isIntangible | ProtoObj::isContainer))
|
|
== (ProtoObj::isIntangible | ProtoObj::isContainer))
|
|
g_vm->_cnm->setUpdate(targetID);
|
|
}
|
|
} else {
|
|
obj->move(Location(args[1], args[2], args[3], args[0]));
|
|
}
|
|
|
|
// If optional 5th parameter is present, then set actor facing
|
|
if (thisThread->_argCount > 4 && isActor(obj)) {
|
|
Actor *a = (Actor *)obj;
|
|
|
|
a->_currentFacing = args[4];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Pick a random location for an object within an area
|
|
// void "c" moveRandom( int u, int v, int z, int distance );
|
|
|
|
int16 scriptMoveRandom(int16 *args) {
|
|
OBJLOG(MoveRandom);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
TilePoint tpMin, tpMax;
|
|
int16 distance = args[3];
|
|
|
|
tpMin.u = args[0] - distance;
|
|
tpMin.v = args[1] - distance;
|
|
tpMin.z = 0;
|
|
|
|
tpMax.u = args[0] + distance;
|
|
tpMax.v = args[1] + distance;
|
|
tpMax.z = 100;
|
|
|
|
obj->moveRandom(tpMin, tpMax);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return Name ID of actor
|
|
// int "c" name( void );
|
|
|
|
int16 scriptActorGetName(int16 *) {
|
|
OBJLOG(GetName);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 oldName = obj->getNameIndex();
|
|
|
|
return oldName;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set Name ID of actor
|
|
// int "c" setName( int nameID );
|
|
|
|
int16 scriptActorSetName(int16 *args) {
|
|
OBJLOG(SetName);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 oldName = obj->getNameIndex();
|
|
|
|
obj->setNameIndex(args[0]);
|
|
|
|
return oldName;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// return current object prototype
|
|
// int "c" proto( void );
|
|
|
|
int16 scriptActorGetProto(int16 *) {
|
|
OBJLOG(GetProto);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
return obj->getProtoNum();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set object prototype and return old proto
|
|
// int "c" setProto( int protoID );
|
|
|
|
int16 scriptActorSetProto(int16 *args) {
|
|
OBJLOG(SetProto);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 oldProto = obj->getProtoNum();
|
|
|
|
if (isActor(obj) && (((Actor *)obj)->_flags & Actor::kAFTemporary)) {
|
|
decTempActorCount(oldProto);
|
|
incTempActorCount(args[0]);
|
|
}
|
|
|
|
obj->setProtoNum(args[0]);
|
|
|
|
return oldProto;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// return current object prototype class
|
|
// int "c" protoClass( void );
|
|
|
|
int16 scriptActorGetProtoClass(int16 *) {
|
|
OBJLOG(GetProtoClass);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
ProtoObj *objProto = obj->proto();
|
|
|
|
return objProto->classType;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// return current object prototype
|
|
// int "c" getScript( void );
|
|
|
|
int16 scriptActorGetScript(int16 *) {
|
|
OBJLOG(GetScript);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
return obj->getScript();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set object script index and return old script
|
|
// int "c" setScript( int protoID );
|
|
|
|
int16 scriptActorSetScript(int16 *args) {
|
|
OBJLOG(SetScript);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 oldScript = obj->getScript();
|
|
|
|
obj->setScript(args[0]);
|
|
|
|
return oldScript;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Use this object
|
|
// int "c" use( GameObject id enactor );
|
|
|
|
int16 scriptGameObjectUse(int16 *args) {
|
|
OBJLOG(Use);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->use(args[0]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Use this object on another object
|
|
// int "c" useOn( GameObject id enactor, GameObject id target );
|
|
|
|
int16 scriptGameObjectUseOn(int16 *args) {
|
|
OBJLOG(UseOn);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->useOn(args[0], args[1]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Use this object on a TAI
|
|
// int "c" useOnTAI( GameObject id enactor, TileActivityInstance id target );
|
|
|
|
int16 scriptGameObjectUseOnTAI(int16 *args) {
|
|
OBJLOG(UseOnTAI);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->useOn(args[0], ActiveItem::activeItemAddress(args[1]));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Drop this object
|
|
// int "c" drop(
|
|
// GameObject id enactor,
|
|
// GameObject id context,
|
|
// int u,
|
|
// int v,
|
|
// int z );
|
|
|
|
int16 scriptGameObjectDrop(int16 *args) {
|
|
OBJLOG(Drop);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->drop(
|
|
args[0],
|
|
Location(args[2], args[3], args[4], args[1 ]));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Drop this object on another object
|
|
// int "c" dropOn( GameObject id enactor, GameObject id target );
|
|
|
|
int16 scriptGameObjectDropOn(int16 *args) {
|
|
OBJLOG(DropOn);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->dropOn(args[0], args[1]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Drop this object on another object. For mergeable objects only
|
|
// int "c" dropMergeableOn(
|
|
// GameObject id enactor,
|
|
// GameObject id target,
|
|
// int count );
|
|
|
|
int16 scriptGameObjectDropMergeableOn(int16 *args) {
|
|
OBJLOG(DropMergeableOn);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->dropOn(args[0], args[1], args[2]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Drop this object on a TAI
|
|
// int "c" dropOnTAI(
|
|
// GameObject id enactor,
|
|
// TileActivityInstance id target,
|
|
// GameObject id context,
|
|
// int u,
|
|
// int v,
|
|
// int z );
|
|
|
|
int16 scriptGameObjectDropOnTAI(int16 *args) {
|
|
OBJLOG(DropOnTAI);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->dropOn(
|
|
args[0],
|
|
ActiveItem::activeItemAddress(args[1]),
|
|
Location(args[3], args[4], args[5], args[2 ]));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Causes actor (or object) to speak...
|
|
// void "c" say( int flags, int sampleID, string, ... );
|
|
|
|
int16 scriptActorSay(int16 *args) {
|
|
OBJLOG(Say);
|
|
// Actor speech enums -- move these to include file
|
|
// MOVED TO SPEECH.H - EO
|
|
// enum {
|
|
// speakContinued = (1<<0), // Append next speech
|
|
// speakNoAnimate = (1<<1), // Don't animate speaking
|
|
// speakWait = (1<<2), // wait until speech finished
|
|
// speakLock = (1<<3), // LockUI while speaking
|
|
// };
|
|
|
|
// 'obj' is the actor doing the speaking.
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
uint16 flags = args[0];
|
|
Speech *sp;
|
|
|
|
if (isActor(obj)) {
|
|
Actor *a = (Actor *)obj;
|
|
|
|
if (a->isDead()) return 0;
|
|
}
|
|
|
|
// Determine if a speech record is being built for this actor.
|
|
// If so, then retrieve it. If not, then build a new one and
|
|
// retrieve it.
|
|
sp = speechList.findSpeech(obj->thisID());
|
|
if (sp == nullptr) {
|
|
uint16 spFlags = 0;
|
|
|
|
if (flags & speakNoAnimate) spFlags |= Speech::spNoAnimate;
|
|
if (flags & speakLock) spFlags |= Speech::spLock;
|
|
|
|
sp = speechList.newTask(obj->thisID(), spFlags);
|
|
|
|
if (sp == nullptr) return 0;
|
|
}
|
|
|
|
// Loop through each of the arguments.
|
|
// REM: Might want to do some range checking on the arguments.
|
|
for (int i = 1; i < thisThread->_argCount; i += 2) {
|
|
uint16 sampleNum = args[i];
|
|
char *speechText = STRING(args[i + 1]);
|
|
|
|
debugC(2, kDebugScripts, "Speech Text: - %s", speechText);
|
|
sp->append(speechText, sampleNum);
|
|
}
|
|
|
|
// If we're ready to activate the speech
|
|
if (!(flags & speakContinued)) {
|
|
// If we're going to wait for it synchronously
|
|
if (flags & speakWait) {
|
|
thisThread->waitForEvent(Thread::waitOther, nullptr);
|
|
sp->setWakeUp(getThreadID(thisThread));
|
|
}
|
|
|
|
// Move speech to active queue
|
|
sp->activate();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Appends a string of text (no samples) to speech buffer, but does not
|
|
// begin the speech
|
|
// void "c" sayText( string txt, ... );
|
|
|
|
int16 scriptActorSayText(int16 *args) {
|
|
OBJLOG(SayText);
|
|
// 'obj' is the actor doing the speaking.
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
Speech *sp;
|
|
char buffer[256];
|
|
|
|
// Determine if a speech record is being built for this actor.
|
|
// If so, then retrieve it. If not, then fail.
|
|
sp = speechList.findSpeech(obj->thisID());
|
|
if (sp == nullptr) return 0;
|
|
|
|
stringf(buffer, sizeof buffer, args[0], &args[1]);
|
|
sp->append(buffer, 0);
|
|
return 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns overall type of object
|
|
// int "c" objectType( void );
|
|
|
|
int16 scriptActorObjectType(int16 *) {
|
|
OBJLOG(ObjectType);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return (int16)(obj->containmentSet());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns overall type of object
|
|
// GameObject id "c" copyObject( void );
|
|
|
|
int16 scriptActorCopyObject(int16 *) {
|
|
OBJLOG(CopyObject);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
Location l(0, 0, 0, Nothing);
|
|
|
|
return (int16)(obj->copy(l));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if this object is activated
|
|
// int "c" isActivated( void );
|
|
|
|
int16 scriptGameObjectIsActivated(int16 *args) {
|
|
OBJLOG(IsActivated);
|
|
return (((ObjectData *)thisThread->_thisObject)->obj)->isActivated();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Object flags access functions
|
|
|
|
int16 scriptActorGetOpen(int16 *) {
|
|
OBJLOG(GetOpen);
|
|
return (((ObjectData *)thisThread->_thisObject)->obj)->isOpen();
|
|
}
|
|
|
|
int16 scriptActorGetLocked(int16 *) {
|
|
OBJLOG(GetLocked);
|
|
return (((ObjectData *)thisThread->_thisObject)->obj)->isLocked();
|
|
}
|
|
|
|
int16 scriptActorGetImportant(int16 *) {
|
|
OBJLOG(GetImportant);
|
|
return (((ObjectData *)thisThread->_thisObject)->obj)->isImportant();
|
|
}
|
|
|
|
int16 scriptActorGetScavengable(int16 *) {
|
|
OBJLOG(GetScavengable);
|
|
return (((ObjectData *)thisThread->_thisObject)->obj)->isScavengable();
|
|
}
|
|
|
|
/*
|
|
int16 scriptActorSetOpen( int16 *args )
|
|
{
|
|
(((ObjectData *)thisThread->_thisObject)->obj)->setFlags(
|
|
args[0] ? 0xffff : 0,
|
|
kObjectOpen );
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptActorSetLocked( int16 *args )
|
|
{
|
|
(((ObjectData *)thisThread->_thisObject)->obj)->setFlags(
|
|
args[0] ? 0xffff : 0,
|
|
kObjectLocked );
|
|
return 0;
|
|
}
|
|
*/
|
|
|
|
int16 scriptActorSetImportant(int16 *args) {
|
|
OBJLOG(SetImportant);
|
|
(((ObjectData *)thisThread->_thisObject)->obj)->setFlags(
|
|
args[0] ? (int16) 0xffff : (int16) 0,
|
|
kObjectImportant);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptActorSetScavengable(int16 *args) {
|
|
OBJLOG(SetScavengable);
|
|
(((ObjectData *)thisThread->_thisObject)->obj)->setFlags(
|
|
args[0] ? (int16) 0xffff : (int16) 0,
|
|
kObjectScavengable);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new timer for this object
|
|
// int "c" addTimer( int timerID, int frameInterval );
|
|
|
|
int16 scriptGameObjectAddTimer(int16 *args) {
|
|
OBJLOG(AddTimer);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addTimer(args[0], args[1]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new timer for this object using the standard frame
|
|
// interval (5 frames)
|
|
// int "c" addStdTimer( int timerID, int frameInterval );
|
|
|
|
int16 scriptGameObjectAddStdTimer(int16 *args) {
|
|
OBJLOG(AddStdTimer);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addTimer(args[0]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Delete a specific timer
|
|
// void "c" removeTimer( int timerID );
|
|
|
|
int16 scriptGameObjectRemoveTimer(int16 *args) {
|
|
OBJLOG(RemoveTimer);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->removeTimer(args[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Delete all timers for this object
|
|
// void "c" removeAllTimers( void );
|
|
|
|
int16 scriptGameObjectRemoveAllTimers(int16 *args) {
|
|
OBJLOG(RemoveAllTimers);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->removeAllTimers();
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a sensor for this object to detect the proximity of a
|
|
// protaganist
|
|
// int "c" addProtaganistSensor( int sensorID, int range );
|
|
|
|
int16 scriptGameObjectAddProtaganistSensor(int16 *args) {
|
|
OBJLOG(AddProtaganistSensor);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addProtaganistSensor(args[0], args[1]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a sensor for this object to detect the proximity of a
|
|
// specified actor
|
|
// int "c" addSpecificActorSensor(
|
|
// int sensorID,
|
|
// int range,
|
|
// Actor id actor );
|
|
|
|
int16 scriptGameObjectAddSpecificActorSensor(int16 *args) {
|
|
OBJLOG(AddSpecificActorSensor);
|
|
assert(isActor(args[2]));
|
|
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addSpecificActorSensor(
|
|
args[0],
|
|
args[1],
|
|
(Actor *)GameObject::objectAddress(args[2]));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a sensor for this object to detect the proximity of a
|
|
// specified object
|
|
// int "c" addSpecificObjectSensor(
|
|
// int sensorID,
|
|
// int range,
|
|
// GameObject id obj );
|
|
|
|
int16 scriptGameObjectAddSpecificObjectSensor(int16 *args) {
|
|
OBJLOG(AddSpecificObjectSensor);
|
|
assert(isObject(args[2]) || isActor(args[2]));
|
|
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addSpecificObjectSensor(args[0], args[1], args[2]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a sensor for this object to detect the proximity of an
|
|
// actor with a specified property
|
|
// int "c" addActorPropertySensor(
|
|
// int sensorID,
|
|
// int range,
|
|
// int actorProperty );
|
|
|
|
int16 scriptGameObjectAddActorPropertySensor(int16 *args) {
|
|
OBJLOG(AddActorPropertySensor);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addActorPropertySensor(args[0], args[1], args[2]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a sensor for this object to detect the proximity of an
|
|
// object with a specified property
|
|
// int "c" addObjectPropertySensor(
|
|
// int sensorID,
|
|
// int range,
|
|
// int objectProperty );
|
|
|
|
int16 scriptGameObjectAddObjectPropertySensor(int16 *args) {
|
|
OBJLOG(AddObjectPropertySensor);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addObjectPropertySensor(args[0], args[1], args[2]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a sensor for this object to detect a specified event
|
|
// within this actor's proximity
|
|
// int "c" addEventSensor( int sensorID, int range, int eventType );
|
|
|
|
int16 scriptGameObjectAddEventSensor(int16 *args) {
|
|
OBJLOG(AddEventSensor);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->addEventSensor(
|
|
args[0],
|
|
args[1],
|
|
args[2]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Delete a specified sensor
|
|
// void "c" removeSensor( int sensorID );
|
|
|
|
int16 scriptGameObjectRemoveSensor(int16 *args) {
|
|
OBJLOG(RemoveSensor);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->removeSensor(args[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Delete every sensor for this object
|
|
// void "c" removeAllSensors( void );
|
|
|
|
int16 scriptGameObjectRemoveAllSensors(int16 *args) {
|
|
OBJLOG(RemoveAllSensors);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->removeAllSensors();
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if this object can sense the proximity of a protaganist
|
|
// int "c" canSenseProtaganist( int range );
|
|
|
|
int16 scriptGameObjectCanSenseProtaganist(int16 *args) {
|
|
OBJLOG(CanSenseProtaganist);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
SenseInfo info;
|
|
|
|
if (obj->canSenseProtaganist(info, args[0])) {
|
|
scriptCallFrame &scf = thisThread->_threadArgs;
|
|
|
|
scf.enactor = obj->thisID();
|
|
scf.directObject = info.sensedObject->thisID();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if this object can sense the proximity of a specific
|
|
// actor
|
|
// int "c" canSenseSpecificActor( int range, Actor id actor );
|
|
|
|
int16 scriptGameObjectCanSenseSpecificActor(int16 *args) {
|
|
OBJLOG(CanSenseSpecificActor);
|
|
assert(isActor(args[1]));
|
|
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
SenseInfo info;
|
|
|
|
if (obj->canSenseSpecificActor(
|
|
info,
|
|
args[0],
|
|
(Actor *)GameObject::objectAddress(args[1]))) {
|
|
scriptCallFrame &scf = thisThread->_threadArgs;
|
|
|
|
scf.enactor = obj->thisID();
|
|
scf.directObject = info.sensedObject->thisID();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if this object can sense the proximity of a specific
|
|
// object
|
|
// int "c" canSenseSpecificObject( int range, GameObject id obj );
|
|
|
|
int16 scriptGameObjectCanSenseSpecificObject(int16 *args) {
|
|
OBJLOG(CanSenseSpecificObject);
|
|
assert(isObject(args[1]) || isActor(args[1]));
|
|
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
SenseInfo info;
|
|
|
|
if (obj->canSenseSpecificObject(info, args[0], args[1])) {
|
|
scriptCallFrame &scf = thisThread->_threadArgs;
|
|
|
|
scf.enactor = obj->thisID();
|
|
scf.directObject = info.sensedObject->thisID();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if this object can sense the proximity of an actor
|
|
// with a specified property
|
|
// int "c" canSenseActorProperty( int range, int actorProperty );
|
|
|
|
int16 scriptGameObjectCanSenseActorProperty(int16 *args) {
|
|
OBJLOG(CanSenseActorProperty);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
SenseInfo info;
|
|
|
|
if (obj->canSenseActorProperty(info, args[0], args[1])) {
|
|
scriptCallFrame &scf = thisThread->_threadArgs;
|
|
|
|
scf.enactor = obj->thisID();
|
|
scf.directObject = info.sensedObject->thisID();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if this object can sense the proximity of an object
|
|
// with a specified property
|
|
// int "c" canSenseObjectProperty( int range, int objectProperty );
|
|
|
|
int16 scriptGameObjectCanSenseObjectProperty(int16 *args) {
|
|
OBJLOG(CanSenseObjectProperty);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
SenseInfo info;
|
|
|
|
if (obj->canSenseObjectProperty(info, args[0], args[1])) {
|
|
scriptCallFrame &scf = thisThread->_threadArgs;
|
|
|
|
scf.enactor = obj->thisID();
|
|
scf.directObject = info.sensedObject->thisID();
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// returns object script, or proto's script if has none
|
|
// int "c" getActualScript( void );
|
|
|
|
int16 scriptGameObjectGetActualScript(int16 *) {
|
|
OBJLOG(GetActualScript);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 script;
|
|
|
|
script = obj->getScript();
|
|
if (script == 0)
|
|
script = obj->proto()->script;
|
|
return script;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// returns the script of the prototype
|
|
// int "c" getProtoScript( void );
|
|
|
|
int16 scriptGameObjectGetProtoScript(int16 *) {
|
|
OBJLOG(GetProtoScript);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->proto()->script;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get and set mass count -- mergeable objects only
|
|
// int "c" getMass( void );
|
|
|
|
int16 scriptGameObjectGetMass(int16 *) {
|
|
OBJLOG(GetMass);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return (obj->proto()->flags & ResourceObjectPrototype::objPropMergeable)
|
|
? obj->getExtra() : 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get and set mass count -- mergeable objects only
|
|
// int "c" setMass( int newMass );
|
|
|
|
int16 scriptGameObjectSetMass(int16 *args) {
|
|
OBJLOG(SetMass);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (obj->proto()->flags & ResourceObjectPrototype::objPropMergeable) {
|
|
obj->setExtra(args[0]);
|
|
if (obj->proto()->flags & ResourceObjectPrototype::objPropMergeable) {
|
|
g_vm->_cnm->setUpdate(obj->IDParent());
|
|
}
|
|
return true;
|
|
} else return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the extra scratch var
|
|
// int "c" getExtra( void );
|
|
|
|
int16 scriptGameObjectGetExtra(int16 *) {
|
|
OBJLOG(GetExtra);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->getExtra();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the extra scratch var
|
|
// void "c" setExtra( int newVal );
|
|
|
|
int16 scriptGameObjectSetExtra(int16 *args) {
|
|
OBJLOG(SetExtra);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->setExtra(args[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Make a copy of this object and all sub-objects
|
|
// GameObject id "c" deepCopy( void );
|
|
|
|
int16 deepCopy(GameObject *src, ObjectID parentID, TilePoint tp) {
|
|
OBJLOG(DeepCopy);
|
|
Location l;
|
|
int16 newID, childID;
|
|
GameObject *childObj = nullptr;
|
|
|
|
l.u = tp.u;
|
|
l.v = tp.v;
|
|
l.z = tp.z;
|
|
l._context = parentID;
|
|
|
|
// Make a copy of this object, and place it in the parent container we spec'd
|
|
newID = src->copy(l);
|
|
if (newID == Nothing) return 0; // REM: How to send error message to script?
|
|
|
|
// Now, recursively copy all the children of this object.
|
|
ContainerIterator iter(src);
|
|
while ((childID = iter.next(&childObj)))
|
|
deepCopy(childObj, newID, childObj->getLocation());
|
|
|
|
// Return the ID of the object just copied.
|
|
return newID;
|
|
}
|
|
|
|
int16 scriptGameObjectDeepCopy(int16 *args) {
|
|
OBJLOG(DeepCopy);
|
|
ObjectID newParentID = args[0];
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj,
|
|
*newParent = GameObject::objectAddress(newParentID),
|
|
*newObj;
|
|
ObjectID id;
|
|
|
|
id = deepCopy(obj, Nothing, TilePoint(0, 0, 0));
|
|
|
|
newObj = GameObject::objectAddress(id);
|
|
if (newParentID != Nothing) {
|
|
TilePoint slot;
|
|
|
|
if (newParent->getAvailableSlot(newObj, &slot))
|
|
newObj->move(Location(slot, newParentID));
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Add an enchantment to the object or actor
|
|
// GameObject id "c" addEnchantment( int majorType,
|
|
// int minorType,
|
|
// int amount,
|
|
// int duration );
|
|
|
|
int16 scriptGameObjectAddEnchantment(int16 *args) {
|
|
OBJLOG(Enchant);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return EnchantObject(obj->thisID(),
|
|
makeEnchantmentID(args[0], args[1], args[2]),
|
|
args[3]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Add an enchantment to the object or actor
|
|
// GameObject id "c" dispelEnchantment( int majorType, int minorType );
|
|
|
|
int16 scriptGameObjectRemoveEnchantment(int16 *args) {
|
|
OBJLOG(Disenchant);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return DispelObjectEnchantment(obj->thisID(),
|
|
makeEnchantmentID(args[0], args[1], 0));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Locates an enchantment object within the actor
|
|
// GameObject id "c" findEnchantment( int majorType, int minorType );
|
|
|
|
int16 scriptGameObjectFindEnchantment(int16 *args) {
|
|
OBJLOG(FindEnchantment);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return FindObjectEnchantment(obj->thisID(),
|
|
makeEnchantmentID(args[0], args[1], 0));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determines if this object is currently in use.
|
|
// int "c" inUse( void );
|
|
|
|
int16 scriptGameObjectInUse(int16 *) {
|
|
OBJLOG(InUse);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return obj->proto()->isObjectBeingUsed(obj);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the specified scratch variable value
|
|
// int "c" getScratchVar( int index );
|
|
|
|
int16 scriptActorGetScratchVar(int16 *args) {
|
|
OBJLOG(GetScratchVar);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->_scriptVar[args[0]];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the specified scratch variable to a new value
|
|
// int "c" setScratchVar( int index, int newVal );
|
|
|
|
int16 scriptActorSetScratchVar(int16 *args) {
|
|
OBJLOG(SetScratchVar);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 oldVal = a->_scriptVar[args[0]];
|
|
|
|
a->_scriptVar[args[0]] = args[1];
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return this actor's disposition
|
|
// int "c" getDisposition( void );
|
|
|
|
int16 scriptActorGetDisposition(int16 *args) {
|
|
OBJLOG(GetDisposition);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->getDisposition();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set this actor's disposition
|
|
// int "c" setDisposition( int newDisp );
|
|
|
|
int16 scriptActorSetDisposition(int16 *args) {
|
|
OBJLOG(SetDisposition);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->setDisposition(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the value of a specified skill
|
|
// int "c" getSkill( int skillID );
|
|
|
|
int16 scriptActorGetSkill(int16 *args) {
|
|
OBJLOG(GetSkill);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->getStats()->skill(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set a specified skill to a specified value
|
|
// int "c" setSkill( int skillID, int newVal );
|
|
|
|
int16 scriptActorSetSkill(int16 *args) {
|
|
OBJLOG(SetSkill);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
uint8 &skillRef = a->getStats()->skill(args[0]);
|
|
uint8 oldVal = skillRef;
|
|
|
|
skillRef = args[1];
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the value of a specified base skill
|
|
// int "c" getBaseSkill( int skillID );
|
|
|
|
int16 scriptActorGetBaseSkill(int16 *args) {
|
|
OBJLOG(GetBaseSkill);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->getBaseStats()->skill(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set a specified base skill to a specified value
|
|
// int "c" setBaseSkill( int skillID, int newVal );
|
|
|
|
int16 scriptActorSetBaseSkill(int16 *args) {
|
|
OBJLOG(SetBaseSkill);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
uint8 &skillRef = a->getBaseStats()->skill(args[0]);
|
|
uint8 oldVal = skillRef;
|
|
|
|
|
|
// If not a player actor, do nothing
|
|
if (isPlayerActor(a)) skillRef = args[1];
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the value of the actor's vitality
|
|
// int "c" getVitality( void );
|
|
|
|
int16 scriptActorGetVitality(int16 *) {
|
|
OBJLOG(GetVitality);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
debugC(2, kDebugScripts, " - value = %d", a->getStats()->vitality);
|
|
return a->getStats()->vitality;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the actor's vitality to a specified value
|
|
// int "c" setVitality( int newVal );
|
|
|
|
int16 scriptActorSetVitality(int16 *args) {
|
|
OBJLOG(SetVitality);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (a->_godmode)
|
|
return 0;
|
|
|
|
int16 &vitalityRef = a->getStats()->vitality;
|
|
int16 oldVal = vitalityRef;
|
|
PlayerActorID pID;
|
|
debugC(2, kDebugScripts, " - value = %d", args[0]);
|
|
|
|
vitalityRef = args[0];
|
|
if (actorToPlayerID(a, pID)) updateBrotherControls(pID);
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the value of the actor's base vitality
|
|
// int "c" getBaseVitality( void );
|
|
|
|
int16 scriptActorGetBaseVitality(int16 *) {
|
|
OBJLOG(GetBaseVitality);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->getBaseStats()->vitality;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the actor's base vitality to a specified value
|
|
// int "c" setBaseVitality( int newVal );
|
|
|
|
int16 scriptActorSetBaseVitality(int16 *args) {
|
|
OBJLOG(SetBaseVitality);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 &vitalityRef = a->getBaseStats()->vitality;
|
|
int16 oldVal = vitalityRef;
|
|
PlayerActorID pID;
|
|
|
|
// If not a player actor, do nothing
|
|
if (actorToPlayerID(a, pID)) {
|
|
vitalityRef = args[0];
|
|
updateBrotherControls(pID);
|
|
}
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the value of the specified color of mana
|
|
// int "c" getMana( int manaID );
|
|
|
|
int16 scriptActorGetMana(int16 *args) {
|
|
OBJLOG(GetMana);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->getStats()->mana(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the specified mana to the specified value
|
|
// int "c" setMana( int manaID, int newVal );
|
|
|
|
int16 scriptActorSetMana(int16 *args) {
|
|
OBJLOG(SetMana);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 &manaRef = a->getStats()->mana(args[0]);
|
|
int16 oldVal = manaRef;
|
|
PlayerActorID pID;
|
|
|
|
manaRef = args[1];
|
|
if (actorToPlayerID(a, pID)) updateBrotherControls(pID);
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the value of the specified color of base mana
|
|
// int "c" getBaseMana( int manaID );
|
|
|
|
int16 scriptActorGetBaseMana(int16 *args) {
|
|
OBJLOG(GetBaseMana);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->getBaseStats()->mana(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the specified base mana to the specified value
|
|
// int "c" setBaseMana( int manaID, int newVal );
|
|
|
|
int16 scriptActorSetBaseMana(int16 *args) {
|
|
OBJLOG(SetBaseMana);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
int16 &manaRef = a->getBaseStats()->mana(args[0]);
|
|
int16 oldVal = manaRef;
|
|
PlayerActorID pID;
|
|
|
|
// If not a player actor, do nothing
|
|
if (isPlayerActor(a)) manaRef = args[1];
|
|
if (actorToPlayerID(a, pID)) updateBrotherControls(pID);
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get actor's schedule
|
|
// int "c" getSchedule( void );
|
|
|
|
int16 scriptActorGetSchedule(int16 *args) {
|
|
OBJLOG(GetSchedule);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->_schedule;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set actor's schedule -- also returns old schedule
|
|
// int "c" setSchedule( int schedule );
|
|
|
|
int16 scriptActorSetSchedule(int16 *args) {
|
|
OBJLOG(SetSchedule);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
uint16 oldSchedule = a->_schedule;
|
|
|
|
a->_schedule = (uint16)args[0];
|
|
|
|
if (a->getAssignment() != nullptr)
|
|
delete a->getAssignment();
|
|
|
|
return (int16)oldSchedule;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Lobotomize the actor
|
|
// void "c" lobotomize( void );
|
|
|
|
int16 scriptActorLobotomize(int16 *args) {
|
|
OBJLOG(Lobotomize);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
a->lobotomize();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// De-lobotomize the actor
|
|
// void "c" delobotomize( void );
|
|
|
|
int16 scriptActorDelobotomize(int16 *args) {
|
|
OBJLOG(Delobotomize);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
a->delobotomize();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Determine if an action is available
|
|
// int "c" isActionAvailable( int action, int anyDir );
|
|
|
|
int16 scriptActorIsActionAvailable(int16 *args) {
|
|
OBJLOG(IsActionAvailable);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->isActionAvailable(args[0], args[1]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the current animation for this actor. Returns the number
|
|
// of poses in the sequence, or 0 if there are no poses in the
|
|
// sequence.
|
|
// int "c" setAction( int action, int flags );
|
|
|
|
int16 scriptActorSetAction(int16 *args) {
|
|
OBJLOG(SetAction);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->setAction(args[0], args[1]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the number of animation frames in the specified action
|
|
// for the specified direction.
|
|
// int "c" animationFrames( int action, int dir );
|
|
|
|
int16 scriptActorAnimationFrames(int16 *args) {
|
|
OBJLOG(AnimationFrames);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->animationFrames(args[0], args[1]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Update the current animation sequence to the next frame.
|
|
// Returns true if there are more animation frames in the current
|
|
// sequence.
|
|
// int "c" nextAnimationFrame( void );
|
|
|
|
int16 scriptActorNextAnimationFrame(int16 *args) {
|
|
OBJLOG(NextAnimationFrame);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->nextAnimationFrame();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Causes actor to face in a new direction, and returns old actor facing
|
|
// int "c" face( int direction );
|
|
|
|
int16 scriptActorFace(int16 *args) {
|
|
OBJLOG(Face);
|
|
int16 oldFacing = 0;
|
|
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
oldFacing = a->_currentFacing;
|
|
|
|
a->_currentFacing = args[0] & 7;
|
|
}
|
|
|
|
return oldFacing;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Causes actor to face towards another object or actor,
|
|
// returns old facing
|
|
// int "c" faceTowards( GameObject id );
|
|
|
|
int16 scriptActorFaceTowards(int16 *args) {
|
|
OBJLOG(FaceTowards);
|
|
int16 oldFacing = 0;
|
|
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
assert(isObject(args[0]) || isActor(args[0]));
|
|
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
oldFacing = a->_currentFacing;
|
|
|
|
a->_currentFacing =
|
|
(GameObject::objectAddress(args[0])->getLocation()
|
|
- a->getLocation()).quickDir();
|
|
}
|
|
|
|
return oldFacing;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Causes actor to turn to a new direction.
|
|
// int "c" turn( int direction, int flags );
|
|
|
|
int16 scriptActorTurn(int16 *args) {
|
|
OBJLOG(Turn);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (a->isDead()) return 0;
|
|
|
|
uint16 flags = args[1];
|
|
|
|
if (flags & kMoveWait) {
|
|
thisThread->waitForEvent(Thread::waitOther, nullptr);
|
|
MotionTask::turn(getThreadID(thisThread), *a, args[0] & 7);
|
|
} else {
|
|
MotionTask::turn(*a, args[0] & 7);
|
|
return kMotionStarted;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Causes actor to turn towards another object or actor.
|
|
// int "c" turnTowards( GameObject id, int flags );
|
|
|
|
int16 scriptActorTurnTowards(int16 *args) {
|
|
OBJLOG(TurnTowards);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
assert(isObject(args[0]) || isActor(args[0]));
|
|
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (a->isDead()) return 0;
|
|
|
|
uint16 flags = args[1];
|
|
Direction dir;
|
|
|
|
dir = (GameObject::objectAddress(args[0])->getLocation()
|
|
- a->getLocation()).quickDir();
|
|
|
|
if (flags & kMoveWait) {
|
|
thisThread->waitForEvent(Thread::waitOther, nullptr);
|
|
MotionTask::turn(getThreadID(thisThread), *a, dir);
|
|
} else {
|
|
MotionTask::turn(*a, dir);
|
|
return kMotionStarted;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
//-----------------------------------------------------------------------
|
|
// Walk the actor to a point
|
|
// int "c" walk( int u, int v, int z, int flags );
|
|
|
|
int16 scriptActorWalk(int16 *args) {
|
|
OBJLOG(Walk);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (a->isDead()) return 0;
|
|
|
|
TilePoint dest(args[0], args[1], args[2]);
|
|
uint16 flags = args[3];
|
|
|
|
if (flags & kMoveWait) {
|
|
thisThread->waitForEvent(Thread::waitOther, nullptr);
|
|
MotionTask::walkToDirect(
|
|
getThreadID(thisThread), *a, dest, flags & kMoveRun);
|
|
} else {
|
|
MotionTask::walkToDirect(*a, dest, flags & kMoveRun);
|
|
return kMotionStarted;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Constructs a patrol route assignment for this actor. Optional fourth
|
|
// parameter specifies the starting waypoint.
|
|
// int "c" assignPatrolRoute(
|
|
// int until,
|
|
// int routeNo,
|
|
// int flags,
|
|
// ... );
|
|
|
|
int16 scriptActorAssignPatrolRoute(int16 *args) {
|
|
OBJLOG(AssignPatrolRoute);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
if (new PatrolRouteAssignment(a,
|
|
(uint16)args[0]
|
|
* CalendarTime::kFramesPerHour,
|
|
args[1],
|
|
(uint8)args[2],
|
|
thisThread->_argCount >= 4
|
|
? args[3]
|
|
: -1)
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Assign a patrol route and specify the beginning and ending waypoints
|
|
// int "c" assignPartialPatrolRoute(
|
|
// int untilHour,
|
|
// int routeNo,
|
|
// int flags,
|
|
// int startingWayPoint,
|
|
// int endingWayPoint );
|
|
|
|
int16 scriptActorAssignPartialPatrolRoute(int16 *args) {
|
|
OBJLOG(AssignPartialPatrolRoute);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
if (new PatrolRouteAssignment(a,
|
|
(uint16)args[0]
|
|
* CalendarTime::kFramesPerHour,
|
|
args[1],
|
|
(uint8)args[2],
|
|
args[3],
|
|
args[4])
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Assign this actor to hunt to be near a location. The range
|
|
// parameter specifies how close to be near the target.
|
|
// int "c" assignBeNearLocation(
|
|
// int untilHour,
|
|
// int targetU,
|
|
// int targetV,
|
|
// int targetZ,
|
|
// int range );
|
|
|
|
int16 scriptActorAssignBeNearLocation(int16 *args) {
|
|
OBJLOG(AssignBeNearLocation);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
TilePoint targetLoc = TilePoint(args[1], args[2], args[3]);
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
if (new HuntToBeNearLocationAssignment(a,
|
|
args[0],
|
|
targetLoc,
|
|
args[4])
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Assign this actor to hunt to be near another actor.
|
|
// where the target actor is.
|
|
// int "c" assignBeNearActor(
|
|
// int until,
|
|
// Actor id target,
|
|
// int range,
|
|
// int track );
|
|
|
|
int16 scriptActorAssignBeNearActor(int16 *args) {
|
|
OBJLOG(AssignBeNearActor);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
assert(isActor(args[1]));
|
|
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj,
|
|
*targetActor;
|
|
|
|
targetActor = (Actor *)GameObject::objectAddress(args[1]);
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
if (new HuntToBeNearActorAssignment(a,
|
|
args[0],
|
|
targetActor,
|
|
args[2],
|
|
args[3])
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Assign this actor to kill another actor.
|
|
// int "c" assignKillActor( int until, Actor id target, int track );
|
|
|
|
int16 scriptActorAssignKillActor(int16 *args) {
|
|
OBJLOG(AssignKillActor);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
assert(isActor(args[1]));
|
|
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj,
|
|
*targetActor;
|
|
|
|
targetActor = (Actor *)GameObject::objectAddress(args[1]);
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
if (new HuntToKillAssignment(a,
|
|
args[0],
|
|
targetActor,
|
|
args[2])
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Constructs a tethered wander assignment for this actor
|
|
// int "c" assignTetheredWander(
|
|
// int until,
|
|
// int minU,
|
|
// int minV,
|
|
// int maxU,
|
|
// int maxV );
|
|
|
|
int16 scriptActorAssignTetheredWander(int16 *args) {
|
|
OBJLOG(AssignTetheredWander);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
TileRegion tetherReg;
|
|
int16 &minU = args[1],
|
|
&minV = args[2],
|
|
&maxU = args[3],
|
|
&maxV = args[4];
|
|
|
|
// Normalize the coordinates
|
|
if (maxU < minU) {
|
|
int16 temp = maxU;
|
|
maxU = minU;
|
|
minU = temp;
|
|
}
|
|
if (maxV < minV) {
|
|
int16 temp = maxV;
|
|
maxV = minV;
|
|
minV = temp;
|
|
}
|
|
|
|
tetherReg.min = TilePoint(minU, minV, 0);
|
|
tetherReg.max = TilePoint(maxU, maxV, 0);
|
|
|
|
if (new TetheredWanderAssignment(a,
|
|
(uint16)args[0]
|
|
* CalendarTime::kFramesPerHour,
|
|
tetherReg)
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Constructs a patrol route assignment for this actor
|
|
// int "c" assignAttend( int frames, GameObject id obj );
|
|
|
|
int16 scriptActorAssignAttend(int16 *args) {
|
|
OBJLOG(AssignAttend);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
// Delete the actor's current assignment
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
|
|
if (new AttendAssignment(a,
|
|
(g_vm->_calendar->frameInDay()
|
|
+ (uint16)args[0])
|
|
% CalendarTime::kFramesPerDay,
|
|
GameObject::objectAddress(args[1]))
|
|
!= nullptr)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Remove this actor's current assignment
|
|
// void "c" removeAssignment( void );
|
|
|
|
int16 scriptActorRemoveAssignment(int16 *args) {
|
|
OBJLOG(removeAssignment);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (a->getAssignment() != nullptr) delete a->getAssignment();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Bands this actor as a follower to the specified leader.
|
|
// void "c" bandWith( Actor id leader );
|
|
|
|
int16 scriptActorBandWith(int16 *args) {
|
|
OBJLOG(BandWith);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
assert(isActor(args[0]));
|
|
|
|
a->bandWith((Actor *)GameObject::objectAddress(args[0]));
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Remove the actor from his current band.
|
|
// void "c" disband( void );
|
|
|
|
int16 scriptActorDisband(int16 *) {
|
|
OBJLOG(Disband);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
a->disband();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns this actor's leader's ID.
|
|
// Actor id "c" getLeader( void );
|
|
|
|
int16 scriptActorGetLeader(int16 *) {
|
|
OBJLOG(GetLeader);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->_leader != nullptr ? a->_leader->thisID() : Nothing;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns the number of followers this actor has.
|
|
// int "c" numFollowers( void );
|
|
|
|
int16 scriptActorNumFollowers(int16 *) {
|
|
OBJLOG(ActorNumFollowers);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
return a->_followers != nullptr ? a->_followers->size() : 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns the ID of the specified follower.
|
|
// Actor id "c" getFollower( int followerNum );
|
|
|
|
int16 scriptActorGetFollower(int16 *args) {
|
|
OBJLOG(GetFollower);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
assert(a->_followers != nullptr);
|
|
assert(args[0] < a->_followers->size());
|
|
|
|
return (*a->_followers)[args[0]]->thisID();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Routine that is called by actor class to use that actor's
|
|
// knowledge list
|
|
// int "c" useKnowledge( GameObject id );
|
|
|
|
int16 scriptActorUseKnowledge(int16 *) {
|
|
OBJLOG(UseKnowledge);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
a->useKnowledge(thisThread->_threadArgs);
|
|
}
|
|
|
|
return thisThread->_threadArgs.returnVal;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// add knowledge package to actor
|
|
// void "c" addKnowledge( int kpIndex );
|
|
|
|
int16 scriptActorAddKnowledge(int16 *args) {
|
|
OBJLOG(AddKnowledge);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
a->addKnowledge(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// delete knowledge package delete actor
|
|
// void "c" deleteKnowledge( int kpIndex );
|
|
|
|
int16 scriptActorDeleteKnowledge(int16 *args) {
|
|
OBJLOG(DeleteKnowledge);
|
|
if (isActor(((ObjectData *)thisThread->_thisObject)->obj)) {
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (args[0] == 0) a->clearKnowledge();
|
|
else a->removeKnowledge(args[0]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// add knowledge package to actor (lasts for duration of mission)
|
|
// void "c" addMissionKnowledge( int missionID, int kpIndex );
|
|
|
|
int16 scriptActorAddMissionKnowledge(int16 *args) {
|
|
OBJLOG(AddMissionKnowledge);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
ActiveMission *am = ActiveMission::missionAddress(args[0]);
|
|
|
|
if (isActor(obj)) {
|
|
return am->addKnowledgeID(obj->thisID(), args[1]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// delete mission knowledge package from actor
|
|
// void "c" removeMissionKnowledge( int missionID, int kpIndex );
|
|
|
|
int16 scriptActorDeleteMissionKnowledge(int16 *args) {
|
|
OBJLOG(DeleteMissionKnowledge);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
ActiveMission *am = ActiveMission::missionAddress(args[0]);
|
|
|
|
if (isActor(obj)) {
|
|
return am->removeKnowledgeID(obj->thisID(), args[1]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Deduct gold or other payment type from actor
|
|
// void "c" deductPayment( int paymentTypeProto, int paymentAmount );
|
|
|
|
int16 scriptActorDeductPayment(int16 *args) {
|
|
OBJLOG(DeductPayment);
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
ProtoObj *currencyProto = g_vm->_objectProtos[args[0]];
|
|
int32 paymentAmount = args[1];
|
|
int32 paymentFound = 0;
|
|
GameObject *obj, *delObj = nullptr;
|
|
ObjectID id;
|
|
bool mergeable =
|
|
currencyProto->flags & ResourceObjectPrototype::objPropMergeable;
|
|
|
|
RecursiveContainerIterator iter(a);
|
|
|
|
// See if he has enough currency
|
|
for (id = iter.first(&obj); id != Nothing; id = iter.next(&obj)) {
|
|
// For each object of appropriate currency type
|
|
if (isObject(id) && obj->proto() == currencyProto) {
|
|
if (mergeable) paymentFound += obj->getExtra();
|
|
else paymentFound++;
|
|
|
|
if (paymentFound >= paymentAmount) break;
|
|
}
|
|
}
|
|
|
|
// If he doesn't have enough, return false.
|
|
if (paymentFound < paymentAmount) return false;
|
|
|
|
// Now, deduct the actual currency
|
|
for (id = iter.first(&obj); id != Nothing; id = iter.next(&obj)) {
|
|
// If the object is valid currency
|
|
if (isObject(id) && obj->proto() == currencyProto) {
|
|
// Mergeable object use the mass count
|
|
if (mergeable) {
|
|
int massCount = obj->getExtra();
|
|
|
|
if (massCount > paymentAmount) {
|
|
obj->setExtra(massCount - paymentAmount);
|
|
g_vm->_cnm->setUpdate(obj->IDParent());
|
|
break;
|
|
} else {
|
|
if (delObj) {
|
|
ObjectID dParent = delObj->IDParent();
|
|
delObj->deleteObject();
|
|
g_vm->_cnm->setUpdate(dParent);
|
|
}
|
|
paymentAmount -= massCount;
|
|
delObj = obj;
|
|
if (paymentAmount == 0)
|
|
break;
|
|
}
|
|
} else {
|
|
// Non-mergeable objects count as 1
|
|
paymentAmount--;
|
|
if (delObj) {
|
|
ObjectID dParent = delObj->IDParent();
|
|
delObj->deleteObject();
|
|
g_vm->_cnm->setUpdate(dParent);
|
|
}
|
|
delObj = obj;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (delObj) {
|
|
ObjectID dParent = delObj->IDParent();
|
|
delObj->deleteObject();
|
|
g_vm->_cnm->setUpdate(dParent);
|
|
}
|
|
|
|
// Payment succeeded!
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Count the amount of gold or other payment type actor has
|
|
// void "c" countPayment( int paymentTypeProto );
|
|
|
|
int16 scriptActorCountPayment(int16 *args) {
|
|
OBJLOG(CountPayment);
|
|
Actor *a = (Actor *)((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
ProtoObj *currencyProto = g_vm->_objectProtos[args[0]];
|
|
int32 paymentFound = 0;
|
|
GameObject *obj = nullptr;
|
|
ObjectID id;
|
|
bool mergeable =
|
|
currencyProto->flags & ResourceObjectPrototype::objPropMergeable;
|
|
|
|
RecursiveContainerIterator iter(a);
|
|
|
|
for (id = iter.first(&obj); id != Nothing; id = iter.next(&obj)) {
|
|
if (isObject(id) && obj->proto() == currencyProto) {
|
|
if (mergeable) paymentFound += obj->getExtra();
|
|
else paymentFound++;
|
|
}
|
|
}
|
|
|
|
return paymentFound;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Physician, heal thyself...
|
|
// void "c" acceptHealing( int amt );
|
|
|
|
int16 scriptActorAcceptHealing(int16 *args) {
|
|
OBJLOG(acceptHealing);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->acceptHealing(obj->thisID(), args[0]);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Hurt me!
|
|
// void "c" acceptDamage( GameObject id enactor, absDamage, type );
|
|
|
|
int16 scriptActorAcceptDamage(int16 *args) {
|
|
OBJLOG(acceptHealing);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
obj->acceptDamage(args[0], args[1], (enum effectDamageTypes)args[2]);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Ressurect
|
|
// void "c" imNotQuiteDead( void );
|
|
|
|
int16 scriptActorImNotQuiteDead(int16 *args) {
|
|
OBJLOG(imNotQuiteDead);
|
|
GameObject *obj = ((ObjectData *)thisThread->_thisObject)->obj;
|
|
|
|
if (isActor(obj)) {
|
|
((Actor *)obj)->imNotQuiteDead();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Actor script call table
|
|
|
|
C_Call *actorCFuncList[] = {
|
|
scriptGameObjectThisID,
|
|
scriptGameObjectRecharge,
|
|
scriptGameObjectGetChargeType,
|
|
scriptActorMove,
|
|
scriptActorMoveRel,
|
|
scriptActorTransfer,
|
|
scriptMoveRandom,
|
|
scriptActorGetName,
|
|
scriptActorSetName,
|
|
scriptActorGetProto,
|
|
scriptActorSetProto,
|
|
scriptActorGetProtoClass,
|
|
scriptActorGetScript,
|
|
scriptActorSetScript,
|
|
|
|
scriptGameObjectUse,
|
|
scriptGameObjectUseOn,
|
|
scriptGameObjectUseOnTAI,
|
|
scriptGameObjectDrop,
|
|
scriptGameObjectDropOn,
|
|
scriptGameObjectDropMergeableOn,
|
|
scriptGameObjectDropOnTAI,
|
|
|
|
scriptActorSay,
|
|
scriptActorSayText,
|
|
scriptActorObjectType,
|
|
scriptActorCopyObject,
|
|
|
|
scriptGameObjectIsActivated,
|
|
|
|
scriptActorGetOpen,
|
|
scriptActorGetLocked,
|
|
scriptActorGetImportant,
|
|
scriptActorSetImportant,
|
|
scriptActorGetScavengable,
|
|
scriptActorSetScavengable,
|
|
|
|
scriptGameObjectAddTimer,
|
|
scriptGameObjectAddStdTimer,
|
|
scriptGameObjectRemoveTimer,
|
|
scriptGameObjectRemoveAllTimers,
|
|
|
|
scriptGameObjectAddProtaganistSensor,
|
|
scriptGameObjectAddSpecificActorSensor,
|
|
scriptGameObjectAddSpecificObjectSensor,
|
|
scriptGameObjectAddActorPropertySensor,
|
|
scriptGameObjectAddObjectPropertySensor,
|
|
scriptGameObjectAddEventSensor,
|
|
scriptGameObjectRemoveSensor,
|
|
scriptGameObjectRemoveAllSensors,
|
|
|
|
scriptGameObjectCanSenseProtaganist,
|
|
scriptGameObjectCanSenseSpecificActor,
|
|
scriptGameObjectCanSenseSpecificObject,
|
|
scriptGameObjectCanSenseActorProperty,
|
|
scriptGameObjectCanSenseObjectProperty,
|
|
|
|
scriptGameObjectGetActualScript,
|
|
scriptGameObjectGetProtoScript,
|
|
|
|
scriptGameObjectGetMass,
|
|
scriptGameObjectSetMass,
|
|
|
|
scriptGameObjectGetExtra,
|
|
scriptGameObjectSetExtra,
|
|
|
|
scriptGameObjectDeepCopy,
|
|
scriptGameObjectAddEnchantment,
|
|
scriptGameObjectRemoveEnchantment,
|
|
scriptGameObjectFindEnchantment,
|
|
|
|
scriptGameObjectInUse,
|
|
|
|
scriptActorGetScratchVar,
|
|
scriptActorSetScratchVar,
|
|
|
|
scriptActorGetDisposition,
|
|
scriptActorSetDisposition,
|
|
|
|
scriptActorGetSkill,
|
|
scriptActorSetSkill,
|
|
scriptActorGetBaseSkill,
|
|
scriptActorSetBaseSkill,
|
|
|
|
scriptActorGetVitality,
|
|
scriptActorSetVitality,
|
|
scriptActorGetBaseVitality,
|
|
scriptActorSetBaseVitality,
|
|
|
|
scriptActorGetMana,
|
|
scriptActorSetMana,
|
|
scriptActorGetBaseMana,
|
|
scriptActorSetBaseMana,
|
|
|
|
scriptActorGetSchedule,
|
|
scriptActorSetSchedule,
|
|
|
|
scriptActorLobotomize,
|
|
scriptActorDelobotomize,
|
|
scriptActorIsActionAvailable,
|
|
scriptActorSetAction,
|
|
scriptActorAnimationFrames,
|
|
scriptActorNextAnimationFrame,
|
|
scriptActorFace,
|
|
scriptActorFaceTowards,
|
|
scriptActorTurn,
|
|
scriptActorTurnTowards,
|
|
scriptActorWalk,
|
|
|
|
scriptActorAssignPatrolRoute,
|
|
scriptActorAssignPartialPatrolRoute,
|
|
scriptActorAssignBeNearLocation,
|
|
scriptActorAssignBeNearActor,
|
|
scriptActorAssignKillActor,
|
|
scriptActorAssignTetheredWander,
|
|
scriptActorAssignAttend,
|
|
scriptActorRemoveAssignment,
|
|
|
|
scriptActorBandWith,
|
|
scriptActorDisband,
|
|
scriptActorGetLeader,
|
|
scriptActorNumFollowers,
|
|
scriptActorGetFollower,
|
|
|
|
scriptActorUseKnowledge,
|
|
scriptActorAddKnowledge,
|
|
scriptActorDeleteKnowledge,
|
|
scriptActorAddMissionKnowledge,
|
|
scriptActorDeleteMissionKnowledge,
|
|
|
|
scriptActorDeductPayment,
|
|
scriptActorCountPayment,
|
|
|
|
scriptActorAcceptHealing,
|
|
scriptActorAcceptDamage,
|
|
scriptActorImNotQuiteDead,
|
|
};
|
|
|
|
CallTable actorCFuncs = { actorCFuncList, ARRAYSIZE(actorCFuncList), 0 };
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the id of this TAI
|
|
// TileActivityInstance id "c" thisID( void );
|
|
|
|
int16 scriptTagThisID(int16 *) {
|
|
MONOLOG(TAG::ThisID);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->thisID();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the current state of this tag
|
|
// int "c" getState( void );
|
|
|
|
int16 scriptTagGetState(int16 *args) {
|
|
MONOLOG(TAG::GetState);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->getInstanceState(ai->getMapNum());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the tag instance to a given state
|
|
// void "c" setState( int state );
|
|
|
|
int16 scriptTagSetState(int16 *args) {
|
|
MONOLOG(TAG::SetState);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
ai->setInstanceState(ai->getMapNum(), args[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the number of associations for this tag
|
|
// int "c" numAssociations( void );
|
|
|
|
int16 scriptTagNumAssoc(int16 *args) {
|
|
MONOLOG(TAG::NumAssoc);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->_data.numAssociations;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the Nth association for this tag
|
|
// TileActivityInstance id "c" assoc( int assocNum );
|
|
|
|
int16 scriptTagAssoc(int16 *args) {
|
|
MONOLOG(TAG::Assoc);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
int mapNum = ai->getMapNum();
|
|
|
|
assert(args[0] >= 0);
|
|
assert(args[0] < ai->_data.numAssociations);
|
|
assert(mapNum >= 0);
|
|
assert(mapNum < 8);
|
|
|
|
return (mapList[mapNum].assocList)[ai->_data.associationOffset + args[0]];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the target U coord of this tag
|
|
// int "c" getTargetU( void );
|
|
|
|
int16 scriptTagGetTargetU(int16 *args) {
|
|
MONOLOG(TAG::GetTargetU);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->_data.instance.targetU;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the target V coord of this tag
|
|
// int "c" getTargetV( void );
|
|
|
|
int16 scriptTagGetTargetV(int16 *) {
|
|
MONOLOG(TAG::GetTargetV);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->_data.instance.targetV;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the target Z coord of this tag
|
|
// int "c" getTargetU( void );
|
|
|
|
int16 scriptTagGetTargetZ(int16 *) {
|
|
MONOLOG(TAG::GetTargetZ);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->_data.instance.targetZ;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the target world coord of this tag
|
|
// int "c" getTargetW( void );
|
|
|
|
int16 scriptTagGetTargetW(int16 *) {
|
|
MONOLOG(TAG::GetTargetW);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->_data.instance.worldNum;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the state of the "locked" bit
|
|
// int "c" isLocked( void );
|
|
|
|
int16 scriptTagIsLocked(int16 *) {
|
|
MONOLOG(TAG::IsLocked);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->isLocked() ? true : false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Change the state of the "locked" bit.
|
|
// int "c" setLocked( void );
|
|
|
|
|
|
int16 scriptTagSetLocked(int16 *args) {
|
|
MONOLOG(TAG::SetLocked);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
ai->setLocked(args[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the tag's key type
|
|
// int "c" getKeyType( void );
|
|
|
|
int16 scriptTagGetKeyType(int16 *) {
|
|
MONOLOG(TAG::GetKeyType);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return ai->lockType();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Use this TAI
|
|
// int "c" use( GameObject id enactor );
|
|
|
|
int16 scriptTagUse(int16 *args) {
|
|
MONOLOG(TAG::Use);
|
|
ActiveItem *tai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
return tai->use(args[0]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Animate the tag
|
|
// void "c" setAnimation( int flags, int targetState );
|
|
|
|
enum {
|
|
tileAnimateWait = (1 << 0) // wait until animation finished
|
|
};
|
|
|
|
int16 scriptTagSetAnimation(int16 *args) {
|
|
MONOLOG(TAG::SetAnimation);
|
|
extern uint32 parse_res_id(char IDstr[]);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
//TilePoint tagLoc;
|
|
int32 soundID = parse_res_id(STRING(args[2]));
|
|
Location ail = ai->getInstanceLocation();
|
|
|
|
// Assert that the state is valid
|
|
assert(args[1] >= 0);
|
|
assert(args[1] < ai->getGroup()->_data.group.numStates);
|
|
|
|
// If soundID is not NULL, then play the sound
|
|
if (soundID) playSoundAt(soundID, ail);
|
|
|
|
// If we want to wait until finished
|
|
if (args[0] & tileAnimateWait) {
|
|
// Wait for the animation
|
|
thisThread->waitForEvent(Thread::waitOther, nullptr);
|
|
|
|
// And start the tile animation
|
|
TileActivityTask::doScript(*ai, args[1], getThreadID(thisThread));
|
|
} else {
|
|
// Else just start the tile animation
|
|
TileActivityTask::doScript(*ai, args[1], NoThread);
|
|
}
|
|
|
|
return ai->lockType();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Wait for animation to finish.
|
|
// void "c" waitAnimate( void );
|
|
|
|
int16 scriptTagSetWait(int16 *args) {
|
|
MONOLOG(TAG::SetAnimation);
|
|
extern uint32 parse_res_id(char IDstr[]);
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
if (TileActivityTask::setWait(ai, getThreadID(thisThread))) {
|
|
// Wait for the animation
|
|
thisThread->waitForEvent(Thread::waitOther, nullptr);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Lock the tag for exclusive use, or else go to sleep
|
|
// void "c" obtainLock( void );
|
|
// void "c" releaseLock( void );
|
|
|
|
#if DEBUG*0
|
|
static int16 lockCount;
|
|
#endif
|
|
|
|
int16 scriptTagObtainLock(int16 *) {
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
if (ai->isExclusive() == false) {
|
|
ai->setExclusive(true);
|
|
#if DEBUG*0
|
|
lockCount += 1;
|
|
WriteStatusF(15, "Locked: %d\n", lockCount);
|
|
#endif
|
|
} else {
|
|
thisThread->waitForEvent(Thread::waitTagSemaphore, ai);
|
|
#if DEBUG*0
|
|
lockCount += 1;
|
|
WriteStatusF(15, "Locked: %d\n", lockCount);
|
|
#endif
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptTagReleaseLock(int16 *) {
|
|
ActiveItem *ai = ((ActiveItemData *)thisThread->_thisObject)->aItem;
|
|
|
|
ai->setExclusive(false);
|
|
#if DEBUG*0
|
|
lockCount -= 1;
|
|
WriteStatusF(15, "Locked: %d\n", lockCount);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// TAG Instance script call table
|
|
|
|
C_Call *tagCFuncList[] = {
|
|
scriptTagThisID,
|
|
scriptTagGetState,
|
|
scriptTagSetState,
|
|
scriptTagSetAnimation,
|
|
scriptTagNumAssoc,
|
|
scriptTagAssoc,
|
|
scriptTagGetTargetU,
|
|
scriptTagGetTargetV,
|
|
scriptTagGetTargetZ,
|
|
scriptTagGetTargetW,
|
|
scriptTagIsLocked,
|
|
scriptTagSetLocked,
|
|
scriptTagGetKeyType,
|
|
scriptTagUse,
|
|
scriptTagSetWait,
|
|
scriptTagObtainLock,
|
|
scriptTagReleaseLock,
|
|
};
|
|
|
|
CallTable tagCFuncs = { tagCFuncList, ARRAYSIZE(tagCFuncList), 0 };
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Find a mission by generator id
|
|
// void "c" deleteMission( int missionID );
|
|
|
|
int16 scriptMissionDelete(int16 *args) {
|
|
MONOLOG(ActiveMission::Delete);
|
|
ActiveMission *am = ((ActiveMissionData *)thisThread->_thisObject)->aMission;
|
|
|
|
am->cleanup();
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new object
|
|
// GameObject id "C" makeObject( int protoID,
|
|
// int nameIndex,
|
|
// int scriptIndex );
|
|
|
|
int16 scriptMakeObject(int16 *args);
|
|
|
|
int16 scriptMissionMakeObject(int16 *args) {
|
|
MONOLOG(TAG::MakeObject);
|
|
ActiveMission *am = ((ActiveMissionData *)thisThread->_thisObject)->aMission;
|
|
ObjectID id;
|
|
|
|
// If there's room in the mission to record the existence of the object
|
|
if (!am->spaceForObject()) return Nothing;
|
|
|
|
// Call the regular make-object function
|
|
id = scriptMakeObject(args);
|
|
|
|
// And record it in the mission object
|
|
if (id != Nothing) {
|
|
am->addObjectID(id);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new object
|
|
// GameObject id "C" makeActor( int protoID,
|
|
// int nameIndex,
|
|
// int scriptIndex,
|
|
// string appearance,
|
|
// int color );
|
|
|
|
int16 scriptMakeActor(int16 *args);
|
|
|
|
int16 scriptMissionMakeActor(int16 *args) {
|
|
MONOLOG(ActiveMission::MakeActor);
|
|
ActiveMission *am = ((ActiveMissionData *)thisThread->_thisObject)->aMission;
|
|
ObjectID id;
|
|
|
|
// If there's room in the mission to record the existence of the actor
|
|
if (!am->spaceForObject()) return Nothing;
|
|
|
|
// Call the regular make-actor function. Add in the "permanent"
|
|
// flag, since actor will be deleted at mission end.
|
|
args[6] |= kActorPermanent;
|
|
id = scriptMakeActor(args);
|
|
|
|
// And record it in the mission object
|
|
if (id != Nothing) {
|
|
am->addObjectID(id);
|
|
}
|
|
|
|
return id;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// ActiveMission Instance script call table
|
|
|
|
C_Call *missionCFuncList[] = {
|
|
scriptMissionDelete,
|
|
scriptMissionMakeObject,
|
|
scriptMissionMakeActor,
|
|
};
|
|
|
|
CallTable missionCFuncs = { missionCFuncList, ARRAYSIZE(missionCFuncList), 0 };
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Global functions
|
|
|
|
int16 scriptWriteMessage(int16 *args) {
|
|
MONOLOG(WriteMessage);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[1], &args[2]);
|
|
|
|
WriteStatusF(args[0], buffer);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Write a message to the status line
|
|
// void "C" status( string caption, ... );
|
|
|
|
int16 scriptStatus(int16 *args) {
|
|
MONOLOG(Status);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[0], &args[1]);
|
|
|
|
StatusMsg(buffer);
|
|
return 0;
|
|
}
|
|
|
|
void writeObject(char *str) {
|
|
warning("OBJ: %s", str);
|
|
}
|
|
|
|
int16 scriptWriteLog(int16 *args) {
|
|
MONOLOG(WriteLog);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[0], &args[1]);
|
|
debugC(2, kDebugScripts, "%s", buffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptWriteObject(int16 *args) {
|
|
MONOLOG(WriteObject);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[0], &args[1]);
|
|
writeObject(buffer);
|
|
return 0;
|
|
}
|
|
//-----------------------------------------------------------------------
|
|
// Put up an error-message dialog
|
|
// void "C" errorDialog( string caption, ... );
|
|
|
|
int16 scriptErrorDialog(int16 *args) {
|
|
MONOLOG(ErrorDialog);
|
|
char buffer[512];
|
|
|
|
stringf(buffer, sizeof buffer, args[1], &args[2]);
|
|
|
|
// WriteStatusF( 1, buffer );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Put up a user-notification dialog
|
|
// void "C" messageDialog( string caption, ... );
|
|
|
|
int16 scriptMessageDialog(int16 *args) {
|
|
MONOLOG(MessageDialog);
|
|
//stringf( buffer, sizeof buffer, args[1], &args[2] );
|
|
|
|
userDialog(STRING(args[0]),
|
|
STRING(args[1]),
|
|
args[2] ? STRING(args[2]) : nullptr,
|
|
nullptr,
|
|
nullptr);
|
|
|
|
// WriteStatusF( 1, buffer );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Put up a multiple-choice button dialog
|
|
// int "C" choiceDialog( string caption, string buttons, ... );
|
|
|
|
int16 scriptChoiceDialog(int16 *args) {
|
|
MONOLOG(ChoiceDialog);
|
|
//stringf( buffer, sizeof buffer, args[1], &args[2] );
|
|
|
|
userDialog(STRING(args[0]),
|
|
STRING(args[1]),
|
|
args[2] ? STRING(args[2]) : nullptr,
|
|
args[3] ? STRING(args[3]) : nullptr,
|
|
args[4] ? STRING(args[4]) : nullptr);
|
|
|
|
// WriteStatusF( 1, buffer );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Put up a placard (stone, wood, or brass)
|
|
// void "C" placard( int placardType, string text, ... );
|
|
|
|
// defined in uidialog.h
|
|
//enum placardTypes {
|
|
// WOOD_TYPE,
|
|
// STONE_TYPE,
|
|
// BRASS_TYPE
|
|
//};
|
|
|
|
int16 scriptPlacard(int16 *args) {
|
|
MONOLOG(Placard);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[1], &args[2]);
|
|
|
|
placardWindow(args[0], buffer); // plaq type, text
|
|
|
|
//GameDisplay( buffer, 0 );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Lock the display so that no updates occur
|
|
// void "C" lockDIsplay( int lockState );
|
|
|
|
int16 scriptLockDisplay(int16 *args) {
|
|
MONOLOG(LockDisplay);
|
|
// WriteStatusF( args[0], STRING( args[1] ) );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the current game mode
|
|
// void "C" setGameMode( int modeNumber );
|
|
|
|
int16 scriptSetGameMode(int16 *args) {
|
|
MONOLOG(SetGameMode);
|
|
// Mode zero is "game not running".
|
|
if (args[0] == 0)
|
|
endGame();
|
|
//gameRunning = false;
|
|
|
|
// REM: Add other modes
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Extended-sequence functions (all these functions automatically
|
|
// cause the script to go into extended sequnce mode).
|
|
|
|
int16 scriptWait(int16 *args) {
|
|
MONOLOG(Wait);
|
|
thisThread->_waitAlarm.set(args[0]);
|
|
thisThread->waitForEvent(Thread::waitDelay, nullptr);
|
|
thisThread->setExtended();
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptWaitFrames(int16 *args) {
|
|
MONOLOG(WaitFrames);
|
|
thisThread->_waitFrameAlarm.set(args[0]);
|
|
thisThread->waitForEvent(Thread::waitFrameDelay, nullptr);
|
|
thisThread->setExtended();
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Play a song (with optional fade-out of old song)
|
|
// void "C" playSong( int songID, int fade );
|
|
|
|
int16 scriptPlaySong(int16 *args) {
|
|
MONOLOG(PlaySong);
|
|
// WriteStatusF( args[0], STRING( args[1] ) );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Play sound effect (with optional looping) { volume = 0-127 }
|
|
// void "C" playFX( int fxID, int volume, int looped );
|
|
|
|
int16 scriptPlayFX(int16 *args) {
|
|
MONOLOG(PlayFX);
|
|
// WriteStatusF( args[0], STRING( args[1] ) );
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Type-casting function
|
|
// Actor id "C" object2Actor( GameObject id objID );
|
|
|
|
int16 scriptObject2Actor(int16 *args) {
|
|
MONOLOG(Object2Actor);
|
|
//return isActor(args[0]) ? args[0] : Nothing;
|
|
return args[0];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Generic script type casting function
|
|
|
|
int16 scriptGenericCast(int16 *args) {
|
|
MONOLOG(genericCast);
|
|
return args[0];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new object
|
|
// GameObject id "C" makeObject( int protoID,
|
|
// int nameIndex,
|
|
// int scriptIndex );
|
|
|
|
int16 scriptMakeObject(int16 *args) {
|
|
MONOLOG(MakeObject);
|
|
GameObject *obj = GameObject::newObject();
|
|
|
|
// REM: We need to throw some kind of SAGA exception...?
|
|
// (We don't have SAGA exceptions, only the C kind...)
|
|
if (obj == nullptr) {
|
|
return 0;
|
|
}
|
|
|
|
obj->setProtoNum(args[0]);
|
|
obj->setNameIndex(args[1]);
|
|
obj->setScript(args[2]);
|
|
|
|
// If it's a mergeable object, have it's mass count default to 1.
|
|
if (obj->proto()->flags & ResourceObjectPrototype::objPropMergeable)
|
|
obj->setExtra(1);
|
|
|
|
return obj->thisID();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Delete an existing object
|
|
// void "C" deleteObject( GameObject id objID );
|
|
|
|
int16 scriptDeleteObject(int16 *args) {
|
|
MONOLOG(DeleteObject);
|
|
GameObject *obj = GameObject::objectAddress(args[0]);
|
|
ObjectID oldParentID;
|
|
|
|
assert(obj);
|
|
oldParentID = obj->IDParent();
|
|
obj->deleteObjectRecursive();
|
|
g_vm->_cnm->setUpdate(oldParentID);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new object
|
|
// GameObject id "C" makeActor( int protoID,
|
|
// int nameIndex,
|
|
// int scriptIndex,
|
|
// string appearance,
|
|
// int color );
|
|
|
|
int16 scriptMakeActor(int16 *args) {
|
|
MONOLOG(MakeActor);
|
|
char *actorAppearanceName = STRING(args[3]);
|
|
int32 actorAppearanceNum;
|
|
Actor *a;
|
|
|
|
assert(actorAppearanceName);
|
|
actorAppearanceNum = READ_BE_INT32(actorAppearanceName);
|
|
|
|
a = Actor::newActor(
|
|
args[0],
|
|
args[1],
|
|
args[2],
|
|
actorAppearanceNum,
|
|
args[4],
|
|
args[5],
|
|
args[6]);
|
|
|
|
// REM: We need to throw some kind of SAGA exception...?
|
|
// (We don't have SAGA exceptions, only the C kind...)
|
|
if (a == nullptr) {
|
|
return 0;
|
|
}
|
|
|
|
return a->thisID();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the ID of the center actor
|
|
// Actor id "C" getCenterActor( void );
|
|
|
|
int16 scriptGetCenterActor(int16 *) {
|
|
MONOLOG(GetCenterActor);
|
|
return getCenterActorID();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// SAGA Import defs
|
|
//
|
|
// void "C" scriptPlaySound( string );
|
|
//
|
|
// void "C" scriptPlayVoice( string );
|
|
//
|
|
// void "C" scriptPlayLoop( string );
|
|
//
|
|
// void "C" scriptPlayMusic( string );
|
|
//
|
|
|
|
int16 scriptPlaySound(int16 *args) {
|
|
MONOLOG(PlaySound);
|
|
char *sID = STRING(args[0]);
|
|
|
|
PlaySound(sID);
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32 parse_res_id(char IDstr[]);
|
|
|
|
int16 scriptPlaySoundAt(int16 *args) {
|
|
MONOLOG(PlaySoundAt);
|
|
char *sID = STRING(args[0]);
|
|
args++;
|
|
int16 u = *args++; // << kTileUVShift;
|
|
int16 v = *args++; // << kTileUVShift;
|
|
int16 h = *args++;
|
|
Location l = Location(TilePoint(u, v, h), Nothing);
|
|
int32 soundID;
|
|
soundID = parse_res_id(sID);
|
|
|
|
if (soundID) playSoundAt(soundID, l);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptPlaySoundFrom(int16 *args) {
|
|
MONOLOG(PlaySoundAt);
|
|
char *sID = STRING(args[0]);
|
|
int32 soundID;
|
|
soundID = parse_res_id(sID);
|
|
GameObject *go = GameObject::objectAddress(args[1]);
|
|
assert(go != nullptr);
|
|
if (soundID) playSoundAt(soundID, go->notGetWorldLocation());
|
|
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptPlayMusic(int16 *args) {
|
|
MONOLOG(PlayMusic);
|
|
char *sID = STRING(args[0]);
|
|
PlayMusic(sID);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptPlayLoop(int16 *args) {
|
|
MONOLOG(PlayLoop);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void PlayLoopAt(char IDstr[], Location l);
|
|
|
|
int16 scriptPlayLoopAt(int16 *args) {
|
|
MONOLOG(PlayLoop);
|
|
char *sID = STRING(args[0]);
|
|
int16 u = *args++; // << kTileUVShift;
|
|
int16 v = *args++; // << kTileUVShift;
|
|
int16 h = *args++;
|
|
Location l = Location(TilePoint(u, v, h), Nothing);
|
|
PlayLoopAt(sID, l);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptPlayVoice(int16 *args) {
|
|
MONOLOG(PlayVoice);
|
|
char *sID = STRING(args[0]);
|
|
PlayVoice(sID);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// int "c" getHour( void );
|
|
|
|
int16 scriptGetHour(int16 *) {
|
|
MONOLOG(GetHour);
|
|
return g_vm->_calendar->_hour;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// int "c" getFrameInHour( void );
|
|
|
|
int16 scriptGetFrameInHour(int16 *) {
|
|
MONOLOG(GetFrameInHour);
|
|
return g_vm->_calendar->_frameInHour;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// int "c" getRandomBetween( int, int );
|
|
|
|
int16 scriptGetRandomBetween(int16 *args) {
|
|
MONOLOG(GetRandomBetween);
|
|
return (GetRandomBetween(args[0], args[1]));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Check if Object contained in another object
|
|
// bool "C" isContaining( GameObject id owner, GameObject id object);
|
|
|
|
int16 scriptIsContaining(int16 *args) {
|
|
MONOLOG(IsContaining);
|
|
GameObject *containerObject = GameObject::objectAddress(args[0]);
|
|
GameObject *containedObject = GameObject::objectAddress(args[1]);
|
|
|
|
return (containerObject->isContaining(containedObject));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// void "C" scriptPlayLongSound( string );
|
|
|
|
int16 scriptPlayLongSound(int16 *args) {
|
|
MONOLOG(PlayLongSound);
|
|
char *sID = STRING(args[0]);
|
|
|
|
PlayLongSound(sID);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// int "C" scriptResID( string ); GT - 03/04/1996
|
|
// converts a standard HRES resource ID into a 16-bit integer. The
|
|
// first character is interpreted as thousands, providing a total
|
|
// possible range of between 1-25,999.
|
|
//-----------------------------------------------------------------------
|
|
|
|
int16 scriptResID(int16 *args) {
|
|
char *sID = STRING(args[0]);
|
|
return (sID[0] - 'A') * 1000 + atoi(&sID[1]);
|
|
}
|
|
|
|
int16 scriptWorldNum2Object(int16 *args) {
|
|
MONOLOG(WorldNum2Object);
|
|
assert(args[0] >= 0);
|
|
// REM: I can't seem to find a symbolic constant for the
|
|
// maximum number of worlds. I know that it's currently 8.
|
|
assert(args[0] < 8);
|
|
|
|
return args[0] + WorldBaseID;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Append a set of strings to the book text
|
|
// void "C" bookText( string text, ... );
|
|
|
|
int16 scriptAppendBookText(int16 *args) {
|
|
MONOLOG(AppendBookText);
|
|
// If optional 4th parameter is present, then set actor facing
|
|
for (int i = 0; i < thisThread->_argCount; i++) {
|
|
char *bookText = STRING(args[i]);
|
|
|
|
appendBookText(bookText);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
#if 0
|
|
//-----------------------------------------------------------------------
|
|
// Append a single string to the scroll text, with printf formatting
|
|
// void "C" bookTextF( string text, ... );
|
|
|
|
int16 scriptAppendScrollTextF(int16 *args) {
|
|
MONOLOG(AppendScrollTextF);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[0], &args[1]);
|
|
|
|
appendBookText(buffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Append a set of strings to the scroll text
|
|
// void "C" bookText( string text, ... );
|
|
|
|
int16 scriptAppendScrollText(int16 *args) {
|
|
MONOLOG(AppendScrollText);
|
|
// If optional 4th parameter is present, then set actor facing
|
|
for (int i = 0; i < thisThread->_argCount; i++) {
|
|
char *ScrollText = STRING(args[i]);
|
|
|
|
appendBookText(ScrollText);
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Append a single string to the book text, with printf formatting
|
|
// void "C" bookTextF( string text, ... );
|
|
|
|
int16 scriptAppendBookTextF(int16 *args) {
|
|
MONOLOG(AppendBookTextF);
|
|
char buffer[256];
|
|
|
|
stringf(buffer, sizeof buffer, args[0], &args[1]);
|
|
|
|
appendBookText(buffer);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Assert an event for any sensors which might be looking for it
|
|
// void "c" assertEvent(
|
|
// int type,
|
|
// GameObject id directObject,
|
|
// GameObject id indirectObject );
|
|
|
|
int16 scriptAssertEvent(int16 *args) {
|
|
MONOLOG(AssertEvent);
|
|
GameEvent ev;
|
|
|
|
assert(isObject(args[1]) || isActor(args[1]));
|
|
assert(args[2] == Nothing
|
|
|| isObject(args[2])
|
|
|| isActor(args[2]));
|
|
|
|
ev.type = args[0];
|
|
ev.directObject = GameObject::objectAddress(args[1]);
|
|
ev.indirectObject = args[2] != Nothing
|
|
? GameObject::objectAddress(args[2])
|
|
: nullptr;
|
|
|
|
assertEvent(ev);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Spell casting
|
|
//
|
|
//bool "C" scriptCanCast (
|
|
// GameObject id casterID,
|
|
// GameObject id spellID);
|
|
//
|
|
//void "C" scriptCastSpellAtObject (
|
|
// GameObject id casterID,
|
|
// GameObject id spellID,
|
|
// GameObject id targetID);
|
|
//
|
|
//void "C" scriptCastSpellAtActor (
|
|
// GameObject id casterID,
|
|
// GameObject id spellID,
|
|
// GameObject id targetID);
|
|
//
|
|
//void "C" scriptCastSpellAtWorld (
|
|
// GameObject id casterID,
|
|
// GameObject id spellID);
|
|
//
|
|
//void "C" scriptCastSpellAtTAG (
|
|
// GameObject id casterID,
|
|
// GameObject id spellID,
|
|
// TileActivityInstance id target);
|
|
//
|
|
//void "C" scriptCastSpellAtTile (
|
|
// GameObject id casterID,
|
|
// GameObject id spellID,
|
|
// int u, int v, int h);
|
|
//
|
|
|
|
int16 scriptCanCast(int16 *args) {
|
|
MONOLOG(CanCast);
|
|
GameObject *caster = GameObject::objectAddress(*args++);
|
|
SkillProto *spell = skillProtoFromID(*args++);
|
|
assert(caster);
|
|
assert(spell);
|
|
return canCast(caster, spell);
|
|
}
|
|
|
|
int16 scriptCastSpellAtObject(int16 *args) {
|
|
MONOLOG(CastSpellAtObject);
|
|
GameObject *caster = GameObject::objectAddress(*args++);
|
|
SkillProto *spell = skillProtoFromID(*args++);
|
|
GameObject *target = GameObject::objectAddress(*args++);
|
|
assert(caster);
|
|
assert(spell);
|
|
assert(target);
|
|
castSpell(caster, target, spell);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptCastSpellAtActor(int16 *args) {
|
|
MONOLOG(CastSpellAtActor);
|
|
GameObject *caster = GameObject::objectAddress(*args++);
|
|
SkillProto *spell = skillProtoFromID(*args++);
|
|
GameObject *target = GameObject::objectAddress(*args++);
|
|
assert(caster);
|
|
assert(spell);
|
|
assert(target);
|
|
castSpell(caster, target, spell);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptCastSpellAtWorld(int16 *args) {
|
|
MONOLOG(CastSpellAtWorld);
|
|
GameObject *caster = GameObject::objectAddress(*args++);
|
|
SkillProto *spell = skillProtoFromID(*args++);
|
|
assert(caster);
|
|
assert(spell);
|
|
castUntargetedSpell(caster, spell);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptCastSpellAtTAG(int16 *args) {
|
|
MONOLOG(CastSpellAtTAG);
|
|
GameObject *caster = GameObject::objectAddress(*args++);
|
|
SkillProto *spell = skillProtoFromID(*args++);
|
|
ActiveItem *ai = ActiveItem::activeItemAddress(*args++);
|
|
assert(caster);
|
|
assert(spell);
|
|
assert(ai);
|
|
castSpell(caster, ai, spell);
|
|
return 0;
|
|
}
|
|
|
|
int16 scriptCastSpellAtTile(int16 *args) {
|
|
MONOLOG(CastSpellAtTile);
|
|
GameObject *caster = GameObject::objectAddress(*args++);
|
|
SkillProto *spell = skillProtoFromID(*args++);
|
|
int16 u = *args++; // << kTileUVShift;
|
|
int16 v = *args++; // << kTileUVShift;
|
|
int16 h = *args++;
|
|
Location l = Location(TilePoint(u, v, h), Nothing);
|
|
assert(caster);
|
|
assert(spell);
|
|
castSpell(caster, l, spell);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Function to select a site for a monster actor or object.
|
|
// returns it's result by filling in the threadCoords therad var.
|
|
// If the return height is negative, then it failed.
|
|
// int "C" SelectNearbySite( int centerU,
|
|
// int centerV,
|
|
// int centerZ,
|
|
// int centerWorld,
|
|
// int minDist,
|
|
// int maxDist,
|
|
// int offScreenOnly );
|
|
|
|
int16 scriptSelectNearbySite(int16 *args) {
|
|
MONOLOG(SelectNearbySite);
|
|
TilePoint tp;
|
|
|
|
tp = selectNearbySite(args[3],
|
|
TilePoint(args[0], args[1], args[2]),
|
|
args[4],
|
|
args[5],
|
|
args[6]);
|
|
|
|
if (tp == Nowhere) return 0;
|
|
scriptCallFrame &scf = thisThread->_threadArgs;
|
|
|
|
scf.coords = tp;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Pick a random actor who is not dead
|
|
// GameObject id pickRandomLivingActor( ... );
|
|
|
|
int16 scriptPickRandomLivingActor(int16 *args) {
|
|
MONOLOG(PickRandomLivingActor);
|
|
int livingCount = 0,
|
|
i;
|
|
|
|
for (i = 0; i < thisThread->_argCount; i++) {
|
|
if (isActor(args[i])) {
|
|
Actor *a = (Actor *)GameObject::objectAddress(args[i]);
|
|
|
|
if (!a->isDead()) livingCount++;
|
|
}
|
|
}
|
|
|
|
if (livingCount <= 0) return Nothing;
|
|
|
|
livingCount = g_vm->_rnd->getRandomNumber(livingCount - 1);
|
|
|
|
for (i = 0; i < thisThread->_argCount; i++) {
|
|
if (isActor(args[i])) {
|
|
Actor *a = (Actor *)GameObject::objectAddress(args[i]);
|
|
|
|
if (!a->isDead()) {
|
|
if (livingCount == 0) return args[i];
|
|
livingCount--;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Nothing;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Create a new mission object
|
|
// int "c" newMission( GameObject id generatorID );
|
|
|
|
int16 scriptNewMission(int16 *args) {
|
|
MONOLOG(NewMission);
|
|
ActiveMission *am = ActiveMission::newMission(args[0], args[1]);
|
|
|
|
return am ? am->getMissionID() : -1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Find a mission by generator id
|
|
// int "c" findMission( GameObject id generatorID );
|
|
|
|
int16 scriptFindMission(int16 *args) {
|
|
MONOLOG(FindMission);
|
|
return ActiveMission::findMission(args[0]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the speed of a tile cycling range
|
|
// void "c" setTileCycleSpeed( int range, int speed );
|
|
|
|
int16 scriptSetTileCycleSpeed(int16 *args) {
|
|
MONOLOG(SetTileCycleSpeed);
|
|
extern CyclePtr _cycleList; // list of tile cycling info
|
|
|
|
TileCycleData &tcd = _cycleList[args[0]];
|
|
|
|
tcd._cycleSpeed = args[1];
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Set the state of a tile cycling range
|
|
// void "c" setTileCycleState( int range, int state );
|
|
|
|
int16 scriptSetTileCycleState(int16 *args) {
|
|
MONOLOG(SetTileCycleState);
|
|
extern CyclePtr _cycleList; // list of tile cycling info
|
|
|
|
TileCycleData &tcd = _cycleList[args[0]];
|
|
|
|
tcd._currentState = args[1];
|
|
tcd._counter = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Search a region of the tile map to see if any of the indicated
|
|
// objects are within that region.
|
|
// int "c" searchRegion( GameObject id world,
|
|
// int uMin. int vMin,
|
|
// int uMax, int vMax, ... );
|
|
|
|
int16 scriptSearchRegion(int16 *args) {
|
|
MONOLOG(SearchRegion);
|
|
GameWorld *worldPtr;
|
|
ObjectID searchObj;
|
|
int count = 0;
|
|
TilePoint minP,
|
|
maxP;
|
|
|
|
// Get a pointer to the world
|
|
assert(isWorld(args[0]));
|
|
worldPtr = (GameWorld *)GameObject::objectAddress(args[0]);
|
|
assert(worldPtr != nullptr);
|
|
|
|
minP.u = MIN(args[1], args[3]);
|
|
minP.v = MIN(args[2], args[4]);
|
|
minP.z = -128;
|
|
maxP.u = MAX(args[1], args[3]);
|
|
maxP.v = MAX(args[2], args[4]);
|
|
maxP.z = 127;
|
|
|
|
// Set up an iterator
|
|
RegionalObjectIterator iter(worldPtr, minP, maxP);
|
|
|
|
// Iterate through the search region
|
|
for (searchObj = iter.first(nullptr);
|
|
searchObj != Nothing;
|
|
searchObj = iter.next(nullptr)) {
|
|
// Starting from the 5th argument, until we reach _argCount,
|
|
// see if the iterated object matches one in the arg list
|
|
for (int i = 5; i < thisThread->_argCount; i++) {
|
|
if (args[i] == searchObj) {
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return number of items found
|
|
return count;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Helper function: Returns the number of objects in a TileRegion
|
|
|
|
int countObjectsInRegion(GameWorld *worldPtr, TileRegion &tr) {
|
|
ObjectID searchObj;
|
|
int count;
|
|
|
|
// Count how many objects are in the first region
|
|
RegionalObjectIterator iter(worldPtr,
|
|
tr.min,
|
|
tr.max);
|
|
|
|
for (searchObj = iter.first(nullptr), count = 0;
|
|
searchObj != Nothing;
|
|
searchObj = iter.next(nullptr)) {
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Helper Function: Returns a list of objects in a tile region
|
|
|
|
void listObjectsInRegion(
|
|
GameWorld *worldPtr,
|
|
TileRegion &tr,
|
|
ObjectID *list) {
|
|
ObjectID searchObj;
|
|
|
|
// Count how many objects are in the first region
|
|
RegionalObjectIterator iter(worldPtr,
|
|
tr.min,
|
|
tr.max);
|
|
|
|
for (searchObj = iter.first(nullptr);
|
|
searchObj != Nothing;
|
|
searchObj = iter.next(nullptr)) {
|
|
*list++ = searchObj;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Swap all of the objects within two regions
|
|
// void "c" swapRegions( GameObject id world1, int u1, int v1,
|
|
// GameObject id world2, int u2, int v2,
|
|
// int uSize, int vSize );
|
|
|
|
int16 scriptSwapRegions(int16 *args) {
|
|
MONOLOG(SwapRegions);
|
|
|
|
ObjectID worldID1 = args[0],
|
|
worldID2 = args[3];
|
|
GameWorld *worldPtr1,
|
|
*worldPtr2;
|
|
ObjectID *objArray1,
|
|
*objArray2;
|
|
int objCount1,
|
|
objCount2;
|
|
TileRegion region1,
|
|
region2;
|
|
|
|
assert(isWorld(worldID1));
|
|
assert(isWorld(worldID2));
|
|
|
|
worldPtr1 = (GameWorld *)GameObject::objectAddress(worldID1);
|
|
worldPtr2 = (GameWorld *)GameObject::objectAddress(worldID2);
|
|
|
|
assert(worldPtr1 != nullptr);
|
|
assert(worldPtr2 != nullptr);
|
|
|
|
region1.min.u = args[1];
|
|
region1.min.v = args[2];
|
|
region1.min.z = -128;
|
|
region1.max.u = args[1] + ABS(args[6]);
|
|
region1.max.v = args[2] + ABS(args[7]);
|
|
region1.max.z = 127;
|
|
|
|
region2.min.u = args[4];
|
|
region2.min.v = args[5];
|
|
region2.min.z = -128;
|
|
region2.max.u = args[4] + ABS(args[6]);
|
|
region2.max.v = args[5] + ABS(args[7]);
|
|
region2.max.z = 127;
|
|
|
|
// Count how many objects are in each region
|
|
objCount1 = countObjectsInRegion(worldPtr1, region1);
|
|
objCount2 = countObjectsInRegion(worldPtr2, region2);
|
|
|
|
// Allocate an array to hold object ID's for each region
|
|
objArray1 = new ObjectID[objCount1];
|
|
assert(objArray1);
|
|
objArray2 = new ObjectID[objCount2];
|
|
assert(objArray2);
|
|
|
|
// Get a list of the objects in each region
|
|
listObjectsInRegion(worldPtr1, region1, objArray1);
|
|
listObjectsInRegion(worldPtr2, region2, objArray2);
|
|
|
|
int i;
|
|
|
|
// Move all the objects in the first list to region 2
|
|
for (i = 0; i < objCount1; i++) {
|
|
GameObject *obj = GameObject::objectAddress(objArray1[i]);
|
|
Location loc;
|
|
TilePoint tp;
|
|
|
|
tp = obj->getLocation();
|
|
|
|
loc._context = worldID2;
|
|
loc.u = tp.u + region2.min.u - region1.min.u;
|
|
loc.v = tp.v + region2.min.v - region1.min.v;
|
|
loc.z = tp.z;
|
|
|
|
obj->move(loc);
|
|
}
|
|
|
|
// Move all the objects in the second list to region 1
|
|
for (i = 0; i < objCount2; i++) {
|
|
GameObject *obj = GameObject::objectAddress(objArray2[i]);
|
|
Location loc;
|
|
TilePoint tp;
|
|
|
|
tp = obj->getLocation();
|
|
|
|
loc._context = worldID1;
|
|
loc.u = tp.u + region1.min.u - region2.min.u;
|
|
loc.v = tp.v + region1.min.v - region2.min.v;
|
|
loc.z = tp.z;
|
|
|
|
obj->move(loc);
|
|
}
|
|
|
|
delete[] objArray1;
|
|
delete[] objArray2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Temporarily disable the updating of the tile display
|
|
// void "c" lockTiles( int lockState );
|
|
|
|
extern bool tileLockFlag;
|
|
|
|
int16 scriptLockTiles(int16 *args) {
|
|
MONOLOG(LockTiles);
|
|
if (args[0] == false) tileLockFlag = false;
|
|
else tileLockFlag = true;
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Get the current attitude of a faction
|
|
// int "c" getFactionTally( actor.faction, int column );
|
|
|
|
int16 scriptGetFactionTally(int16 *args) {
|
|
MONOLOG(GetFactionTally);
|
|
return GetFactionTally(args[0], (enum factionTallyTypes)args[1]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Adjust the attitude of a faction
|
|
// int "c" addFactionTally( actor.faction, int column, int amount );
|
|
|
|
int16 scriptAddFactionTally(int16 *args) {
|
|
MONOLOG(AddFactionTally);
|
|
return AddFactionTally(args[0], (enum factionTallyTypes)args[1], args[2]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the count of how many temp actors of this type exist.
|
|
// int "c" numTempActors( int protoNum );
|
|
|
|
extern int16 actorProtoCount;
|
|
extern int16 objectProtoCount;
|
|
|
|
int16 scriptNumTempActors(int16 *args) {
|
|
MONOLOG(NumTempActors);
|
|
|
|
assert(args[0] >= 0);
|
|
assert(args[0] < actorProtoCount);
|
|
|
|
return getTempActorCount(args[0]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return the base price of an object, given the prototype
|
|
// int16 "c" getObjectBasePrice( int protoNum );
|
|
|
|
int16 scriptGetObjectBasePrice(int16 *args) {
|
|
MONOLOG(GetBaseObjectPrice);
|
|
|
|
assert(args[0] >= 0);
|
|
assert(args[0] < objectProtoCount);
|
|
|
|
return g_vm->_objectProtos[args[0]]->price;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Win the game
|
|
// int16 "c" gotoWinMode( void );
|
|
|
|
int16 scriptGotoWinMode(int16 *args) {
|
|
MONOLOG(gotoWinMode);
|
|
int16 winType = args[0];
|
|
setWintroMode(winType);
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// open automap
|
|
// void "c" openAutoMap( void );
|
|
|
|
int16 scriptOpenAutoMap(int16 *args) {
|
|
MONOLOG(openAutoMap);
|
|
openAutoMap();
|
|
return 0;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------
|
|
// play a video
|
|
// void "C" scriptPlayVideo( string );
|
|
|
|
int16 scriptPlayVideo(int16 *args) {
|
|
MONOLOG(PlaySound);
|
|
char *sID = STRING(args[0]);
|
|
|
|
openVidBox(sID);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Returns the horizontal distance between two objects
|
|
// int "c" distanceBetween( GameObject id obj1, GameObject id obj2 );
|
|
|
|
int16 scriptDistanceBetween(int16 *args) {
|
|
MONOLOG(distanceBetween);
|
|
|
|
assert((isObject(args[0]) || isActor(args[0]))
|
|
&& (isObject(args[1]) || isActor(args[1])));
|
|
|
|
GameObject *obj1 = GameObject::objectAddress(args[0]),
|
|
*obj2 = GameObject::objectAddress(args[1]);
|
|
|
|
return (obj1->getLocation() - obj2->getLocation()).quickHDistance();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Transport the center actor and all banded brothers who have a path
|
|
// to the center actor
|
|
// void "c" transportCenterBand( GameObject id context, int u, int v, int z )
|
|
|
|
int16 scriptTransportCenterBand(int16 *args) {
|
|
MONOLOG(transportCenterBand);
|
|
|
|
assert(isWorld(args[0]));
|
|
|
|
transportCenterBand(Location(args[1], args[2], args[3], args[0 ]));
|
|
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Lock the user interface
|
|
// void "c" lockUI( int locked )
|
|
|
|
int16 scriptLockUI(int16 *args) {
|
|
MONOLOG(lockUI);
|
|
|
|
noStickyMap();
|
|
LockUI(args[0]);
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Return number of pending speeches in speech queue
|
|
// int "c" pendingSpeeches( void );
|
|
|
|
int16 scriptPendingSpeeches(int16 *args) {
|
|
MONOLOG(PendingSpeeches);
|
|
|
|
return speechList.activeCount();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Redraw the main tile display
|
|
// void "c" drawFrame( void );
|
|
|
|
int16 scriptDrawFrame(int16 *) {
|
|
MONOLOG(DrawFrame);
|
|
|
|
drawMainDisplay();
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Fade down the palette - duh
|
|
// void "c" fadeDown( void );
|
|
|
|
int16 scriptFadeDown(int16 *) {
|
|
MONOLOG(FadeDown);
|
|
|
|
fadeDown();
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Fade up the palette
|
|
// void "c" fadeUp( void );
|
|
|
|
int16 scriptFadeUp(int16 *) {
|
|
MONOLOG(FadeUp);
|
|
|
|
fadeUp();
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Enable or disable script task switching. Returns previous synchronous
|
|
// setting.
|
|
// int "c" setSynchronous( int val );
|
|
|
|
int16 scriptSetSynchronous(int16 *args) {
|
|
MONOLOG(SetSynchronous);
|
|
|
|
int16 oldVal = (thisThread->_flags & Thread::synchronous) != 0;
|
|
|
|
if (args[0])
|
|
thisThread->_flags |= Thread::synchronous;
|
|
else
|
|
thisThread->_flags &= ~Thread::synchronous;
|
|
|
|
return oldVal;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Multiplication with overflow protection
|
|
// int "c" bigMul( int m1, int m2, int d );
|
|
|
|
int16 scriptBigMul(int16 *args) {
|
|
MONOLOG(BigMul);
|
|
|
|
long result = (long)args[0] * (long)args[1];
|
|
|
|
if (args[2] == 0) result = 0;
|
|
else result /= args[2];
|
|
|
|
result = clamp((short)minint16, (long)result, (short)maxint16);
|
|
|
|
return (int16)result;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Global script call table
|
|
|
|
C_Call *globalCFuncList[] = {
|
|
scriptWriteMessage,
|
|
scriptStatus,
|
|
scriptErrorDialog,
|
|
scriptMessageDialog,
|
|
scriptChoiceDialog,
|
|
scriptPlacard,
|
|
scriptLockDisplay,
|
|
scriptSetGameMode,
|
|
|
|
scriptWait,
|
|
scriptWaitFrames,
|
|
|
|
scriptPlaySong,
|
|
scriptPlayFX,
|
|
|
|
scriptObject2Actor,
|
|
|
|
scriptGenericCast,
|
|
scriptGenericCast,
|
|
scriptGenericCast,
|
|
scriptGenericCast,
|
|
scriptGenericCast,
|
|
scriptGenericCast,
|
|
|
|
scriptWriteLog,
|
|
scriptWriteObject,
|
|
scriptMakeObject,
|
|
scriptDeleteObject,
|
|
scriptMakeActor,
|
|
scriptGetCenterActor,
|
|
|
|
scriptPlaySound,
|
|
scriptPlayVoice,
|
|
scriptPlayMusic,
|
|
scriptPlayLoop,
|
|
scriptResID,
|
|
|
|
scriptGetHour,
|
|
scriptGetFrameInHour,
|
|
scriptGetRandomBetween,
|
|
scriptIsContaining,
|
|
scriptPlayLongSound,
|
|
scriptWorldNum2Object,
|
|
|
|
scriptAppendBookText,
|
|
scriptAppendBookTextF,
|
|
scriptAppendBookText, // scriptAppendScrollText,
|
|
scriptAppendBookTextF, // scriptAppendScrollText,
|
|
|
|
scriptCastSpellAtObject,
|
|
scriptCastSpellAtActor,
|
|
scriptCastSpellAtWorld,
|
|
scriptCastSpellAtTAG,
|
|
scriptCastSpellAtTile,
|
|
|
|
scriptAssertEvent,
|
|
|
|
scriptSelectNearbySite,
|
|
|
|
scriptPickRandomLivingActor,
|
|
scriptNewMission,
|
|
scriptFindMission,
|
|
|
|
scriptSetTileCycleSpeed,
|
|
scriptSetTileCycleState,
|
|
|
|
scriptSearchRegion,
|
|
scriptSwapRegions,
|
|
scriptLockTiles,
|
|
|
|
scriptGetFactionTally,
|
|
scriptAddFactionTally,
|
|
|
|
scriptNumTempActors,
|
|
scriptGetObjectBasePrice,
|
|
|
|
scriptGotoWinMode,
|
|
scriptOpenAutoMap,
|
|
|
|
scriptCanCast,
|
|
|
|
scriptPlayVideo,
|
|
|
|
scriptDistanceBetween,
|
|
|
|
scriptTransportCenterBand,
|
|
scriptLockUI,
|
|
|
|
scriptPendingSpeeches,
|
|
|
|
scriptDrawFrame,
|
|
scriptFadeDown,
|
|
scriptFadeUp,
|
|
|
|
scriptSetSynchronous,
|
|
|
|
scriptPlaySoundAt,
|
|
scriptPlaySoundFrom,
|
|
scriptPlayLoopAt,
|
|
|
|
scriptBigMul,
|
|
};
|
|
|
|
CallTable globalCFuncs = { globalCFuncList, ARRAYSIZE(globalCFuncList), 0 };
|
|
|
|
} // end of namespace Saga2
|