Javascript improvements to prepare for AI porting. The two types of repeating timers now unified
and functionality of setObjectTimer() implemented as an extra parameter to setGlobalTimer(). Also added a new one-shot timer called queue().master
parent
7426d0c2bf
commit
f88f363ad6
|
@ -82,7 +82,7 @@ function eventGameInit()
|
|||
attackGroup = newGroup(); // allocate a new group
|
||||
groupAddArea(attackGroup, 0, 0, (mapWidth * 128), (mapHeight * 128));
|
||||
scavtick();
|
||||
setGlobalTimer("scavtick", 15000); // start a constant timer function
|
||||
setTimer("scavtick", 15000); // start a constant timer function
|
||||
}
|
||||
|
||||
// deal with a droid being built by us
|
||||
|
|
|
@ -4,10 +4,6 @@
|
|||
// contains the rules for starting and ending a game.
|
||||
// as well as warning messages.
|
||||
//
|
||||
|
||||
// TODO set tech level as a global, and set that up here as well
|
||||
// TODO use gameTime instead of t second ticker...
|
||||
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
|
||||
var lastHitTime = 0;
|
||||
|
@ -122,7 +118,7 @@ function eventGameInit()
|
|||
}
|
||||
}
|
||||
}
|
||||
setGlobalTimer("checkEndConditions", 100);
|
||||
setTimer("checkEndConditions", 100);
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "intdisplay.h"
|
||||
#include "mission.h"
|
||||
#include "projectile.h"
|
||||
#include "qtscript.h"
|
||||
#include "random.h"
|
||||
#include "research.h"
|
||||
#include "scriptcb.h"
|
||||
|
@ -998,6 +999,7 @@ void actionUpdateDroid(DROID *psDroid)
|
|||
{
|
||||
//the script can call startMission for this callback for offworld missions
|
||||
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL);
|
||||
triggerEvent(TRIGGER_START_LEVEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#include "mission.h"
|
||||
#include "modding.h"
|
||||
#include "multiplay.h"
|
||||
#include "qtscript.h"
|
||||
#include "research.h"
|
||||
#include "scripttabs.h"
|
||||
#include "seqdisp.h"
|
||||
|
@ -821,6 +822,7 @@ static void startGameLoop(void)
|
|||
if (game.type == SKIRMISH)
|
||||
{
|
||||
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL);
|
||||
triggerEvent(TRIGGER_START_LEVEL);
|
||||
}
|
||||
screen_disableMapPreview();
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "intorder.h"
|
||||
#include "orderdef.h"
|
||||
#include "transporter.h"
|
||||
#include "qtscript.h"
|
||||
#include "group.h"
|
||||
#include "cmddroid.h"
|
||||
#include "lib/script/script.h"
|
||||
|
@ -332,6 +333,7 @@ void orderUpdateDroid(DROID *psDroid)
|
|||
{
|
||||
// the script can call startMission for this callback for offworld missions
|
||||
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL);
|
||||
triggerEvent(TRIGGER_START_LEVEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -420,6 +422,7 @@ void orderUpdateDroid(DROID *psDroid)
|
|||
{
|
||||
//the script can call startMission for this callback for offworld missions
|
||||
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL);
|
||||
triggerEvent(TRIGGER_START_LEVEL);
|
||||
|
||||
/* clear order */
|
||||
psDroid->order = DORDER_NONE;
|
||||
|
@ -1156,6 +1159,7 @@ void orderUpdateDroid(DROID *psDroid)
|
|||
{
|
||||
// the script can call startMission for this callback for offworld missions
|
||||
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL);
|
||||
triggerEvent(TRIGGER_START_LEVEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,16 +41,23 @@
|
|||
|
||||
#include "qtscriptfuncs.h"
|
||||
|
||||
enum timerType
|
||||
{
|
||||
TIMER_REPEAT, TIMER_ONESHOT_READY, TIMER_ONESHOT_DONE
|
||||
};
|
||||
|
||||
struct timerNode
|
||||
{
|
||||
QString function;
|
||||
QScriptEngine *engine;
|
||||
QString baseobj;
|
||||
int baseobj;
|
||||
int frameTime;
|
||||
int ms;
|
||||
int player;
|
||||
timerType type;
|
||||
timerNode() {}
|
||||
timerNode(QScriptEngine *caller, QString val, int plr, int frame) : function(val) { player = plr; ms = frame; frameTime = frame + gameTime; engine = caller; }
|
||||
timerNode(QScriptEngine *caller, QString val, int plr, int frame)
|
||||
: function(val), engine(caller), baseobj(-1), frameTime(frame + gameTime), ms(frame), player(plr), type(TIMER_REPEAT) {}
|
||||
bool operator== (const timerNode &t) { return function == t.function && player == t.player; }
|
||||
// implement operator less TODO
|
||||
};
|
||||
|
@ -112,28 +119,41 @@ static QScriptValue js_removeTimer(QScriptContext *context, QScriptEngine *engin
|
|||
return QScriptValue();
|
||||
}
|
||||
|
||||
/// Special scripting function that registers a non-specific timer event. Note: Functions must be passed
|
||||
/// quoted, otherwise they will be inlined!
|
||||
static QScriptValue js_setGlobalTimer(QScriptContext *context, QScriptEngine *engine)
|
||||
/// Special scripting function that registers a timer event. Note: Functions must be passed
|
||||
/// quoted, otherwise they will be inlined! If a third parameter is passed, this must be an
|
||||
/// object, which is then passed to the timer. If the object is dead, the timer stops.
|
||||
static QScriptValue js_setTimer(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
QString funcName = context->argument(0).toString();
|
||||
QScriptValue ms = context->argument(1);
|
||||
int player = engine->globalObject().property("me").toInt32();
|
||||
timerNode node(engine, funcName, player, ms.toInt32() + gameTime);
|
||||
timerNode node(engine, funcName, player, ms.toInt32());
|
||||
if (context->argumentCount() == 3)
|
||||
{
|
||||
QScriptValue obj = context->argument(2);
|
||||
node.baseobj = obj.property("id").toInt32();
|
||||
}
|
||||
node.type = TIMER_REPEAT;
|
||||
timers.push_back(node);
|
||||
return QScriptValue();
|
||||
}
|
||||
|
||||
/// Special scripting function that registers a object-specific timer event. Note: Functions must be passed
|
||||
/// quoted, otherwise they will be inlined!
|
||||
static QScriptValue js_setObjectTimer(QScriptContext *context, QScriptEngine *engine)
|
||||
/// Special scripting function that queues up a function to call once at a later time frame.
|
||||
/// Note: Functions must be passed quoted, otherwise they will be inlined! If a third
|
||||
/// parameter is passed, this must be an object, which is then passed to the timer. If
|
||||
/// the object is dead, the timer stops.
|
||||
static QScriptValue js_queue(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
QString funcName = context->argument(0).toString();
|
||||
QScriptValue ms = context->argument(1);
|
||||
QScriptValue obj = context->argument(2);
|
||||
int player = engine->globalObject().property("me").toInt32();
|
||||
timerNode node(engine, funcName, player, ms.toInt32());
|
||||
node.baseobj = obj.toString();
|
||||
if (context->argumentCount() == 3)
|
||||
{
|
||||
QScriptValue obj = context->argument(2);
|
||||
node.baseobj = obj.property("id").toInt32();
|
||||
}
|
||||
node.type = TIMER_ONESHOT_READY;
|
||||
timers.push_back(node);
|
||||
return QScriptValue();
|
||||
}
|
||||
|
@ -195,10 +215,24 @@ bool updateScripts()
|
|||
|
||||
engine->globalObject().setProperty("gameTime", gameTime, QScriptValue::ReadOnly | QScriptValue::Undeletable);
|
||||
}
|
||||
// Weed out dead timers
|
||||
for (int i = 0; i < timers.count(); )
|
||||
{
|
||||
const timerNode node = timers.at(i);
|
||||
if (node.type == TIMER_ONESHOT_DONE || (node.baseobj > NOT_CURRENT_LIST && !IdToPointer(node.baseobj, node.player)))
|
||||
{
|
||||
timers.removeAt(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
// Check for timers, and run them if applicable.
|
||||
// TODO - load balancing
|
||||
QList<timerNode> runlist; // make a new list here, since we might trample all over the timer list during execution
|
||||
QList<timerNode>::iterator iter;
|
||||
// Weed out dead timers
|
||||
for (iter = timers.begin(); iter != timers.end(); iter++)
|
||||
{
|
||||
if (iter->frameTime <= gameTime)
|
||||
|
@ -206,10 +240,20 @@ bool updateScripts()
|
|||
iter->frameTime = iter->ms + gameTime; // update for next invokation
|
||||
runlist.append(*iter);
|
||||
}
|
||||
else if (iter->type == TIMER_ONESHOT_READY)
|
||||
{
|
||||
iter->type = TIMER_ONESHOT_DONE;
|
||||
runlist.append(*iter);
|
||||
}
|
||||
}
|
||||
for (iter = runlist.begin(); iter != runlist.end(); iter++)
|
||||
{
|
||||
callFunction(iter->engine, iter->function, QScriptValueList());
|
||||
QScriptValueList args;
|
||||
if (iter->baseobj > NOT_CURRENT_LIST)
|
||||
{
|
||||
args += convObj(IdToPointer(iter->baseobj, iter->player), iter->engine);
|
||||
}
|
||||
callFunction(iter->engine, iter->function, args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -241,8 +285,8 @@ bool loadPlayerScript(QString path, int player, int difficulty)
|
|||
ASSERT_OR_RETURN(false, !engine->hasUncaughtException(), "Uncaught exception at line %d, file %s: %s",
|
||||
engine->uncaughtExceptionLineNumber(), path.toAscii().constData(), result.toString().toAscii().constData());
|
||||
// Special functions
|
||||
engine->globalObject().setProperty("setGlobalTimer", engine->newFunction(js_setGlobalTimer));
|
||||
engine->globalObject().setProperty("setObjectTimer", engine->newFunction(js_setObjectTimer));
|
||||
engine->globalObject().setProperty("setTimer", engine->newFunction(js_setTimer));
|
||||
engine->globalObject().setProperty("queue", engine->newFunction(js_queue));
|
||||
engine->globalObject().setProperty("removeTimer", engine->newFunction(js_removeTimer));
|
||||
engine->globalObject().setProperty("include", engine->newFunction(js_include));
|
||||
|
||||
|
@ -300,11 +344,12 @@ bool saveScriptStates(const char *filename)
|
|||
ini.beginGroup(QString("triggers_") + QString::number(i));
|
||||
ini.setValue("player", node.player);
|
||||
ini.setValue("function", node.function.toUtf8().constData());
|
||||
if (!node.baseobj.isEmpty())
|
||||
if (!node.baseobj >= NOT_CURRENT_LIST)
|
||||
{
|
||||
ini.setValue("object", node.baseobj.toUtf8().constData());
|
||||
ini.setValue("object", QVariant(node.baseobj));
|
||||
}
|
||||
ini.setValue("frame", node.frameTime);
|
||||
ini.setValue("type", (int)node.type);
|
||||
ini.setValue("ms", node.ms);
|
||||
ini.endGroup();
|
||||
}
|
||||
|
@ -343,7 +388,8 @@ bool loadScriptStates(const char *filename)
|
|||
debug(LOG_SAVE, "Registering trigger %d for player %d", i, node.player);
|
||||
node.engine = findEngineForPlayer(node.player);
|
||||
node.function = ini.value("function").toString();
|
||||
node.baseobj = ini.value("baseobj", QString()).toString();
|
||||
node.baseobj = ini.value("baseobj", -1).toInt();
|
||||
node.type = (timerType)ini.value("type", TIMER_REPEAT).toInt();
|
||||
timers.push_back(node);
|
||||
ini.endGroup();
|
||||
}
|
||||
|
@ -379,6 +425,9 @@ bool triggerEvent(SCRIPT_TRIGGER_TYPE trigger)
|
|||
case TRIGGER_GAME_INIT:
|
||||
callFunction(engine, "eventGameInit", QScriptValueList());
|
||||
break;
|
||||
case TRIGGER_START_LEVEL:
|
||||
callFunction(engine, "eventStartLevel", QScriptValueList());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
|
||||
enum SCRIPT_TRIGGER_TYPE
|
||||
{
|
||||
TRIGGER_GAME_INIT
|
||||
TRIGGER_GAME_INIT,
|
||||
TRIGGER_START_LEVEL
|
||||
};
|
||||
|
||||
// ----------------------------------------------
|
||||
|
|
|
@ -59,6 +59,7 @@ QScriptValue convStructure(STRUCTURE *psStruct, QScriptEngine *engine)
|
|||
value.setProperty("y", psStruct->pos.y, QScriptValue::ReadOnly);
|
||||
value.setProperty("z", psStruct->pos.z, QScriptValue::ReadOnly);
|
||||
value.setProperty("player", psStruct->player, QScriptValue::ReadOnly);
|
||||
value.setProperty("selected", psStruct->selected, QScriptValue::ReadOnly);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -71,6 +72,7 @@ QScriptValue convDroid(DROID *psDroid, QScriptEngine *engine)
|
|||
value.setProperty("y", psDroid->pos.y, QScriptValue::ReadOnly);
|
||||
value.setProperty("z", psDroid->pos.z, QScriptValue::ReadOnly);
|
||||
value.setProperty("player", psDroid->player, QScriptValue::ReadOnly);
|
||||
value.setProperty("selected", psDroid->selected, QScriptValue::ReadOnly);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -83,6 +85,7 @@ QScriptValue convObj(BASE_OBJECT *psObj, QScriptEngine *engine)
|
|||
value.setProperty("y", psObj->pos.y, QScriptValue::ReadOnly);
|
||||
value.setProperty("z", psObj->pos.z, QScriptValue::ReadOnly);
|
||||
value.setProperty("player", psObj->player, QScriptValue::ReadOnly);
|
||||
value.setProperty("selected", psObj->selected, QScriptValue::ReadOnly);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -654,6 +657,12 @@ static QScriptValue js_translate(QScriptContext *context, QScriptEngine *engine)
|
|||
return QScriptValue(gettext(context->argument(0).toString().toUtf8().constData()));
|
||||
}
|
||||
|
||||
static QScriptValue js_playerPower(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
int player = context->argument(0).toInt32();
|
||||
return QScriptValue(getPower(player));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// Register functions with scripting system
|
||||
|
||||
|
@ -677,6 +686,7 @@ bool registerFunctions(QScriptEngine *engine)
|
|||
engine->globalObject().setProperty("groupAddDroid", engine->newFunction(js_groupAddDroid));
|
||||
engine->globalObject().setProperty("groupSize", engine->newFunction(js_groupSize));
|
||||
engine->globalObject().setProperty("orderDroidLoc", engine->newFunction(js_orderDroidLoc));
|
||||
engine->globalObject().setProperty("playerPower", engine->newFunction(js_playerPower));
|
||||
|
||||
// Functions that operate on the current player only
|
||||
engine->globalObject().setProperty("centreView", engine->newFunction(js_centreView));
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "mission.h"
|
||||
#include "objects.h"
|
||||
#include "display.h"
|
||||
#include "qtscript.h"
|
||||
#include "lib/script/script.h"
|
||||
#include "scripttabs.h"
|
||||
#include "order.h"
|
||||
|
@ -1638,6 +1639,7 @@ bool updateTransporter(DROID *psTransporter)
|
|||
|
||||
//the script can call startMission for this callback for offworld missions
|
||||
eventFireCallbackTrigger((TRIGGER_TYPE)CALL_START_NEXT_LEVEL);
|
||||
triggerEvent(TRIGGER_START_LEVEL);
|
||||
|
||||
// clear order
|
||||
psTransporter->order = DORDER_NONE;
|
||||
|
|
|
@ -111,6 +111,7 @@ QScriptValue convStructure(QScriptEngine *engine)
|
|||
value.setProperty("y", 11, QScriptValue::ReadOnly);
|
||||
value.setProperty("z", 0, QScriptValue::ReadOnly);
|
||||
value.setProperty("player", 1, QScriptValue::ReadOnly);
|
||||
value.setProperty("selected", 0, QScriptValue::ReadOnly);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -122,6 +123,7 @@ QScriptValue convDroid(QScriptEngine *engine)
|
|||
value.setProperty("y", 11, QScriptValue::ReadOnly);
|
||||
value.setProperty("z", 0, QScriptValue::ReadOnly);
|
||||
value.setProperty("player", 1, QScriptValue::ReadOnly);
|
||||
value.setProperty("selected", 0, QScriptValue::ReadOnly);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -133,6 +135,7 @@ QScriptValue convObj(QScriptEngine *engine)
|
|||
value.setProperty("y", 11, QScriptValue::ReadOnly);
|
||||
value.setProperty("z", 0, QScriptValue::ReadOnly);
|
||||
value.setProperty("player", 1, QScriptValue::ReadOnly);
|
||||
value.setProperty("selected", 0, QScriptValue::ReadOnly);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -442,13 +445,15 @@ static QScriptValue js_removeTimer(QScriptContext *context, QScriptEngine *engin
|
|||
|
||||
/// Special scripting function that registers a non-specific timer event. Note: Functions must be passed
|
||||
/// quoted, otherwise they will be inlined!
|
||||
static QScriptValue js_setGlobalTimer(QScriptContext *context, QScriptEngine *engine)
|
||||
static QScriptValue js_setTimer(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
ARG_COUNT_EXACT(2);
|
||||
ARG_COUNT_VAR(2, 3);
|
||||
ARG_STRING(0);
|
||||
ARG_NUMBER(1);
|
||||
if (context->argumentCount() == 3) ARG_OBJ(2);
|
||||
QString funcName = context->argument(0).toString();
|
||||
// TODO - check that a function by that name exists
|
||||
// TODO - object argument
|
||||
int player = engine->globalObject().property("me").toInt32();
|
||||
timerNode node(engine, funcName, player);
|
||||
timers.push_back(node);
|
||||
|
@ -457,14 +462,15 @@ static QScriptValue js_setGlobalTimer(QScriptContext *context, QScriptEngine *en
|
|||
|
||||
/// Special scripting function that registers a object-specific timer event. Note: Functions must be passed
|
||||
/// quoted, otherwise they will be inlined!
|
||||
static QScriptValue js_setObjectTimer(QScriptContext *context, QScriptEngine *engine)
|
||||
static QScriptValue js_queue(QScriptContext *context, QScriptEngine *engine)
|
||||
{
|
||||
ARG_COUNT_EXACT(2);
|
||||
ARG_COUNT_VAR(2, 3);
|
||||
ARG_STRING(0);
|
||||
ARG_NUMBER(1);
|
||||
ARG_OBJ(2);
|
||||
if (context->argumentCount() == 3) ARG_OBJ(2);
|
||||
QString funcName = context->argument(0).toString();
|
||||
// TODO - check that a function by that name exists
|
||||
// TODO - object argument
|
||||
int player = engine->globalObject().property("me").toInt32();
|
||||
timerNode node(engine, funcName, player);
|
||||
timers.push_back(node);
|
||||
|
@ -536,8 +542,8 @@ bool testPlayerScript(QString path, int player, int difficulty)
|
|||
return false;
|
||||
}
|
||||
// Special functions
|
||||
engine->globalObject().setProperty("setGlobalTimer", engine->newFunction(js_setGlobalTimer));
|
||||
engine->globalObject().setProperty("setObjectTimer", engine->newFunction(js_setObjectTimer));
|
||||
engine->globalObject().setProperty("setTimer", engine->newFunction(js_setTimer));
|
||||
engine->globalObject().setProperty("queue", engine->newFunction(js_queue));
|
||||
engine->globalObject().setProperty("removeTimer", engine->newFunction(js_removeTimer));
|
||||
engine->globalObject().setProperty("include", engine->newFunction(js_include));
|
||||
|
||||
|
|
Loading…
Reference in New Issue