Skip to content

Commit 19d3739

Browse files
committedMay 25, 2017
qtscript: Add a way for a script library to register an event namespace
New function: namespace(prefix) The namespace function registers a new namespace for events, that the script environment will call in addition to the non-prefixed event names. This allows script libraries to exist that can handle events, without overwriting or being overwritten by scripts using that library. All existing campaign event handlers except area handlers have been changed to use the new namespace feature. New buttons in debug menu to show all labels, all active labels, clear labels, and show all gateways.
1 parent 50babf0 commit 19d3739

File tree

6 files changed

+162
-61
lines changed

6 files changed

+162
-61
lines changed
 

‎data/base/script/campaign/libcampaign.js

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@
7070
HTML by HeVeA, which fails to support most of the complicated stuff.
7171
*/
7272

73+
////////////////////////////////////////////////////////////////////////////////
74+
// Library initialization.
75+
////////////////////////////////////////////////////////////////////////////////
76+
77+
// Registers a private event namespace for this library, to avoid collisions with
78+
// any event handling in code using this library. Make sure no other library uses
79+
// the same namespace, or strange things will happen. After this, we can name our
80+
// event handlers with the registered prefix, and they will still get called.
81+
namespace("cam_");
82+
7383
////////////////////////////////////////////////////////////////////////////////
7484
// Misc useful stuff.
7585
////////////////////////////////////////////////////////////////////////////////
@@ -2398,23 +2408,23 @@ var __camLastHitTime = 0;
23982408

23992409
const __CAM_EVENT_ATTACKED_INTENSITY = 5000;
24002410

2401-
__camPreHookEvent("eventPickup", function(feature, droid)
2411+
function cam_eventPickup(feature, droid)
24022412
{
24032413
if (feature.stattype === ARTIFACT)
24042414
{
24052415
__camPickupArtifact(feature);
24062416
}
2407-
});
2417+
}
24082418

2409-
__camPreHookEvent("eventGroupLoss", function(obj, group, newsize)
2419+
function cam_eventGroupLoss(obj, group, newsize)
24102420
{
24112421
if (newsize === 0)
24122422
__camCheckBaseEliminated(group);
24132423
if (camDef(__camGroupInfo[group]))
24142424
profile("__camCheckGroupMorale", group);
2415-
});
2425+
}
24162426

2417-
__camPreHookEvent("eventCheatMode", function(entered)
2427+
function cam_eventCheatMode(entered)
24182428
{
24192429
if (entered)
24202430
{
@@ -2427,9 +2437,9 @@ __camPreHookEvent("eventCheatMode", function(entered)
24272437
__camCheatMode = false;
24282438
}
24292439
__camUpdateMarkedTiles();
2430-
});
2440+
}
24312441

2432-
__camPreHookEvent("eventChat", function(from, to, message)
2442+
function cam_eventChat(from, to, message)
24332443
{
24342444
if (!__camCheatMode)
24352445
return;
@@ -2448,9 +2458,9 @@ __camPreHookEvent("eventChat", function(from, to, message)
24482458
__camNextLevel = message.substring(7).toUpperCase().replace(/-/g, "_");
24492459
__camLetMeWin();
24502460
}
2451-
});
2461+
}
24522462

2453-
__camPreHookEvent("eventStartLevel", function()
2463+
function cam_eventStartLevel()
24542464
{
24552465
isReceivingAllEvents = true;
24562466
// Variables initialized here are the ones that should not be
@@ -2482,9 +2492,9 @@ __camPreHookEvent("eventStartLevel", function()
24822492
setTimer("__camTick", 1000); // campaign pollers
24832493
setTimer("__camTruckTick", 150100); // some slower campaign pollers
24842494
queue("__camTacticsTick", 100); // would re-queue itself
2485-
});
2495+
}
24862496

2487-
__camPreHookEvent("eventDroidBuilt", function(droid, structure)
2497+
function cam_eventDroidBuilt(droid, structure)
24882498
{
24892499
if (!camDef(structure)) // "clone wars" cheat
24902500
return;
@@ -2496,26 +2506,26 @@ __camPreHookEvent("eventDroidBuilt", function(droid, structure)
24962506
return;
24972507
__camContinueProduction(structure);
24982508
__camAddDroidToFactoryGroup(droid, structure);
2499-
});
2509+
}
25002510

2501-
__camPreHookEvent("eventDestroyed", function(obj)
2511+
function cam_eventDestroyed(obj)
25022512
{
25032513
__camCheckPlaceArtifact(obj);
25042514
if (obj.type === DROID && obj.droidType === DROID_CONSTRUCT)
25052515
__camCheckDeadTruck(obj);
2506-
});
2516+
}
25072517

