From 7679d1073b2202a47ea705c6b3369381c768ff53 Mon Sep 17 00:00:00 2001 From: historic_bruno Date: Wed, 17 Aug 2011 01:43:23 +0000 Subject: [PATCH] Fixes garrison behavior for ships - they no longer unload units underwater. See #893. Fixes behavior when ships are destroyed (garrisoned units at the time will also be killed). Updates ship templates accordingly. This was SVN commit r10020. --- .../simulation/components/GarrisonHolder.js | 136 +++++++++++++----- .../public/simulation/helpers/Commands.js | 17 ++- .../template_unit_mechanical_ship.xml | 1 + .../template_unit_mechanical_ship_bireme.xml | 8 +- .../template_unit_mechanical_ship_fishing.xml | 6 +- ...template_unit_mechanical_ship_merchant.xml | 6 +- ...plate_unit_mechanical_ship_quinquereme.xml | 8 +- .../template_unit_mechanical_ship_trireme.xml | 8 +- 8 files changed, 132 insertions(+), 58 deletions(-) diff --git a/binaries/data/mods/public/simulation/components/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/GarrisonHolder.js index c506a796e6..e1221a26fd 100644 --- a/binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ b/binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -11,7 +11,7 @@ GarrisonHolder.prototype.Schema = "" + "" + "" + - "" + + "" + "" + "" + "" + @@ -133,10 +133,29 @@ GarrisonHolder.prototype.Garrison = function(entity) /** * Simply eject the unit from the garrisoning entity without * moving it + * Returns true if successful, false if not */ -GarrisonHolder.prototype.Eject = function(entity) +GarrisonHolder.prototype.Eject = function(entity, forced) { var entityIndex = this.entities.indexOf(entity); + + // Find spawning location + var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); + var pos = cmpFootprint.PickSpawnPoint(entity); + if (pos.y < 0) + { + // Error: couldn't find space satisfying the unit's passability criteria + if (forced) + { // If ejection is forced, we need to continue, so use center of the building + var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); + pos = cmpPosition.GetPosition(); + } + else + { // Fail + return false; + } + } + this.spaceOccupied -= 1; this.entities.splice(entityIndex, 1); @@ -146,25 +165,11 @@ GarrisonHolder.prototype.Eject = function(entity) cmpUnitAI.Ungarrison(); } - var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint); - var pos = cmpFootprint.PickSpawnPoint(entity); - if (pos.y < 0) - { - // Whoops, something went wrong (maybe there wasn't any space to place the unit). - // What should we do here? - // For now, just move the unit into the middle of the building where it'll probably get stuck - var cmpPosition = Engine.QueryInterface(this.entity, IID_Position); - pos = cmpPosition.GetPosition(); - - var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); - var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to ungarrison unit"}; - var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); - cmpGUIInterface.PushNotification(notification); - } - var cmpNewPosition = Engine.QueryInterface(entity, IID_Position); cmpNewPosition.JumpTo(pos.x, pos.z); // TODO: what direction should they face in? + + return true; }; /** @@ -193,29 +198,51 @@ GarrisonHolder.prototype.OrderWalkToRallyPoint = function(entities) /** * Unload units from the garrisoning entity and order them * to move to the Rally Point + * Returns true if successful, false if not */ -GarrisonHolder.prototype.Unload = function(entity) +GarrisonHolder.prototype.Unload = function(entity, forced) { - this.Eject(entity); - this.OrderWalkToRallyPoint([entity]); - this.UpdateGarrisonFlag(); + if (this.Eject(entity, forced)) + { + this.OrderWalkToRallyPoint([entity]); + this.UpdateGarrisonFlag(); + return true; + } + + return false; }; /** * Unload all units from the entity + * Returns true if all successful, false if not */ -GarrisonHolder.prototype.UnloadAll = function() +GarrisonHolder.prototype.UnloadAll = function(forced) { - // The entities list is saved to a temporary variable - // because during each loop an element is removed - // from the list - var entities = this.entities.splice(0); + // Make copy of entity list + var entities = []; + for each (var entity in this.entities) + { + entities.push(entity); + } + + var ejectedEntities = []; + var success = true; for each (var entity in entities) { - this.Eject(entity); + if (this.Eject(entity, forced)) + { + ejectedEntities.push(entity); + } + else + { + success = false; + } } - this.OrderWalkToRallyPoint(entities); + + this.OrderWalkToRallyPoint(ejectedEntities); this.UpdateGarrisonFlag(); + + return success; }; /** @@ -226,7 +253,26 @@ GarrisonHolder.prototype.OnHealthChanged = function(msg) { if (!this.HasEnoughHealth()) { - this.UnloadAll(); + // We have to be careful of our passability + // ships: not land passable, so assume units have drowned in a shipwreck + // building: land passable, so units can be ejected freely + var classes = (Engine.QueryInterface(this.entity, IID_Identity)).GetClassesList(); + if (classes.indexOf("Ship") != -1) + { // Ship - kill all units + for each (var entity in this.entities) + { + var cmpHealth = Engine.QueryInterface(entity, IID_Health); + if (cmpHealth) + { + cmpHealth.Kill(); + } + } + this.entities = []; + } + else + { // Building - force ejection + this.UnloadAll(true); + } } }; @@ -302,19 +348,34 @@ GarrisonHolder.prototype.OnDestroy = function() */ GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg) { - if (this.entities.indexOf(msg.entity) != -1) + var entityIndex = this.entities.indexOf(msg.entity); + if (entityIndex != -1) { // If the entity is dead, remove it directly instead of ejecting the corpse var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health); if (cmpHealth && cmpHealth.GetHitpoints() == 0) { - this.entities.splice(this.entities.indexOf(msg.entity), 1); + this.entities.splice(entityIndex, 1); } else { - // Otherwise the unit probably got captured somehow and we don't want it - // any more, so eject it - this.Eject(msg.entity); + // We have to be careful of our passability + // ships: not land passable, assume unit was thrown overboard or something + // building: land passable, unit can be ejected freely + var classes = (Engine.QueryInterface(this.entity, IID_Identity)).GetClassesList(); + if (classes.indexOf("Ship") != -1) + { // Ship - kill unit + var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health); + if (cmpHealth) + { + cmpHealth.Kill(); + } + this.entities.splice(entityIndex, 1); + } + else + { // Building - force ejection + this.Eject(msg.entity, true); + } } } }; @@ -324,9 +385,10 @@ GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg) */ GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg) { - if (this.entities.indexOf(msg.entity) != -1) + var entityIndex = this.entities.indexOf(msg.entity); + if (entityIndex != -1) { - this.entities[this.entities.indexOf(msg.entity)] = msg.newentity; + this.entities[entityIndex] = msg.newentity; } }; diff --git a/binaries/data/mods/public/simulation/helpers/Commands.js b/binaries/data/mods/public/simulation/helpers/Commands.js index 9049fc0488..57dc2b9fb4 100644 --- a/binaries/data/mods/public/simulation/helpers/Commands.js +++ b/binaries/data/mods/public/simulation/helpers/Commands.js @@ -262,8 +262,13 @@ function ProcessCommand(player, cmd) if (CanControlUnit(cmd.garrisonHolder, player, controlAllUnits)) { var cmpGarrisonHolder = Engine.QueryInterface(cmd.garrisonHolder, IID_GarrisonHolder); - if (cmpGarrisonHolder) - cmpGarrisonHolder.Unload(cmd.entity); + if (!cmpGarrisonHolder || !cmpGarrisonHolder.Unload(cmd.entity)) + { + var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); + var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to ungarrison unit"}; + var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); + cmpGUIInterface.PushNotification(notification); + } } break; @@ -271,7 +276,13 @@ function ProcessCommand(player, cmd) if (CanControlUnit(cmd.garrisonHolder, player, controlAllUnits)) { var cmpGarrisonHolder = Engine.QueryInterface(cmd.garrisonHolder, IID_GarrisonHolder); - cmpGarrisonHolder.UnloadAll(); + if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadAll()) + { + var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); + var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to ungarrison all units"}; + var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); + cmpGUIInterface.PushNotification(notification); + } } break; diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml index 0a96b20a5a..215786b0c2 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml @@ -25,6 +25,7 @@ Ship + Ship diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml index 81e8a57f83..d2b9761c6e 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml @@ -30,9 +30,9 @@ 20 - 0.1 - Support Infantry Cavalry - 1 + 0 + Support Infantry Cavalry + 1 300 @@ -40,7 +40,7 @@ Light Warship Light Warship. - Warship + Warship diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml index 2b233ae736..70eb409e79 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml @@ -11,9 +11,9 @@ 1 - 0.1 - Support Infantry - 1 + 0 + Support Infantry + 1 Fishing Boat diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml index 2a547e6d82..df6ed9b403 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml @@ -13,9 +13,9 @@ 15 - 0.1 - Support Infantry Cavalry - 1 + 0 + Support Infantry Cavalry + 1 200 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml index 45caa31c39..ab1995868e 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml @@ -26,9 +26,9 @@ 50 - 0.1 - Support Infantry Cavalry Siege - 1 + 0 + Support Infantry Cavalry Siege + 1 500 @@ -36,7 +36,7 @@ Heavy Warship Heavy Warship. - Warship + Warship diff --git a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml index b9fa6d8442..8c007a7980 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml @@ -30,9 +30,9 @@ 30 - 0.1 - Support Infantry Cavalry Siege - 1 + 0 + Support Infantry Cavalry Siege + 1 400 @@ -40,7 +40,7 @@ Medium Warship Medium Warship. - Warship + Warship