1
0
forked from 0ad/0ad

Make UnitAI moddable by exposing the FSM spec and calculated FSM as part of the prototype

This was SVN commit r15237.
This commit is contained in:
sanderd17 2014-05-27 07:24:07 +00:00
parent e4d3189494
commit b9f3a95e17

View File

@ -124,7 +124,7 @@ var g_Stances = {
};
// See ../helpers/FSM.js for some documentation of this FSM specification syntax
var UnitFsmSpec = {
UnitAI.prototype.UnitFsmSpec = {
// Default event handlers:
@ -3109,8 +3109,6 @@ var UnitFsmSpec = {
},
};
var UnitFsm = new FSM(UnitFsmSpec);
UnitAI.prototype.Init = function()
{
this.orderQueue = []; // current order is at the front of the list
@ -3243,11 +3241,11 @@ UnitAI.prototype.IsWalkingAndFighting = function()
UnitAI.prototype.OnCreate = function()
{
if (this.IsAnimal())
UnitFsm.Init(this, "ANIMAL.FEEDING");
this.UnitFsm.Init(this, "ANIMAL.FEEDING");
else if (this.IsFormationController())
UnitFsm.Init(this, "FORMATIONCONTROLLER.IDLE");
this.UnitFsm.Init(this, "FORMATIONCONTROLLER.IDLE");
else
UnitFsm.Init(this, "INDIVIDUAL.IDLE");
this.UnitFsm.Init(this, "INDIVIDUAL.IDLE");
};
UnitAI.prototype.OnDiplomacyChanged = function(msg)
@ -3267,7 +3265,7 @@ UnitAI.prototype.OnOwnershipChanged = function(msg)
// Switch to a virgin state to let states execute their leave handlers.
var index = this.GetCurrentState().indexOf(".");
if (index != -1)
UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index));
this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index));
this.SetStance(this.template.DefaultStance);
if(!this.isGarrisoned)
@ -3278,7 +3276,7 @@ UnitAI.prototype.OnOwnershipChanged = function(msg)
UnitAI.prototype.OnDestroy = function()
{
// Switch to an empty state to let states execute their leave handlers.
UnitFsm.SwitchToNextState(this, "");
this.UnitFsm.SwitchToNextState(this, "");
// Clean up range queries
var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
@ -3320,7 +3318,7 @@ UnitAI.prototype.OnPickupCanceled = function(msg)
if (this.orderQueue[i].type == "PickupUnit" && this.orderQueue[i].data.target == msg.entity)
{
if (i == 0)
UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
else
this.orderQueue.splice(i, 1);
break;
@ -3419,24 +3417,24 @@ UnitAI.prototype.SetupHealRangeQuery = function()
UnitAI.prototype.SetNextState = function(state)
{
UnitFsm.SetNextState(this, state);
this.UnitFsm.SetNextState(this, state);
};
// This will make sure that the state is always entered even if this means leaving it and reentering it
// This is so that a state can be reinitialized with new order data without having to switch to an intermediate state
UnitAI.prototype.SetNextStateAlwaysEntering = function(state)
{
UnitFsm.SetNextStateAlwaysEntering(this, state);
this.UnitFsm.SetNextStateAlwaysEntering(this, state);
};
UnitAI.prototype.DeferMessage = function(msg)
{
UnitFsm.DeferMessage(this, msg);
this.UnitFsm.DeferMessage(this, msg);
};
UnitAI.prototype.GetCurrentState = function()
{
return UnitFsm.GetCurrentState(this);
return this.UnitFsm.GetCurrentState(this);
};
UnitAI.prototype.FsmStateNameChanged = function(state)
@ -3465,7 +3463,7 @@ UnitAI.prototype.FinishOrder = function()
if (this.orderQueue.length)
{
var ret = UnitFsm.ProcessMessage(this,
var ret = this.UnitFsm.ProcessMessage(this,
{"type": "Order."+this.order.type, "data": this.order.data}
);
@ -3519,7 +3517,7 @@ UnitAI.prototype.PushOrder = function(type, data)
if (this.orderQueue.length == 1)
{
this.order = order;
var ret = UnitFsm.ProcessMessage(this,
var ret = this.UnitFsm.ProcessMessage(this,
{"type": "Order."+this.order.type, "data": this.order.data}
);
@ -3555,7 +3553,7 @@ UnitAI.prototype.PushOrderFront = function(type, data)
{
this.orderQueue.unshift(order);
this.order = order;
var ret = UnitFsm.ProcessMessage(this,
var ret = this.UnitFsm.ProcessMessage(this,
{"type": "Order."+this.order.type, "data": this.order.data}
);
@ -3756,7 +3754,7 @@ UnitAI.prototype.TimerHandler = function(data, lateness)
this.timer = undefined;
}
UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
};
/**
@ -3797,11 +3795,11 @@ UnitAI.prototype.OnMotionChanged = function(msg)
{
if (msg.starting && !msg.error)
{
UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "MoveStarted", "data": msg});
}
else if (!msg.starting || msg.error)
{
UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "MoveCompleted", "data": msg});
}
};
@ -3810,7 +3808,7 @@ UnitAI.prototype.OnGlobalConstructionFinished = function(msg)
// TODO: This is a bit inefficient since every unit listens to every
// construction message - ideally we could scope it to only the one we're building
UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
};
UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
@ -3829,30 +3827,30 @@ UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
UnitAI.prototype.OnAttacked = function(msg)
{
UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
};
UnitAI.prototype.OnGuardedAttacked = function(msg)
{
UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
};
UnitAI.prototype.OnHealthChanged = function(msg)
{
UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
};
UnitAI.prototype.OnRangeUpdate = function(msg)
{
if (msg.tag == this.losRangeQuery)
UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
else if (msg.tag == this.losHealRangeQuery)
UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
};
UnitAI.prototype.OnPackFinished = function(msg)
{
UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
};
//// Helper functions to be called by the FSM ////
@ -4647,7 +4645,7 @@ UnitAI.prototype.SetFormationController = function(ent)
// If we were removed from a formation, let the FSM switch back to INDIVIDUAL
if (ent == INVALID_ENTITY)
UnitFsm.ProcessMessage(this, { "type": "FormationLeave" });
this.UnitFsm.ProcessMessage(this, { "type": "FormationLeave" });
};
UnitAI.prototype.GetFormationController = function()
@ -4824,7 +4822,7 @@ UnitAI.prototype.RemoveGuard = function()
return;
if (this.order.type == "Guard")
UnitFsm.ProcessMessage(this, {"type": "RemoveGuard"});
this.UnitFsm.ProcessMessage(this, {"type": "RemoveGuard"});
else
for (var i = 1; i < this.orderQueue.length; ++i)
if (this.orderQueue[i].type == "Guard")
@ -5785,4 +5783,6 @@ UnitAI.prototype.TestAllMemberFunction = function(funcname, args)
return true;
};
UnitAI.prototype.UnitFsm = new FSM(UnitAI.prototype.UnitFsmSpec);
Engine.RegisterComponentType(IID_UnitAI, "UnitAI", UnitAI);