Index: ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js (revision 20616) +++ ps/trunk/binaries/data/mods/public/simulation/components/AlertRaiser.js (revision 20617) @@ -1,162 +1,155 @@ function AlertRaiser() {} AlertRaiser.prototype.Schema = "" + ""; AlertRaiser.prototype.Init = function() { this.level = 0; - - // Remember the units ordered to garrison this.garrisonedUnits = []; - this.walkingUnits = []; - - // Remember production buildings under alert this.prodBuildings = []; + this.walkingUnits = []; }; AlertRaiser.prototype.GetLevel = function() { return this.level; }; AlertRaiser.prototype.HasRaisedAlert = function() { return this.level > 0; }; AlertRaiser.prototype.CanIncreaseLevel = function() { return this.template.MaximumLevel > this.level; }; AlertRaiser.prototype.SoundAlert = function() { - var alertString = "alert" + this.level; - PlaySound(alertString, this.entity); + PlaySound("alert" + this.level, this.entity); }; /** * Used when units are spawned and need to follow alert orders. * @param {number[]} units - Entity IDs of spawned units. */ AlertRaiser.prototype.UpdateUnits = function(units) { - var level = this.GetLevel(); - for (var unit of units) + for (let unit of units) { - var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); - if (!cmpUnitAI || !cmpUnitAI.ReactsToAlert(level)) + let cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); + if (!cmpUnitAI || !cmpUnitAI.ReactsToAlert(this.level)) continue; - cmpUnitAI.ReplaceOrder("Alert", {"raiser": this.entity, "force": true}); + + cmpUnitAI.ReplaceOrder("Alert", { "raiser": this.entity, "force": true }); this.walkingUnits.push(unit); } }; AlertRaiser.prototype.IncreaseAlertLevel = function() { if (!this.CanIncreaseLevel()) return false; - this.level++; + ++this.level; this.SoundAlert(); // Find buildings/units owned by this unit's player - var players = []; - var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); + let players = []; + let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); if (cmpOwnership) players = [cmpOwnership.GetOwner()]; // Select production buildings to put "under alert", including the raiser itself if possible - var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - var level = this.GetLevel(); - var buildings = cmpRangeManager.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_ProductionQueue); + let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); + let buildings = cmpRangeManager.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_ProductionQueue); if (Engine.QueryInterface(this.entity, IID_ProductionQueue)) buildings.push(this.entity); - for (var building of buildings) + for (let building of buildings) { - var cmpProductionQueue = Engine.QueryInterface(building, IID_ProductionQueue); + let cmpProductionQueue = Engine.QueryInterface(building, IID_ProductionQueue); cmpProductionQueue.PutUnderAlert(this.entity); this.prodBuildings.push(building); } // Select units to put under alert, according to their reaction to this level - var level = this.GetLevel(); - var units = cmpRangeManager.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter(ent => { - var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); - return !cmpUnitAI.IsUnderAlert() && cmpUnitAI.ReactsToAlert(level); + let units = cmpRangeManager.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter(ent => { + let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); + return !cmpUnitAI.IsUnderAlert() && cmpUnitAI.ReactsToAlert(this.level); }); - for (var unit of units) + for (let unit of units) { - var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); - cmpUnitAI.ReplaceOrder("Alert", {"raiser": this.entity, "force": true}); + let cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); + cmpUnitAI.ReplaceOrder("Alert", { "raiser": this.entity, "force": true }); this.walkingUnits.push(unit); } return true; }; AlertRaiser.prototype.OnUnitGarrisonedAfterAlert = function(msg) { - this.garrisonedUnits.push({"holder": msg.holder, "unit": msg.unit}); + this.garrisonedUnits.push({ "holder": msg.holder, "unit": msg.unit }); - var index = this.walkingUnits.indexOf(msg.unit); + let index = this.walkingUnits.indexOf(msg.unit); if (index != -1) this.walkingUnits.splice(index, 1); }; AlertRaiser.prototype.EndOfAlert = function() { this.level = 0; this.SoundAlert(); // First, handle units not yet garrisoned - for (var unit of this.walkingUnits) + for (let unit of this.walkingUnits) { - var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); + let cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); if (!cmpUnitAI) continue; cmpUnitAI.ResetAlert(); if (cmpUnitAI.HasWorkOrders()) cmpUnitAI.BackToWork(); else cmpUnitAI.ReplaceOrder("Stop", undefined); } this.walkingUnits = []; // Then, eject garrisoned units - for (var slot of this.garrisonedUnits) + for (let slot of this.garrisonedUnits) { - var cmpGarrisonHolder = Engine.QueryInterface(slot.holder, IID_GarrisonHolder); - var cmpUnitAI = Engine.QueryInterface(slot.unit, IID_UnitAI); + let cmpGarrisonHolder = Engine.QueryInterface(slot.holder, IID_GarrisonHolder); + let cmpUnitAI = Engine.QueryInterface(slot.unit, IID_UnitAI); if (!cmpUnitAI) continue; // If the garrison building was destroyed, the unit is already ejected if (!cmpGarrisonHolder || cmpGarrisonHolder.PerformEject([slot.unit], true)) { cmpUnitAI.ResetAlert(); if (cmpUnitAI.HasWorkOrders()) cmpUnitAI.BackToWork(); } } this.garrisonedUnits = []; // Finally, reset production buildings state - for (var building of this.prodBuildings) + for (let building of this.prodBuildings) { - var cmpProductionQueue = Engine.QueryInterface(building, IID_ProductionQueue); + let cmpProductionQueue = Engine.QueryInterface(building, IID_ProductionQueue); if (cmpProductionQueue) cmpProductionQueue.ResetAlert(); } this.prodBuildings = []; return true; }; Engine.RegisterComponentType(IID_AlertRaiser, "AlertRaiser", AlertRaiser); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_AlertRaiser.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_AlertRaiser.js (nonexistent) +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_AlertRaiser.js (revision 20617) @@ -0,0 +1,68 @@ +Engine.LoadComponentScript("interfaces/AlertRaiser.js") +Engine.LoadComponentScript("interfaces/ProductionQueue.js"); +Engine.LoadComponentScript("interfaces/Sound.js"); +Engine.LoadComponentScript("interfaces/UnitAI.js"); +Engine.LoadComponentScript("AlertRaiser.js"); + +const alertRaiserId = 5; +const unitsIds = [10, 11, 12]; +const buildingsIds = [13, 14, 15]; + +let cmpAlertRaiser = ConstructComponent(alertRaiserId, "AlertRaiser", { + "MaximumLevel": 0, + "Range": 50 +}); + +Engine.RegisterGlobal("PlaySound", (name, source) => { + TS_ASSERT_EQUALS(name, "alert" + cmpAlertRaiser.GetLevel()); + TS_ASSERT_EQUALS(source, alertRaiserId); +}); + +AddMock(SYSTEM_ENTITY, IID_RangeManager, { + "ExecuteQuery": (ent, value, range, players, iid) => iid === IID_UnitAI ? unitsIds : buildingsIds +}); + +unitsIds.forEach((unitId) => { + AddMock(unitId, IID_UnitAI, { + "ReactsToAlert": (alertLevel) => alertLevel >= 2, + "ReplaceOrder": () => {}, + "IsUnderAlert": () => {}, + "HasWorkOrders": () => true, + "BackToWork": () => {}, + "ResetAlert": () => {} + }); +}); + +buildingsIds.forEach((buildingId) => { + AddMock(buildingId, IID_ProductionQueue, { + "PutUnderAlert": (alertRaiserId) => {}, + "ResetAlert": () => {} + }); +}); + +TS_ASSERT_EQUALS(cmpAlertRaiser.GetLevel(), 0); +TS_ASSERT_EQUALS(cmpAlertRaiser.HasRaisedAlert(), false); +TS_ASSERT_EQUALS(cmpAlertRaiser.CanIncreaseLevel(), false); +TS_ASSERT_EQUALS(cmpAlertRaiser.IncreaseAlertLevel(), false); + +cmpAlertRaiser = ConstructComponent(alertRaiserId, "AlertRaiser", { + "MaximumLevel": 2, + "Range": 50 +}); + +TS_ASSERT_EQUALS(cmpAlertRaiser.CanIncreaseLevel(), true); + +cmpAlertRaiser.UpdateUnits([]); +cmpAlertRaiser.UpdateUnits(unitsIds); + +TS_ASSERT_UNEVAL_EQUALS(cmpAlertRaiser.walkingUnits, []); +TS_ASSERT_EQUALS(cmpAlertRaiser.IncreaseAlertLevel(), true); +TS_ASSERT_EQUALS(cmpAlertRaiser.GetLevel(), 1); +TS_ASSERT_UNEVAL_EQUALS(cmpAlertRaiser.prodBuildings, buildingsIds); +TS_ASSERT_EQUALS(cmpAlertRaiser.IncreaseAlertLevel(), true); +TS_ASSERT_EQUALS(cmpAlertRaiser.GetLevel(), 2); +TS_ASSERT_UNEVAL_EQUALS(cmpAlertRaiser.walkingUnits, unitsIds); +TS_ASSERT_EQUALS(cmpAlertRaiser.IncreaseAlertLevel(), false); +TS_ASSERT_EQUALS(cmpAlertRaiser.HasRaisedAlert(), true); +TS_ASSERT_EQUALS(cmpAlertRaiser.EndOfAlert(), true); +TS_ASSERT_EQUALS(cmpAlertRaiser.GetLevel(), 0); Property changes on: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_AlertRaiser.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property