This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

Changeset 10020 for ps


Ignore:
Timestamp:
08/17/11 03:43:23 (13 years ago)
Author:
ben
Message:

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.

Location:
ps/trunk/binaries/data/mods/public/simulation
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • ps/trunk/binaries/data/mods/public/simulation/components/GarrisonHolder.js

    r9970 r10020  
    1212    "</element>" +
    1313    "<element name='EjectHealth'>" +
    14         "<ref name='positiveDecimal'/>" +
     14        "<ref name='nonNegativeDecimal'/>" +
    1515    "</element>" +
    1616    "<element name='BuffHeal'>" +
     
    134134 * Simply eject the unit from the garrisoning entity without
    135135 * moving it
    136  */
    137 GarrisonHolder.prototype.Eject = function(entity)
     136 * Returns true if successful, false if not
     137 */
     138GarrisonHolder.prototype.Eject = function(entity, forced)
    138139{
    139140    var entityIndex = this.entities.indexOf(entity);
    140     this.spaceOccupied -= 1;
    141     this.entities.splice(entityIndex, 1);
    142    
    143     var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
    144     if (cmpUnitAI)
    145     {
    146         cmpUnitAI.Ungarrison();
    147     }
    148    
     141   
     142    // Find spawning location
    149143    var cmpFootprint = Engine.QueryInterface(this.entity, IID_Footprint);
    150144    var pos = cmpFootprint.PickSpawnPoint(entity);
    151145    if (pos.y < 0)
    152146    {
    153         // Whoops, something went wrong (maybe there wasn't any space to place the unit).
    154         // What should we do here?
    155         // For now, just move the unit into the middle of the building where it'll probably get stuck
    156         var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
    157         pos = cmpPosition.GetPosition();
    158        
    159         var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
    160         var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to ungarrison unit"};
    161         var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
    162         cmpGUIInterface.PushNotification(notification);
    163     }
    164 
     147        // Error: couldn't find space satisfying the unit's passability criteria
     148        if (forced)
     149        {   // If ejection is forced, we need to continue, so use center of the building
     150            var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
     151            pos = cmpPosition.GetPosition();
     152        }
     153        else
     154        {   // Fail
     155            return false;
     156        }
     157    }
     158   
     159    this.spaceOccupied -= 1;
     160    this.entities.splice(entityIndex, 1);
     161   
     162    var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
     163    if (cmpUnitAI)
     164    {
     165        cmpUnitAI.Ungarrison();
     166    }
     167   
    165168    var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
    166169    cmpNewPosition.JumpTo(pos.x, pos.z);
    167170    // TODO: what direction should they face in?
     171   
     172    return true;
    168173};
    169174
     
    194199 * Unload units from the garrisoning entity and order them
    195200 * to move to the Rally Point
    196  */
    197 GarrisonHolder.prototype.Unload = function(entity)
    198 {
    199     this.Eject(entity);
    200     this.OrderWalkToRallyPoint([entity]);
     201 * Returns true if successful, false if not
     202 */
     203GarrisonHolder.prototype.Unload = function(entity, forced)
     204{
     205    if (this.Eject(entity, forced))
     206    {
     207        this.OrderWalkToRallyPoint([entity]);
     208        this.UpdateGarrisonFlag();
     209        return true;
     210    }
     211   
     212    return false;
     213};
     214
     215/**
     216 * Unload all units from the entity
     217 * Returns true if all successful, false if not
     218 */
     219GarrisonHolder.prototype.UnloadAll = function(forced)
     220{
     221    // Make copy of entity list
     222    var entities = [];
     223    for each (var entity in this.entities)
     224    {
     225        entities.push(entity);
     226    }
     227   
     228    var ejectedEntities = [];
     229    var success = true;
     230    for each (var entity in entities)
     231    {
     232        if (this.Eject(entity, forced))
     233        {
     234            ejectedEntities.push(entity);
     235        }
     236        else
     237        {
     238            success = false;
     239        }
     240    }
     241   
     242    this.OrderWalkToRallyPoint(ejectedEntities);
    201243    this.UpdateGarrisonFlag();
    202 };
    203 
    204 /**
    205  * Unload all units from the entity
    206  */
    207 GarrisonHolder.prototype.UnloadAll = function()
    208 {
    209     // The entities list is saved to a temporary variable
    210     // because during each loop an element is removed
    211     // from the list
    212     var entities = this.entities.splice(0);
    213     for each (var entity in entities)
    214     {
    215         this.Eject(entity);
    216     }
    217     this.OrderWalkToRallyPoint(entities);
    218     this.UpdateGarrisonFlag();
     244   
     245    return success;
    219246};
    220247
     
    227254    if (!this.HasEnoughHealth())
    228255    {
    229         this.UnloadAll();
     256        // We have to be careful of our passability
     257        //  ships: not land passable, so assume units have drowned in a shipwreck
     258        //  building: land passable, so units can be ejected freely
     259        var classes = (Engine.QueryInterface(this.entity, IID_Identity)).GetClassesList();
     260        if (classes.indexOf("Ship") != -1)
     261        {   // Ship - kill all units
     262            for each (var entity in this.entities)
     263            {
     264                var cmpHealth = Engine.QueryInterface(entity, IID_Health);
     265                if (cmpHealth)
     266                {
     267                    cmpHealth.Kill();
     268                }
     269            }
     270            this.entities = [];
     271        }
     272        else
     273        {   // Building - force ejection
     274            this.UnloadAll(true);
     275        }
    230276    }
    231277};
     
    303349GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg)
    304350{
    305     if (this.entities.indexOf(msg.entity) != -1)
     351    var entityIndex = this.entities.indexOf(msg.entity);
     352    if (entityIndex != -1)
    306353    {
    307354        // If the entity is dead, remove it directly instead of ejecting the corpse
     
    309356        if (cmpHealth && cmpHealth.GetHitpoints() == 0)
    310357        {
    311             this.entities.splice(this.entities.indexOf(msg.entity), 1);
     358            this.entities.splice(entityIndex, 1);
    312359        }
    313360        else
    314361        {
    315             // Otherwise the unit probably got captured somehow and we don't want it
    316             // any more, so eject it
    317             this.Eject(msg.entity);
     362            // We have to be careful of our passability
     363            //  ships: not land passable, assume unit was thrown overboard or something
     364            //  building: land passable, unit can be ejected freely
     365            var classes = (Engine.QueryInterface(this.entity, IID_Identity)).GetClassesList();
     366            if (classes.indexOf("Ship") != -1)
     367            {   // Ship - kill unit
     368                var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health);
     369                if (cmpHealth)
     370                {
     371                    cmpHealth.Kill();
     372                }
     373                this.entities.splice(entityIndex, 1);
     374            }
     375            else
     376            {   // Building - force ejection
     377                this.Eject(msg.entity, true);
     378            }
    318379        }
    319380    }
     
    325386GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
    326387{
    327     if (this.entities.indexOf(msg.entity) != -1)
    328     {
    329         this.entities[this.entities.indexOf(msg.entity)] = msg.newentity;
     388    var entityIndex = this.entities.indexOf(msg.entity);
     389    if (entityIndex != -1)
     390    {
     391        this.entities[entityIndex] = msg.newentity;
    330392    }
    331393};
  • ps/trunk/binaries/data/mods/public/simulation/helpers/Commands.js

    r10008 r10020  
    263263        {
    264264            var cmpGarrisonHolder = Engine.QueryInterface(cmd.garrisonHolder, IID_GarrisonHolder);
    265             if (cmpGarrisonHolder)
    266                 cmpGarrisonHolder.Unload(cmd.entity);
     265            if (!cmpGarrisonHolder || !cmpGarrisonHolder.Unload(cmd.entity))
     266            {
     267                var cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
     268                var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to ungarrison unit"};
     269                var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     270                cmpGUIInterface.PushNotification(notification);
     271            }   
    267272        }
    268273        break;
     
    272277        {
    273278            var cmpGarrisonHolder = Engine.QueryInterface(cmd.garrisonHolder, IID_GarrisonHolder);
    274             cmpGarrisonHolder.UnloadAll();
     279            if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadAll())
     280            {
     281                var cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
     282                var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to ungarrison all units"};
     283                var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     284                cmpGUIInterface.PushNotification(notification);
     285            }
    275286        }
    276287        break;
  • ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml

    r10010 r10020  
    2626  <Identity>
    2727    <GenericName>Ship</GenericName>
     28    <Classes datatype="tokens">Ship</Classes>
    2829  </Identity>
    2930  <Obstruction>
  • ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml

    r10010 r10020  
    3131  <GarrisonHolder>
    3232    <Max>20</Max>
    33     <EjectHealth>0.1</EjectHealth>
    34     <List datatype="tokens">Support Infantry Cavalry</List>
    35     <BuffHeal>1</BuffHeal>
     33    <EjectHealth>0</EjectHealth>
     34    <List datatype="tokens">Support Infantry Cavalry</List>
     35    <BuffHeal>1</BuffHeal>
    3636  </GarrisonHolder>
    3737  <Health>
     
    4141    <GenericName>Light Warship</GenericName>
    4242    <Tooltip>Light Warship.</Tooltip>
    43     <Classes datatype="tokens">Warship</Classes>
     43    <Classes datatype="tokens">Warship</Classes>
    4444  </Identity>
    4545  <ResourceGatherer disable=""/>
  • ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml

    r10010 r10020  
    1212  <GarrisonHolder>
    1313    <Max>1</Max>
    14     <EjectHealth>0.1</EjectHealth>
    15     <List datatype="tokens">Support Infantry</List>
    16     <BuffHeal>1</BuffHeal>
     14    <EjectHealth>0</EjectHealth>
     15    <List datatype="tokens">Support Infantry</List>
     16    <BuffHeal>1</BuffHeal>
    1717  </GarrisonHolder>
    1818  <Identity>
  • ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml

    r9936 r10020  
    1414  <GarrisonHolder>
    1515    <Max>15</Max>
    16     <EjectHealth>0.1</EjectHealth>
    17     <List datatype="tokens">Support Infantry Cavalry</List>
    18     <BuffHeal>1</BuffHeal>
     16    <EjectHealth>0</EjectHealth>
     17    <List datatype="tokens">Support Infantry Cavalry</List>
     18    <BuffHeal>1</BuffHeal>
    1919  </GarrisonHolder>
    2020  <Health>
  • ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml

    r10010 r10020  
    2727  <GarrisonHolder>
    2828    <Max>50</Max>
    29     <EjectHealth>0.1</EjectHealth>
    30     <List datatype="tokens">Support Infantry Cavalry Siege</List>
    31     <BuffHeal>1</BuffHeal>
     29    <EjectHealth>0</EjectHealth>
     30    <List datatype="tokens">Support Infantry Cavalry Siege</List>
     31    <BuffHeal>1</BuffHeal>
    3232  </GarrisonHolder>
    3333  <Health>
     
    3737    <GenericName>Heavy Warship</GenericName>
    3838    <Tooltip>Heavy Warship.</Tooltip>
    39     <Classes datatype="tokens">Warship</Classes>
     39    <Classes datatype="tokens">Warship</Classes>
    4040  </Identity>
    4141  <ResourceGatherer disable=""/>
  • ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml

    r10010 r10020  
    3131  <GarrisonHolder>
    3232    <Max>30</Max>
    33     <EjectHealth>0.1</EjectHealth>
    34     <List datatype="tokens">Support Infantry Cavalry Siege</List>
    35     <BuffHeal>1</BuffHeal>
     33    <EjectHealth>0</EjectHealth>
     34    <List datatype="tokens">Support Infantry Cavalry Siege</List>
     35    <BuffHeal>1</BuffHeal>
    3636  </GarrisonHolder>
    3737  <Health>
     
    4141    <GenericName>Medium Warship</GenericName>
    4242    <Tooltip>Medium Warship.</Tooltip>
    43     <Classes datatype="tokens">Warship</Classes>
     43    <Classes datatype="tokens">Warship</Classes>
    4444  </Identity>
    4545  <ResourceGatherer disable=""/>
Note: See TracChangeset for help on using the changeset viewer.