/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * aint32 with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * Based on the original sources * Faery Tale II -- The Halls of the Dead * (c) 1993-1996 The Wyrmkeep Entertainment Co. */ #define FORBIDDEN_SYMBOL_ALLOW_ALL // FIXME: Remove #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(void); #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::temporary)) { 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 == NULL) { uint16 spFlags = 0; if (flags & speakNoAnimate) spFlags |= Speech::spNoAnimate; if (flags & speakLock) spFlags |= Speech::spLock; sp = speechList.newTask(obj->thisID(), spFlags); if (sp == NULL) 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, 0); 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 == NULL) 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, objectOpen ); return 0; } int16 scriptActorSetLocked( int16 *args ) { (((ObjectData *)thisThread->thisObject)->obj)->setFlags( args[0] ? 0xffff : 0, objectLocked ); return 0; } */ int16 scriptActorSetImportant(int16 *args) { OBJLOG(SetImportant); (((ObjectData *)thisThread->thisObject)->obj)->setFlags( args[0] ? (int16) 0xffff : (int16) 0, objectImportant); return 0; } int16 scriptActorSetScavengable(int16 *args) { OBJLOG(SetScavengable); (((ObjectData *)thisThread->thisObject)->obj)->setFlags( args[0] ? (int16) 0xffff : (int16) 0, objectScavengable); 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() != NULL) 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 & moveWait) { thisThread->waitForEvent(Thread::waitOther, 0); MotionTask::turn(getThreadID(thisThread), *a, args[0] & 7); } else { MotionTask::turn(*a, args[0] & 7); return motionStarted; } } 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 & moveWait) { thisThread->waitForEvent(Thread::waitOther, 0); MotionTask::turn(getThreadID(thisThread), *a, dir); } else { MotionTask::turn(*a, dir); return motionStarted; } } 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 & moveWait) { thisThread->waitForEvent(Thread::waitOther, 0); MotionTask::walkToDirect( getThreadID(thisThread), *a, dest, flags & moveRun); } else { MotionTask::walkToDirect(*a, dest, flags & moveRun); return motionStarted; } } 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() != NULL) delete a->getAssignment(); if (new PatrolRouteAssignment(a, (uint16)args[0] * CalenderTime::kFramesPerHour, args[1], (uint8)args[2], thisThread->argCount >= 4 ? args[3] : -1) != NULL) return true; } return false; } //----------------------------------------------------------------------- // Assign a patrol route and specify the begining 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() != NULL) delete a->getAssignment(); if (new PatrolRouteAssignment(a, (uint16)args[0] * CalenderTime::kFramesPerHour, args[1], (uint8)args[2], args[3], args[4]) != NULL) 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() != NULL) delete a->getAssignment(); if (new HuntToBeNearLocationAssignment(a, args[0], targetLoc, args[4]) != NULL) 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() != NULL) delete a->getAssignment(); if (new HuntToBeNearActorAssignment(a, args[0], targetActor, args[2], args[3]) != NULL) 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() != NULL) delete a->getAssignment(); if (new HuntToKillAssignment(a, args[0], targetActor, args[2]) != NULL) 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() != NULL) 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] * CalenderTime::kFramesPerHour, tetherReg) != NULL) 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() != NULL) delete a->getAssignment(); if (new AttendAssignment(a, (g_vm->_calender->frameInDay() + (uint16)args[0]) % CalenderTime::kFramesPerDay, GameObject::objectAddress(args[1])) != NULL) 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() != NULL) 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 != NULL ? 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 != NULL ? 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 != NULL); 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 = NULL; 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, 0); // 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, 0); } 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] |= actorPermanent; 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; } //----------------------------------------------------------------------- // Write a message to a log file // void "C" status( string caption, ... ); /* void writeLog( char *str ) { static FILE *logFile = NULL; if (logFile == NULL) { logFile = fopen( "logfile.txt", "a+t" ); } if (logFile) fputs( str, logFile ); fclose(logFile); } */ void writeLog(char *str) { FILE *logFile = NULL; #ifdef __WATCOMC__ time_t time_of_day; auto char buf[26]; char strbuf[256]; logFile = fopen("logfile.txt", "a+t"); if (logFile) { time_of_day = time(NULL); _ctime(&time_of_day, buf); buf[strlen(buf) - 1] = 0; sprintf(strbuf, "%s: %s", buf, str); fputs(strbuf, logFile); fclose(logFile); } #else logFile = fopen("logfile.txt", "a+t"); if (logFile) { fputs(str, logFile); fclose(logFile); } #endif } void writeObject(char *str) { FILE *logFile = NULL; logFile = fopen("objfile.txt", "a+t"); if (logFile) { fputs(str, logFile); fclose(logFile); } } 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]) : NULL, NULL, NULL); // 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]) : NULL, args[3] ? STRING(args[3]) : NULL, args[4] ? STRING(args[4]) : NULL); // 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, 0); thisThread->setExtended(); return 0; } int16 scriptWaitFrames(int16 *args) { MONOLOG(WaitFrames); thisThread->waitFrameAlarm.set(args[0]); thisThread->waitForEvent(Thread::waitFrameDelay, 0); 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 == NULL) { 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 == NULL) { 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 != NULL); 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->_calender->_hour; } //----------------------------------------------------------------------- // int "c" getFrameInHour( void ); int16 scriptGetFrameInHour(int16 *) { MONOLOG(GetFrameInHour); return g_vm->_calender->_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]) : NULL; 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 != NULL); 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(NULL); searchObj != Nothing; searchObj = iter.next(NULL)) { // 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(NULL), count = 0; searchObj != Nothing; searchObj = iter.next(NULL)) { 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(NULL); searchObj != Nothing; searchObj = iter.next(NULL)) { *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 != NULL); assert(worldPtr2 != NULL); 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