Index: ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -179,17 +179,6 @@ this.entities.push(entity); this.UpdateGarrisonFlag(); - let cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); - if (cmpProductionQueue) - cmpProductionQueue.PauseProduction(); - - let cmpAura = Engine.QueryInterface(entity, IID_Auras); - if (cmpAura && cmpAura.HasGarrisonAura()) - cmpAura.ApplyGarrisonAura(this.entity); - - let cmpPosition = Engine.QueryInterface(entity, IID_Position); - if (cmpPosition) - cmpPosition.MoveOutOfWorld(); Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [entity], @@ -215,7 +204,27 @@ if (entityIndex == -1) return false; - // Find spawning location + let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable); + if (!cmpGarrisonable || !cmpGarrisonable.UnGarrison(forced)) + return false; + + this.entities.splice(entityIndex, 1); + Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { + "added": [], + "removed": [entity], + "renamed": renamed + }); + + return true; +}; + +/** + * @param {number} entity - EntityID to find the spawn position for. + * @param {boolean} forced - Optionally whether the spawning is forced. + * @return {Vector3D} - An appropriate spawning position. + */ +GarrisonHolder.prototype.GetSpawnPosition = function(entity, forced) +{ let cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); @@ -232,49 +241,13 @@ { // Error: couldn't find space satisfying the unit's passability criteria if (!forced) - return false; + return null; // If ejection is forced, we need to continue, so use center of the building let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); pos = cmpPosition.GetPosition(); } - - this.entities.splice(entityIndex, 1); - - let cmpEntUnitAI = Engine.QueryInterface(entity, IID_UnitAI); - if (cmpEntUnitAI) - cmpEntUnitAI.Ungarrison(); - - let cmpEntProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue); - if (cmpEntProductionQueue) - cmpEntProductionQueue.UnpauseProduction(); - - let cmpEntAura = Engine.QueryInterface(entity, IID_Auras); - if (cmpEntAura && cmpEntAura.HasGarrisonAura()) - cmpEntAura.RemoveGarrisonAura(this.entity); - - let cmpEntPosition = Engine.QueryInterface(entity, IID_Position); - if (cmpEntPosition) - { - cmpEntPosition.JumpTo(pos.x, pos.z); - cmpEntPosition.SetHeightOffset(0); - - let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); - if (cmpPosition) - cmpEntPosition.SetYRotation(cmpPosition.GetPosition().horizAngleTo(pos)); - } - - let cmpGarrisonable = Engine.QueryInterface(entity, IID_Garrisonable); - if (cmpGarrisonable) - cmpGarrisonable.UnGarrison(); - - Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { - "added": [], - "removed": [entity], - "renamed": renamed - }); - - return true; + return pos; }; /** Index: ps/trunk/binaries/data/mods/public/simulation/components/Garrisonable.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/Garrisonable.js +++ ps/trunk/binaries/data/mods/public/simulation/components/Garrisonable.js @@ -24,15 +24,61 @@ return false; this.holder = entity; + + let cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue); + if (cmpProductionQueue) + cmpProductionQueue.PauseProduction(); + + let cmpAura = Engine.QueryInterface(this.entity, IID_Auras); + if (cmpAura && cmpAura.HasGarrisonAura()) + cmpAura.ApplyGarrisonAura(entity); + + let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); + if (cmpPosition) + cmpPosition.MoveOutOfWorld(); + return true; }; /** - * Resets the garrisonHolder. + * @param {boolean} forced - Optionally whether the spawning is forced. + * @return {boolean} - Whether the ungarrisoning succeeded. */ -Garrisonable.prototype.UnGarrison = function() +Garrisonable.prototype.UnGarrison = function(forced) { + let cmpPosition = Engine.QueryInterface(this.entity, IID_Position); + if (cmpPosition) + { + let pos; + let cmpGarrisonHolder = Engine.QueryInterface(this.holder, IID_GarrisonHolder); + if (cmpGarrisonHolder) + pos = cmpGarrisonHolder.GetSpawnPosition(this.entity, forced); + + if (!pos) + return false; + + cmpPosition.JumpTo(pos.x, pos.z); + cmpPosition.SetHeightOffset(0); + + let cmpHolderPosition = Engine.QueryInterface(this.holder, IID_Position); + if (cmpHolderPosition) + cmpPosition.SetYRotation(cmpHolderPosition.GetPosition().horizAngleTo(pos)); + } + + let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI); + if (cmpUnitAI) + cmpUnitAI.Ungarrison(); + + let cmpProductionQueue = Engine.QueryInterface(this.entity, IID_ProductionQueue); + if (cmpProductionQueue) + cmpProductionQueue.UnpauseProduction(); + + let cmpAura = Engine.QueryInterface(this.entity, IID_Auras); + if (cmpAura && cmpAura.HasGarrisonAura()) + cmpAura.RemoveGarrisonAura(this.holder); + delete this.holder; + return true; }; Engine.RegisterComponentType(IID_Garrisonable, "Garrisonable", Garrisonable); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_GarrisonHolder.js @@ -4,12 +4,9 @@ Engine.LoadComponentScript("interfaces/Garrisonable.js"); Engine.LoadComponentScript("interfaces/TurretHolder.js"); Engine.LoadComponentScript("GarrisonHolder.js"); -Engine.LoadComponentScript("interfaces/Auras.js"); Engine.LoadComponentScript("interfaces/Health.js"); -Engine.LoadComponentScript("interfaces/ProductionQueue.js"); Engine.LoadComponentScript("interfaces/ModifiersManager.js"); Engine.LoadComponentScript("interfaces/Timer.js"); -Engine.LoadComponentScript("interfaces/UnitAI.js"); const garrisonedEntitiesList = [25, 26, 27, 28, 29, 30, 31, 32, 33]; const garrisonHolderId = 15; @@ -70,7 +67,7 @@ AddMock(i, IID_Garrisonable, { "Garrison": entity => true, - "UnGarrison": () => {} + "UnGarrison": () => true }); AddMock(i, IID_Position, { @@ -217,7 +214,7 @@ }); AddMock(siegeEngineId, IID_Garrisonable, { "Garrison": entity => true, - "UnGarrison": () => {} + "UnGarrison": () => true }); let cavalryId = 46; AddMock(cavalryId, IID_Identity, { @@ -238,7 +235,7 @@ }); AddMock(cavalryId, IID_Garrisonable, { "Garrison": entity => true, - "UnGarrison": () => {} + "UnGarrison": () => true }); TS_ASSERT(cmpGarrisonHolder.Garrison(siegeEngineId)); TS_ASSERT_EQUALS(cmpGarrisonHolder.GetGarrisonedEntitiesCount(), 1); Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js +++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Garrisonable.js @@ -1,4 +1,7 @@ +Engine.LoadComponentScript("interfaces/Auras.js"); Engine.LoadComponentScript("interfaces/Garrisonable.js"); +Engine.LoadComponentScript("interfaces/ProductionQueue.js"); +Engine.LoadComponentScript("interfaces/UnitAI.js"); Engine.LoadComponentScript("Garrisonable.js"); const garrisonHolderID = 1;