2508-
__camPreHookEvent("eventObjectSeen", function(viewer, seen)
2518+
function cam_eventObjectSeen(viewer, seen)
25092519
{
25102520
__camCheckBaseSeen(seen);
2511-
});
2521+
}
25122522

2513-
__camPreHookEvent("eventGroupSeen", function(viewer, group)
2523+
function cam_eventGroupSeen(viewer, group)
25142524
{
25152525
__camCheckBaseSeen(group);
2516-
});
2526+
}
25172527

2518-
__camPreHookEvent("eventTransporterExit", function(transport)
2528+
function cam_eventTransporterExit(transport)
25192529
{
25202530
if (transport.player !== CAM_HUMAN_PLAYER ||
25212531
(__camWinLossCallback === "__camVictoryStandard" &&
@@ -2531,28 +2541,28 @@ __camPreHookEvent("eventTransporterExit", function(transport)
25312541
__camGameWon();
25322542
return;
25332543
}
2534-
});
2544+
}
25352545

2536-
__camPreHookEvent("eventTransporterLanded", function(transport)
2546+
function cam_eventTransporterLanded(transport)
25372547
{
25382548
if (transport.player !== CAM_HUMAN_PLAYER)
25392549
__camLandTransporter(transport.player, camMakePos(transport));
2540-
});
2550+
}
25412551

2542-
__camPreHookEvent("eventMissionTimeout", function()
2552+
function cam_eventMissionTimeout()
25432553
{
25442554
if (__camDefeatOnTimeout)
25452555
{
25462556
camTrace("0 minutes remaining.");
25472557
__camGameLost();
25482558
}
2549-
});
2559+
}
25502560

2551-
__camPreHookEvent("eventAttacked", function(victim, attacker)
2561+
function cam_eventAttacked(victim, attacker)
25522562
{
25532563
if (camDef(victim) && victim &&
25542564
victim.type === DROID && camDef(__camGroupInfo[victim.group]))
25552565
{
25562566
__camGroupInfo[victim.group].lastHit = gameTime;
25572567
}
2558-
});
2568+
}

‎src/qtscript.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ typedef struct monitor_bin
134134
} MONITOR_BIN;
135135
typedef QHash<QString, MONITOR_BIN> MONITOR;
136136
static QHash<QScriptEngine *, MONITOR *> monitors;
137+
static QHash<QScriptEngine *, QStringList> eventNamespaces; // separate event namespaces for libraries
137138

138139
static MODELMAP models;
139140
static QStandardItemModel *triggerModel;
@@ -149,9 +150,21 @@ void doNotSaveGlobal(const QString &global)
149150
}
150151

151152
// Call a function by name
152-
static QScriptValue callFunction(QScriptEngine *engine, const QString &function, const QScriptValueList &args, bool required = false)
153+
static QScriptValue callFunction(QScriptEngine *engine, const QString &function, const QScriptValueList &args, bool event = true)
153154
{
154-
code_part level = required ? LOG_ERROR : LOG_SCRIPT;
155+
if (event)
156+
{
157+
// recurse into variants, if any
158+
for (const QString &s : eventNamespaces[engine])
159+
{
160+
const QScriptValue &value = engine->globalObject().property(s + function);
161+
if (value.isValid() && value.isFunction())
162+
{
163+
callFunction(engine, s + function, args, event);
164+
}
165+
}
166+
}
167+
code_part level = event ? LOG_SCRIPT : LOG_ERROR;
155168
QScriptValue value = engine->globalObject().property(function);
156169
if (!value.isValid() || !value.isFunction())
157170
{
@@ -351,6 +364,18 @@ void scriptRemoveObject(BASE_OBJECT *psObj)
351364
groupRemoveObject(psObj);
352365
}
353366

367+
//-- \subsection{namespace(prefix)}
368+
//-- Registers a new event namespace. All events can now have this prefix. This is useful for
369+
//-- code libraries, to implement event that do not conflict with events in main code. This
370+
//-- function should be called from global; do not (for hopefully obvious reasons) put it
371+
//-- inside an event.
372+
static QScriptValue js_namespace(QScriptContext *context, QScriptEngine *engine)
373+
{
374+
QString prefix(context->argument(0).toString());
375+
eventNamespaces[engine].append(prefix);
376+
return QScriptValue(true);
377+
}
378+
354379
//-- \subsection{include(file)}
355380
//-- Includes another source code file at this point. You should generally only specify the filename,
356381
//-- not try to specify its path, here.
@@ -554,6 +579,7 @@ QScriptEngine *loadPlayerScript(const QString& path, int player, int difficulty)
554579
engine->globalObject().setProperty("removeTimer", engine->newFunction(js_removeTimer));
555580
engine->globalObject().setProperty("profile", engine->newFunction(js_profile));
556581
engine->globalObject().setProperty("include", engine->newFunction(js_include));
582+
engine->globalObject().setProperty("namespace", engine->newFunction(js_namespace));
557583

558584
// Special global variables
559585
//== \item[version] Current version of the game, set in \emph{major.minor} format.

‎src/qtscriptdebug.cpp

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ void ScriptDebugger::deityButtonClicked()
9494
kf_ToggleGodMode();
9595
}
9696

