Index: ps/trunk/binaries/data/mods/public/maps/scenarios/Triggers_demo.js
===================================================================
--- ps/trunk/binaries/data/mods/public/maps/scenarios/Triggers_demo.js (revision 15425)
+++ ps/trunk/binaries/data/mods/public/maps/scenarios/Triggers_demo.js (revision 15426)
@@ -1,90 +1,97 @@
warn("loading the triggers file");
///////////////////////
// Trigger listeners //
///////////////////////
// every function just logs when it gets fired, and shows the data
Trigger.prototype.StructureBuiltAction = function(data)
{
warn("The OnStructureBuilt event happened with the following data:");
warn(uneval(data));
};
Trigger.prototype.ConstructionStartedAction = function(data)
{
warn("The OnConstructionStarted event happened with the following data:");
warn(uneval(data));
};
Trigger.prototype.TrainingFinishedAction = function(data)
{
warn("The OnTrainingFinished event happened with the following data:");
warn(uneval(data));
};
Trigger.prototype.TrainingQueuedAction = function(data)
{
warn("The OnTrainingQueued event happened with the following data:");
warn(uneval(data));
};
Trigger.prototype.ResearchFinishedAction = function(data)
{
warn("The OnResearchFinished event happened with the following data:");
warn(uneval(data));
};
Trigger.prototype.ResearchQueuedAction = function(data)
{
warn("The OnResearchQueued event happened with the following data:");
warn(uneval(data));
};
+Trigger.prototype.OwnershipChangedAction = function(data)
+{
+ warn("The OnOwnershipChanged event happened with the following data:");
+ warn(uneval(data));
+};
+
Trigger.prototype.PlayerCommandAction = function(data)
{
warn("The OnPlayerCommand event happened with the following data:");
warn(uneval(data));
};
Trigger.prototype.IntervalAction = function(data)
{
warn("The OnInterval event happened with the following data:");
warn(uneval(data));
this.numberOfTimerTrigger++;
if (this.numberOfTimerTrigger >= this.maxNumberOfTimerTrigger)
this.DisableTrigger("OnInterval", "IntervalAction");
};
Trigger.prototype.RangeAction = function(data)
{
warn("The OnRange event happened with the following data:");
warn(uneval(data));
};
// Activate all possible triggers
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
var data = {"enabled": true};
cmpTrigger.RegisterTrigger("OnStructureBuilt", "StructureBuiltAction", data);
cmpTrigger.RegisterTrigger("OnConstructionStarted", "ConstructionStartedAction", data);
cmpTrigger.RegisterTrigger("OnTrainingFinished", "TrainingFinishedAction", data);
cmpTrigger.RegisterTrigger("OnTrainingQueued", "TrainingQueuedAction", data);
cmpTrigger.RegisterTrigger("OnResearchFinished", "ResearchFinishedAction", data);
cmpTrigger.RegisterTrigger("OnResearchQueued", "ResearchQueuedAction", data);
+cmpTrigger.RegisterTrigger("OnOwnershipChanged", "OwnershipChangedAction", data);
cmpTrigger.RegisterTrigger("OnPlayerCommand", "PlayerCommandAction", data);
data.delay = 10000; // after 10 seconds
data.interval = 1000; // every second
cmpTrigger.numberOfTimerTrigger = 0;
cmpTrigger.maxNumberOfTimerTrigger = 10; // execute it 10 times maximum
cmpTrigger.RegisterTrigger("OnInterval", "IntervalAction", data);
var entities = cmpTrigger.GetTriggerPoints("A");
data = {
"entities": entities, // central points to calculate the range circles
"players": [1], // only count entities of player 1
"maxRange": 40,
"requiredComponent": IID_UnitAI, // only count units in range
"enabled": true,
};
cmpTrigger.RegisterTrigger("OnRange", "RangeAction", data);
Index: ps/trunk/binaries/data/mods/public/simulation/components/Trigger.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/Trigger.js (revision 15425)
+++ ps/trunk/binaries/data/mods/public/simulation/components/Trigger.js (revision 15426)
@@ -1,258 +1,265 @@
function Trigger() {}
Trigger.prototype.Schema =
"";
/**
* Events we're able to receive and call handlers for
*/
Trigger.prototype.eventNames =
[
"StructureBuilt",
"ConstructionStarted",
"TrainingFinished",
"TrainingQueued",
"ResearchFinished",
"ResearchQueued",
+ "OwnershipChanged",
"PlayerCommand",
"Interval",
"Range",
];
Trigger.prototype.Init = function()
{
this.triggerPoints = {};
// Each event has its own set of actions determined by the map maker.
for each (var eventName in this.eventNames)
this["On" + eventName + "Actions"] = {};
};
Trigger.prototype.RegisterTriggerPoint = function(ref, ent)
{
if (!this.triggerPoints[ref])
this.triggerPoints[ref] = [];
this.triggerPoints[ref].push(ent);
};
Trigger.prototype.RemoveRegisteredTriggerPoint = function(ref, ent)
{
if (!this.triggerPoints[ref])
{
warn("no trigger points found with ref "+ref);
return;
}
var i = this.triggerPoints[ref].indexOf(ent);
if (i == -1)
{
warn("entity " + ent + " wasn't found under the trigger points with ref "+ref);
return;
}
this.triggerPoints[ref].splice(i, 1);
};
Trigger.prototype.GetTriggerPoints = function(ref)
{
return this.triggerPoints[ref] || [];
};
/** Binds the "action" function to one of the implemented events.
*
* @param event Name of the event (see the list in init)
* @param action Functionname of a function available under this object
* @param Extra Data for the trigger (enabled or not, delay for timers, range for range triggers ...)
*
* Interval triggers example:
* data = {enabled: true, interval: 1000, delay: 500}
*
* Range trigger:
* data.entities = [id1, id2] * Ids of the source
* data.players = [1,2,3,...] * list of player ids
* data.minRange = 0 * Minimum range for the query
* data.maxRange = -1 * Maximum range for the query (-1 = no maximum)
* data.requiredComponent = 0 * Required component id the entities will have
* data.enabled = false * If the query is enabled by default
*/
Trigger.prototype.RegisterTrigger = function(event, action, data)
{
var eventString = event + "Actions";
if (!this[eventString])
{
warn("Trigger.js: Invalid trigger event \"" + event + "\".")
return;
}
if (this[eventString][action])
{
warn("Trigger.js: Trigger has been registered before. Aborting...");
return;
}
// clone the data to be sure it's only modified locally
// We could run into triggers overwriting each other's data otherwise.
// F.e. getting the wrong timer tag
data = clone(data) || {"enabled": false};
this[eventString][action] = data;
// setup range query
if (event == "OnRange")
{
if (!data.entities)
{
warn("Trigger.js: Range triggers should carry extra data");
return;
}
data.queries = [];
for (var ent of data.entities)
{
var cmpTriggerPoint = Engine.QueryInterface(ent, IID_TriggerPoint);
if (!cmpTriggerPoint)
{
warn("Trigger.js: Range triggers must be defined on trigger points");
continue;
}
data.queries.push(cmpTriggerPoint.RegisterRangeTrigger(action, data));
}
}
if (data.enabled)
this.EnableTrigger(event, action);
};
// Disable trigger
Trigger.prototype.DisableTrigger = function(event, action)
{
var eventString = event + "Actions";
if (!this[eventString][action])
{
warn("Trigger.js: Disabling unknown trigger");
return;
}
var data = this[eventString][action];
// special casing interval and range triggers for performance
if (event == "OnInterval")
{
if (!data.timer) // don't disable it a second time
return;
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
cmpTimer.CancelTimer(data.timer);
data.timer = null;
}
else if (event == "OnRange")
{
if (!data.queries)
{
warn("Trigger.js: Range query wasn't set up before trying to disable it.");
return;
}
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
for (var query of data.queries)
cmpRangeManager.DisableActiveQuery(query);
}
data.enabled = false;
};
// Enable trigger
Trigger.prototype.EnableTrigger = function(event, action)
{
var eventString = event + "Actions";
if (!this[eventString][action])
{
warn("Trigger.js: Enabling unknown trigger");
return;
}
var data = this[eventString][action];
// special casing interval and range triggers for performance
if (event == "OnInterval")
{
if (data.timer) // don't enable it a second time
return;
if (!data.interval)
{
warn("Trigger.js: An interval trigger should have an intervel in its data")
return;
}
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
var timer = cmpTimer.SetInterval(this.entity, IID_Trigger, "DoAction", data.delay || 0, data.interval, {"action" : action});
data.timer = timer;
}
else if (event == "OnRange")
{
if (!data.queries)
{
warn("Trigger.js: Range query wasn't set up before");
return;
}
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
for (var query of data.queries)
cmpRangeManager.EnableActiveQuery(query);
}
data.enabled = true;
};
/**
* This function executes the actions bound to the events
* It's either called directlty from other simulation scripts,
* or from message listeners in this file
*
* @param event Name of the event (see the list in init)
* @param data Data object that will be passed to the actions
*/
Trigger.prototype.CallEvent = function(event, data)
{
var eventString = "On" + event + "Actions";
if (!this[eventString])
{
warn("Trigger.js: Unknown trigger event called:\"" + event + "\".");
return;
}
for (var action in this[eventString])
{
if (this[eventString][action].enabled)
this.DoAction({"action": action, "data":data});
}
};
// Handles "OnStructureBuilt" event.
Trigger.prototype.OnGlobalConstructionFinished = function(msg)
{
this.CallEvent("StructureBuilt", {"building": msg.newentity}); // The data for this one is {"building": constructedBuilding}
};
// Handles "OnTrainingFinished" event.
Trigger.prototype.OnGlobalTrainingFinished = function(msg)
{
this.CallEvent("TrainingFinished", msg);
// The data for this one is {"entities": createdEnts,
// "owner": cmpOwnership.GetOwner(),
// "metadata": metadata}
// See function "SpawnUnits" in ProductionQueue for more details
};
+Trigger.prototype.OnGlobalOwnershipChanged = function(msg)
+{
+ this.CallEvent("OwnershipChanged", msg);
+ // data is {"entities": ents, "from": playerId, "to": playerId}
+};
+
/**
* Execute a function after a certain delay
* @param time The delay expressed in milleseconds
* @param action Name of the action function
* @param data Data object that will be passed to the action function
*/
Trigger.prototype.DoAfterDelay = function(miliseconds, action, data)
{
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
return cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_Trigger, "DoAction", miliseconds, {"action": action, "data": data});
};
/**
* Called by the trigger listeners to exucute the actual action. Including sanity checks.
*/
Trigger.prototype.DoAction = function(msg)
{
if (this[msg.action])
this[msg.action](msg.data || null);
else
warn("Trigger.js: called a trigger action '" + msg.action + "' that wasn't found");
};
Engine.RegisterSystemComponentType(IID_Trigger, "Trigger", Trigger);