2010-11-22 21:12:04 +01:00
|
|
|
Engine.LoadHelperScript("FSM.js");
|
2011-06-28 20:25:38 +02:00
|
|
|
Engine.LoadHelperScript("Entity.js");
|
2011-11-26 02:58:39 +01:00
|
|
|
Engine.LoadHelperScript("Player.js");
|
2010-11-22 21:12:04 +01:00
|
|
|
Engine.LoadComponentScript("interfaces/Attack.js");
|
|
|
|
Engine.LoadComponentScript("interfaces/DamageReceiver.js");
|
|
|
|
Engine.LoadComponentScript("interfaces/Formation.js");
|
2012-04-17 22:22:13 +02:00
|
|
|
Engine.LoadComponentScript("interfaces/Heal.js");
|
2010-11-22 21:12:04 +01:00
|
|
|
Engine.LoadComponentScript("interfaces/Health.js");
|
2011-12-20 00:09:38 +01:00
|
|
|
Engine.LoadComponentScript("interfaces/ResourceSupply.js");
|
2010-11-22 21:12:04 +01:00
|
|
|
Engine.LoadComponentScript("interfaces/Timer.js");
|
|
|
|
Engine.LoadComponentScript("interfaces/UnitAI.js");
|
|
|
|
Engine.LoadComponentScript("Formation.js");
|
|
|
|
Engine.LoadComponentScript("UnitAI.js");
|
|
|
|
|
|
|
|
/* Regression test.
|
|
|
|
* Tests the FSM behaviour of a unit when walking as part of a formation,
|
|
|
|
* then exiting the formation.
|
|
|
|
* mode == 0: There is no enemy unit nearby.
|
|
|
|
* mode == 1: There is a live enemy unit nearby.
|
|
|
|
* mode == 2: There is a dead enemy unit nearby.
|
|
|
|
*/
|
|
|
|
function TestFormationExiting(mode)
|
|
|
|
{
|
|
|
|
ResetState();
|
|
|
|
|
|
|
|
var playerEntity = 5;
|
|
|
|
var unit = 10;
|
|
|
|
var enemy = 20;
|
|
|
|
var controller = 30;
|
|
|
|
|
|
|
|
|
|
|
|
AddMock(SYSTEM_ENTITY, IID_Timer, {
|
2012-04-29 19:39:16 +02:00
|
|
|
SetInterval: function() { },
|
2010-11-22 21:12:04 +01:00
|
|
|
SetTimeout: function() { },
|
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(SYSTEM_ENTITY, IID_RangeManager, {
|
2012-04-17 22:22:13 +02:00
|
|
|
CreateActiveQuery: function(ent, minRange, maxRange, players, iid, flags) {
|
2010-11-22 21:12:04 +01:00
|
|
|
return 1;
|
|
|
|
},
|
|
|
|
EnableActiveQuery: function(id) { },
|
|
|
|
ResetActiveQuery: function(id) { if (mode == 0) return []; else return [enemy]; },
|
|
|
|
DisableActiveQuery: function(id) { },
|
2012-04-17 22:22:13 +02:00
|
|
|
GetEntityFlagMask: function(identifier) { },
|
2010-11-22 21:12:04 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
|
|
|
|
GetPlayerByID: function(id) { return playerEntity; },
|
|
|
|
GetNumPlayers: function() { return 2; },
|
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(playerEntity, IID_Player, {
|
2011-07-02 02:06:39 +02:00
|
|
|
IsAlly: function() { return []; },
|
|
|
|
IsEnemy: function() { return []; },
|
2010-11-22 21:12:04 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
|
2011-03-05 00:22:09 +01:00
|
|
|
var unitAI = ConstructComponent(unit, "UnitAI", { "FormationController": "false", "DefaultStance": "aggressive" });
|
2010-11-22 21:12:04 +01:00
|
|
|
|
2011-05-04 01:16:16 +02:00
|
|
|
AddMock(unit, IID_Identity, {
|
|
|
|
GetClassesList: function() { return []; },
|
|
|
|
});
|
|
|
|
|
2011-06-28 20:25:38 +02:00
|
|
|
AddMock(unit, IID_Ownership, {
|
|
|
|
GetOwner: function() { return 1; },
|
|
|
|
});
|
|
|
|
|
2010-11-22 21:12:04 +01:00
|
|
|
AddMock(unit, IID_Position, {
|
|
|
|
GetPosition: function() { return { "x": 0, "z": 0 }; },
|
|
|
|
IsInWorld: function() { return true; },
|
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(unit, IID_UnitMotion, {
|
|
|
|
GetWalkSpeed: function() { return 1; },
|
|
|
|
MoveToFormationOffset: function(target, x, z) { },
|
2011-06-28 20:25:38 +02:00
|
|
|
IsInTargetRange: function(target, min, max) { return true; },
|
2010-11-30 13:31:54 +01:00
|
|
|
MoveToTargetRange: function(target, min, max) { },
|
|
|
|
StopMoving: function() { },
|
2010-11-22 21:12:04 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(unit, IID_Vision, {
|
|
|
|
GetRange: function() { return 10; },
|
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(unit, IID_Attack, {
|
|
|
|
GetRange: function() { return 10; },
|
|
|
|
GetBestAttack: function() { return "melee"; },
|
2012-05-02 00:20:08 +02:00
|
|
|
GetBestAttackAgainst: function(t) { return "melee"; },
|
2010-11-22 21:12:04 +01:00
|
|
|
GetTimers: function() { return { "prepare": 500, "repeat": 1000 }; },
|
2012-05-02 00:20:08 +02:00
|
|
|
CanAttack: function(v) { return true; },
|
|
|
|
CompareEntitiesByPreference: function(a, b) { return 0; },
|
2010-11-22 21:12:04 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
unitAI.OnCreate();
|
|
|
|
|
|
|
|
unitAI.SetupRangeQuery(1);
|
|
|
|
|
|
|
|
|
|
|
|
if (mode == 1)
|
|
|
|
AddMock(enemy, IID_Health, {
|
|
|
|
GetHitpoints: function() { return 10; },
|
|
|
|
});
|
|
|
|
else if (mode == 2)
|
|
|
|
AddMock(enemy, IID_Health, {
|
|
|
|
GetHitpoints: function() { return 0; },
|
|
|
|
});
|
|
|
|
|
|
|
|
var controllerFormation = ConstructComponent(controller, "Formation");
|
2011-03-05 00:22:09 +01:00
|
|
|
var controllerAI = ConstructComponent(controller, "UnitAI", { "FormationController": "true", "DefaultStance": "aggressive" });
|
2010-11-22 21:12:04 +01:00
|
|
|
|
|
|
|
AddMock(controller, IID_Position, {
|
|
|
|
JumpTo: function(x, z) { this.x = x; this.z = z; },
|
|
|
|
GetPosition: function() { return { "x": this.x, "z": this.z }; },
|
|
|
|
IsInWorld: function() { return true; },
|
|
|
|
});
|
|
|
|
|
|
|
|
AddMock(controller, IID_UnitMotion, {
|
|
|
|
SetUnitRadius: function(r) { },
|
|
|
|
SetSpeed: function(speed) { },
|
2010-11-30 13:31:54 +01:00
|
|
|
MoveToPointRange: function(x, z, minRange, maxRange) { },
|
2010-11-22 21:12:04 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
controllerAI.OnCreate();
|
|
|
|
|
|
|
|
|
|
|
|
TS_ASSERT_EQUALS(controllerAI.fsmStateName, "FORMATIONCONTROLLER.IDLE");
|
|
|
|
TS_ASSERT_EQUALS(unitAI.fsmStateName, "INDIVIDUAL.IDLE");
|
|
|
|
|
|
|
|
controllerFormation.SetMembers([unit]);
|
|
|
|
controllerAI.Walk(100, 100, false);
|
|
|
|
controllerAI.OnMotionChanged({ "starting": true });
|
|
|
|
|
|
|
|
TS_ASSERT_EQUALS(controllerAI.fsmStateName, "FORMATIONCONTROLLER.WALKING");
|
|
|
|
TS_ASSERT_EQUALS(unitAI.fsmStateName, "FORMATIONMEMBER.WALKING");
|
|
|
|
|
|
|
|
controllerFormation.Disband();
|
|
|
|
|
|
|
|
if (mode == 0)
|
|
|
|
TS_ASSERT_EQUALS(unitAI.fsmStateName, "INDIVIDUAL.IDLE");
|
|
|
|
else if (mode == 1)
|
|
|
|
TS_ASSERT_EQUALS(unitAI.fsmStateName, "INDIVIDUAL.COMBAT.ATTACKING");
|
|
|
|
else if (mode == 2)
|
|
|
|
TS_ASSERT_EQUALS(unitAI.fsmStateName, "INDIVIDUAL.IDLE");
|
|
|
|
else
|
|
|
|
TS_FAIL("invalid mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
TestFormationExiting(0);
|
|
|
|
TestFormationExiting(1);
|
|
|
|
TestFormationExiting(2);
|