97+
void ScriptDebugger::gatewayButtonClicked()
98+
{
99+
kf_ToggleShowGateways();
100+
}
101+
97102
void ScriptDebugger::weatherButtonClicked()
98103
{
99104
kf_ToggleWeather();
@@ -134,7 +139,8 @@ ScriptDebugger::ScriptDebugger(const MODELMAP &models, QStandardItemModel *trigg
134139
miscLayout->addWidget(createButton("Fog", SLOT(fogButtonClicked()), this));
135140
mainLayout->addLayout(miscLayout);
136141
QHBoxLayout *worldLayout = new QHBoxLayout();
137-
worldLayout->addWidget(createButton("Show all", SLOT(deityButtonClicked()), this));
142+
worldLayout->addWidget(createButton("Show gateways", SLOT(gatewayButtonClicked()), this));
143+
worldLayout->addWidget(createButton("Reveal all", SLOT(deityButtonClicked()), this));
138144
worldLayout->addWidget(createButton("Weather", SLOT(weatherButtonClicked()), this));
139145
worldLayout->addWidget(createButton("Reveal mode", SLOT(revealButtonClicked()), this));
140146
mainLayout->addLayout(worldLayout);
@@ -214,11 +220,20 @@ ScriptDebugger::ScriptDebugger(const MODELMAP &models, QStandardItemModel *trigg
214220
labelView.setSelectionMode(QAbstractItemView::SingleSelection);
215221
labelView.setSelectionBehavior(QAbstractItemView::SelectRows);
216222
connect(&labelView, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(labelClickedIdx(const QModelIndex &)));
217-
QPushButton *button = new QPushButton("Show", this);
218-
connect(button, SIGNAL(pressed()), this, SLOT(labelClicked()));
223+
QPushButton *buttonShow = new QPushButton("Show selected", this);
224+
QPushButton *buttonShowAll = new QPushButton("Show all", this);
225+
QPushButton *buttonShowActive = new QPushButton("Show active", this);
226+
QPushButton *buttonClear = new QPushButton("Clear", this);
227+
connect(buttonShow, SIGNAL(pressed()), this, SLOT(labelClicked()));
228+
connect(buttonShowAll, SIGNAL(pressed()), this, SLOT(labelClickedAll()));
229+
connect(buttonShowActive, SIGNAL(pressed()), this, SLOT(labelClickedActive()));
230+
connect(buttonClear, SIGNAL(pressed()), this, SLOT(labelClear()));
219231
QVBoxLayout *labelLayout = new QVBoxLayout(this);
220232
labelLayout->addWidget(&labelView);
221-
labelLayout->addWidget(button);
233+
labelLayout->addWidget(buttonShow);
234+
labelLayout->addWidget(buttonShowAll);
235+
labelLayout->addWidget(buttonShowActive);
236+
labelLayout->addWidget(buttonClear);
222237
QWidget *dummyWidget = new QWidget(this);
223238
dummyWidget->setLayout(labelLayout);
224239
tab.addTab(dummyWidget, "Labels");
@@ -251,6 +266,23 @@ void ScriptDebugger::updateModels()
251266
doUpdateModels = true;
252267
}
253268

269+
void ScriptDebugger::labelClear()
270+
{
271+
clearMarks();
272+
}
273+
274+
void ScriptDebugger::labelClickedAll()
275+
{
276+
clearMarks();
277+
markAllLabels(false);
278+
}
279+
280+
void ScriptDebugger::labelClickedActive()
281+
{
282+
clearMarks();
283+
markAllLabels(true);
284+
}
285+
254286
void ScriptDebugger::labelClicked()
255287
{
256288
QItemSelectionModel *selected = labelView.selectionModel();

‎src/qtscriptdebug.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class ScriptDebugger : public QDialog
6666
protected slots:
6767
void labelClickedIdx(const QModelIndex &idx);
6868
void labelClicked();
69+
void labelClickedAll();
70+
void labelClickedActive();
71+
void labelClear();
6972
void runClicked(QObject *obj);
7073
void updateModels();
7174
void powerEditing(const QString &value);
@@ -77,6 +80,7 @@ protected slots:
7780
void researchButtonClicked();
7881
void sensorsButtonClicked();
7982
void deityButtonClicked();
83+
void gatewayButtonClicked();
8084
void weatherButtonClicked();
8185
void revealButtonClicked();
8286
void shadowButtonClicked();

0 commit comments

Comments
 (0)