Ticket #1807: garrison-v4.diff

File garrison-v4.diff, 23.0 KB (added by mimo, 11 years ago)
  • binaries/data/mods/public/gui/session/selection.js

     
    5959                continue;
    6060
    6161            var templateName = entState.template;
    62             var template = GetTemplateData(templateName);
    63             var key = template.selectionGroupName || templateName;
    64            
     62            if (templateName && templateName.indexOf("&") != -1)
     63            {
     64                var key = templateName;   // Garrisoned units have an extended template
     65            }
     66            else
     67            {
     68                var template = GetTemplateData(templateName);
     69                var key = template.selectionGroupName || templateName;
     70            }
     71
    6572            if (this.groups[key])
    6673                this.groups[key] += 1;
    6774            else
  • binaries/data/mods/public/gui/session/utility_functions.js

     
    6262            "teamsLocked": playerState.teamsLocked,
    6363            "state": playerState.state,
    6464            "isAlly": playerState.isAlly,
     65            "isMutualAlly": playerState.isMutualAlly,
    6566            "isNeutral": playerState.isNeutral,
    6667            "isEnemy": playerState.isEnemy,
    6768            "guid": undefined, // network guid for players controlled by hosts
  • binaries/data/mods/public/gui/session/input.js

     
    217217        var playerState = simState.players[entState.player];
    218218        var playerOwned = (targetState.player == entState.player);
    219219        var allyOwned = playerState.isAlly[targetState.player];
     220        var mutualAllyOwned = playerState.isMutualAlly[targetState.player];
    220221        var enemyOwned = playerState.isEnemy[targetState.player];
    221222        var gaiaOwned = (targetState.player == 0);
    222223
     
    225226
    226227        // default to walking there
    227228        var data = {command: "walk"};
    228         if (targetState.garrisonHolder && playerOwned)
     229        if (targetState.garrisonHolder && (playerOwned || mutualAllyOwned))
    229230        {
    230231            data.command = "garrison";
    231232            data.target = target;
     
    297298        var playerState = simState.players[entState.player];
    298299        var playerOwned = (targetState.player == entState.player);
    299300        var allyOwned = playerState.isAlly[targetState.player];
     301        var mutualAllyOwned = playerState.isMutualAlly[targetState.player];
    300302        var neutralOwned = playerState.isNeutral[targetState.player];
    301303        var enemyOwned = playerState.isEnemy[targetState.player];
    302304        var gaiaOwned = (targetState.player == 0);
     
    308310        switch (action)
    309311        {
    310312        case "garrison":
    311             if (hasClass(entState, "Unit") && targetState.garrisonHolder && playerOwned)
     313            if (hasClass(entState, "Unit") && targetState.garrisonHolder && (playerOwned || mutualAllyOwned))
    312314            {
    313315                var allowedClasses = targetState.garrisonHolder.allowedClasses;
    314316                for each (var unitClass in entState.identity.classes)
     
    17321734        var unitName = getEntityName(template);
    17331735
    17341736        var playerID = Engine.GetPlayerID();
     1737        var simState = Engine.GuiInterfaceCall("GetSimulationState");
     1738
    17351739        if (entState.player == playerID || g_DevSettings.controlAll)
    17361740        {
    17371741            switch (commandName)
     
    17801784                break;
    17811785            }
    17821786        }
     1787        else if (simState.players[playerID].isMutualAlly[entState.player])
     1788        {
     1789            switch (commandName)
     1790            {
     1791            case "garrison":
     1792                inputState = INPUT_PRESELECTEDACTION;
     1793                preSelectedAction = ACTION_GARRISON;
     1794                break;
     1795            default:
     1796                break;
     1797            }
     1798        }
    17831799    }
    17841800}
    17851801
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    689689                affordableMask.hidden = false;
    690690                affordableMask.sprite = "colour: 0 0 0 127";
    691691            }
     692
     693            if (guiName == GARRISON)
     694            {
     695                var ents = garrisonGroups.getEntsByName(item);
     696                var entplayer = GetEntityState(ents[0]).player;
     697                button.sprite = "colour: " + g_Players[entplayer].color.r + " " + g_Players[entplayer].color.g + " " + g_Players[entplayer].color.b;
     698
     699                var player = Engine.GetPlayerID();
     700                if(player != unitEntState.player && !g_DevSettings.controlAll)
     701                {
     702                    if (entplayer != player)
     703                    {
     704                        button.enabled = false;
     705                        grayscale = "grayscale:";
     706                    }
     707                }
     708            }
    692709           
    693710            icon.sprite = "stretched:" + grayscale + "session/portraits/" + template.icon;
    694711           
     
    10031020
    10041021    // If the selection is friendly units, add the command panels
    10051022    var player = Engine.GetPlayerID();
     1023    // Get player state to check some constraints
     1024    // e.g. presence of a hero or build limits
     1025    var simState = Engine.GuiInterfaceCall("GetSimulationState");
     1026    var playerState = simState.players[player];
     1027
    10061028    if (entState.player == player || g_DevSettings.controlAll)
    10071029    {
    1008         // Get player state to check some constraints
    1009         // e.g. presence of a hero or build limits
    1010         var simState = Engine.GuiInterfaceCall("GetSimulationState");
    1011         var playerState = simState.players[player];
    10121030
    10131031        if (selection.length > 1)
    10141032            setupUnitPanel(SELECTION, usedPanels, entState, playerState, g_Selection.groups.getTemplateNames(),
     
    10241042            var groups = new EntityGroups();
    10251043            for (var i in selection)
    10261044            {
    1027                 state = GetEntityState(selection[i]);
     1045                var state = GetEntityState(selection[i]);
    10281046                if (state.garrisonHolder)
    10291047                    groups.add(state.garrisonHolder.entities)
    10301048            }
     
    11911209        supplementalDetailsPanel.hidden = false;
    11921210        commandsPanel.hidden = false;
    11931211    }
     1212    else if (playerState.isMutualAlly[entState.player]) // owned by allied player
     1213    {
     1214
     1215        if (entState.garrisonHolder)
     1216        {
     1217            var groups = new EntityGroups();
     1218            for (var i in selection)
     1219            {
     1220                var state = GetEntityState(selection[i]);
     1221                if (state.garrisonHolder)
     1222                    groups.add(state.garrisonHolder.entities)
     1223            }
     1224
     1225            setupUnitPanel(GARRISON, usedPanels, entState, playerState, groups.getTemplateNames(),
     1226                function (item) { unloadTemplate(item); } );
     1227
     1228            supplementalDetailsPanel.hidden = false;
     1229        }
     1230        else
     1231        {
     1232            supplementalDetailsPanel.hidden = true;
     1233        }
     1234
     1235        commandsPanel.hidden = true;
     1236    }
    11941237    else // owned by another player
    11951238    {
    11961239        supplementalDetailsPanel.hidden = true;
  • binaries/data/mods/public/simulation/ai/common-api-v3/entity.js

     
    580580    unloadAll: function() {
    581581        if (!this._template.GarrisonHolder)
    582582            return undefined;
    583         Engine.PostCommand({"type": "unload-all", "garrisonHolders": [this.id()]});
     583        Engine.PostCommand({"type": "unload-all-own", "garrisonHolders": [this.id()]});
    584584        return this;
    585585    },
    586586
  • binaries/data/mods/public/simulation/helpers/Player.js

     
    214214    if (cmpOwnership)
    215215        owner = cmpOwnership.GetOwner();
    216216
    217     // Figure out which player controls the foundation being built
     217    // Figure out which player controls the target entity
    218218    var targetOwner = 0;
    219219    var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
    220220    if (cmpOwnershipTarget)
     
    231231}
    232232
    233233/**
     234 * Returns true if the entity 'target' is owned by a mutual ally of
     235 * the owner of 'entity'.
     236 */
     237function IsOwnedByMutualAllyOfEntity(entity, target)
     238{
     239    // Figure out which player controls us
     240    var owner = 0;
     241    var cmpOwnership = Engine.QueryInterface(entity, IID_Ownership);
     242    if (cmpOwnership)
     243        owner = cmpOwnership.GetOwner();
     244
     245    // Figure out which player controls the target entity
     246    var targetOwner = 0;
     247    var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
     248    if (cmpOwnershipTarget)
     249        targetOwner = cmpOwnershipTarget.GetOwner();
     250
     251    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     252    var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(owner), IID_Player);
     253
     254    // Check for allied diplomacy status
     255    if (cmpPlayer.IsMutualAlly(targetOwner))
     256        return true;
     257
     258    return false;
     259}
     260
     261/**
    234262 * Returns true if the entity 'target' is owned by player
    235263 */
    236264function IsOwnedByPlayer(player, target)
     
    269297}
    270298
    271299/**
     300 * Returns true if the entity 'target' is owned by a mutual ally of player
     301 */
     302function IsOwnedByMutualAllyOfPlayer(player, target)
     303{
     304    var targetOwner = 0;
     305    var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
     306    if (cmpOwnershipTarget)
     307        targetOwner = cmpOwnershipTarget.GetOwner();
     308
     309    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     310    var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player);
     311
     312    // Check for allied diplomacy status
     313    if (cmpPlayer.IsMutualAlly(targetOwner))
     314        return true;
     315
     316    return false;
     317}
     318
     319/**
    272320 * Returns true if the entity 'target' is owned by someone neutral to player
    273321 */
    274322function IsOwnedByNeutralOfPlayer(player,target)
     
    312360Engine.RegisterGlobal("QueryOwnerInterface", QueryOwnerInterface);
    313361Engine.RegisterGlobal("QueryPlayerIDInterface", QueryPlayerIDInterface);
    314362Engine.RegisterGlobal("IsOwnedByAllyOfEntity", IsOwnedByAllyOfEntity);
     363Engine.RegisterGlobal("IsOwnedByMutualAllyOfEntity", IsOwnedByMutualAllyOfEntity);
    315364Engine.RegisterGlobal("IsOwnedByPlayer", IsOwnedByPlayer);
    316365Engine.RegisterGlobal("IsOwnedByGaia", IsOwnedByGaia);
    317366Engine.RegisterGlobal("IsOwnedByAllyOfPlayer", IsOwnedByAllyOfPlayer);
     367Engine.RegisterGlobal("IsOwnedByMutualAllyOfPlayer", IsOwnedByMutualAllyOfPlayer);
    318368Engine.RegisterGlobal("IsOwnedByNeutralOfPlayer", IsOwnedByNeutralOfPlayer);
    319369Engine.RegisterGlobal("IsOwnedByEnemyOfPlayer", IsOwnedByEnemyOfPlayer);
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    314314        break;
    315315
    316316    case "garrison":
    317         // Verify that the building can be controlled by the player
    318         if (CanControlUnit(cmd.target, player, controlAllUnits))
     317        // Verify that the building can be controlled by the player or is mutualAlly
     318        if (CanControlUnitOrIsAlly(cmd.target, player, controlAllUnits))
    319319        {
    320320            var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
    321321            GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
     
    336336        break;
    337337
    338338    case "unload":
    339         // Verify that the building can be controlled by the player
    340         if (CanControlUnit(cmd.garrisonHolder, player, controlAllUnits))
     339        // Verify that the building can be controlled by the player or is mutualAlly
     340        if (CanControlUnitOrIsAlly(cmd.garrisonHolder, player, controlAllUnits))
    341341        {
    342342            var cmpGarrisonHolder = Engine.QueryInterface(cmd.garrisonHolder, IID_GarrisonHolder);
    343343            var notUngarrisoned = 0;
    344             for each (ent in cmd.entities)
     344            if (IsOwnedByPlayer(player, cmd.garrisonHolder))
     345                var entities = cmd.entities;
     346            else
     347                var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     348
     349            for each (var ent in entities)
    345350                if (!cmpGarrisonHolder || !cmpGarrisonHolder.Unload(ent))
    346351                    notUngarrisoned++;
    347352
     
    355360        break;
    356361
    357362    case "unload-template":
     363        var index = cmd.template.indexOf("&");  // Templates for garrisoned units are extended
     364        if (index == -1)
     365            break;
     366        var selected = FilterEntityListWithAllies(cmd.garrisonHolders, player, controlAllUnits);
     367        for each (var garrisonHolder in selected)
     368        {
     369            var cmpGarrisonHolder = Engine.QueryInterface(garrisonHolder, IID_GarrisonHolder);
     370            if (cmpGarrisonHolder)
     371            {
     372                // Only the owner of the garrisonHolder may unload entities from any owners
     373                if (!IsOwnedByPlayer(player, garrisonHolder) && !controlAllUnits)
     374                {
     375                    if (player != +(cmd.template.slice(1,index)))
     376                        continue;
     377                }
     378                if (!cmpGarrisonHolder.UnloadTemplate(cmd.template, cmd.all))
     379                    notifyUnloadFailure(player, garrisonHolder);
     380            }
     381        }
     382        break;
     383
     384    case "unload-all-own":
    358385        var selected = FilterEntityList(cmd.garrisonHolders, player, controlAllUnits);
    359386        for each (var garrisonHolder in selected)
    360387        {
    361388            var cmpGarrisonHolder = Engine.QueryInterface(garrisonHolder, IID_GarrisonHolder);
    362             if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadTemplate(cmd.template, cmd.all))
     389            if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadAllOwn())
    363390                notifyUnloadFailure(player, garrisonHolder)
    364391        }
    365392        break;
     
    12721299
    12731300/**
    12741301 * Check if player can control this entity
    1275  * returns: true if the entity is valid and owned by the player if
    1276  *      or control all units is activated for the player, else false
     1302 * returns: true if the entity is valid and owned by the player
     1303 *      or control all units is activated, else false
    12771304 */
    12781305function CanControlUnit(entity, player, controlAll)
    12791306{
     
    12811308}
    12821309
    12831310/**
     1311 * Check if player can control this entity
     1312 * returns: true if the entity is valid and owned by the player
     1313 *              or  the entity is owned by an mutualAlly
     1314 *      or control all units is activated, else false
     1315 */
     1316function CanControlUnitOrIsAlly(entity, player, controlAll)
     1317{
     1318    return (IsOwnedByPlayer(player, entity) || IsOwnedByMutualAllyOfPlayer(player, entity) || controlAll);
     1319}
     1320
     1321/**
    12841322 * Filter entities which the player can control
    12851323 */
    12861324function FilterEntityList(entities, player, controlAll)
     
    12891327}
    12901328
    12911329/**
     1330 * Filter entities which the player can control or are mutualAlly
     1331 */
     1332function FilterEntityListWithAllies(entities, player, controlAll)
     1333{
     1334    return entities.filter(function(ent) { return CanControlUnitOrIsAlly(ent, player, controlAll);} );
     1335}
     1336
     1337/**
    12921338 * Try to transform a wall to a gate
    12931339 */
    12941340function TryTransformWallToGate(ent, cmpPlayer, template)
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    6464       
    6565        // store player ally/neutral/enemy data as arrays
    6666        var allies = [];
     67        var mutualAllies = [];
    6768        var neutrals = [];
    6869        var enemies = [];
    6970        for (var j = 0; j < n; ++j)
    7071        {
    7172            allies[j] = cmpPlayer.IsAlly(j);
     73            mutualAllies[j] = cmpPlayer.IsMutualAlly(j);
    7274            neutrals[j] = cmpPlayer.IsNeutral(j);
    7375            enemies[j] = cmpPlayer.IsEnemy(j);
    7476        }
     
    8688            "teamsLocked": cmpPlayer.GetLockTeams(),
    8789            "phase": phase,
    8890            "isAlly": allies,
     91            "isMutualAlly": mutualAllies,
    8992            "isNeutral": neutrals,
    9093            "isEnemy": enemies,
    9194            "entityLimits": cmpPlayerEntityLimits.GetLimits(),
     
    313316            "state": cmpUnitAI.GetCurrentState(),
    314317            "orders": cmpUnitAI.GetOrders(),
    315318        };
     319        // Special extended template for garrisoned units
     320        if (cmpUnitAI.isGarrisoned && ret.player)
     321            ret.template = "p" + ret.player + "&" + ret.template;
    316322    }
    317323   
    318324    var cmpGate = Engine.QueryInterface(ent, IID_Gate);
     
    344350    return ret;
    345351};
    346352
    347 GuiInterface.prototype.GetTemplateData = function(player, name)
     353GuiInterface.prototype.GetTemplateData = function(player, extendedName)
    348354{
     355    var name = extendedName;
     356    // Special case for garrisoned units which have a extended template
     357    if (extendedName.indexOf("&") != -1)
     358        name = extendedName.slice(extendedName.indexOf("&")+1);
     359
    349360    var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
    350361    var template = cmpTemplateManager.GetTemplate(name);
    351362
     
    522533    return ret;
    523534};
    524535
    525 GuiInterface.prototype.GetTechnologyData = function(player, name)
     536GuiInterface.prototype.GetTechnologyData = function(player, extendedName)
    526537{
     538    var name = extendedName;
     539    // Special case for garrisoned units which have an extended template
     540    // (does not need technology for now, but we never know)
     541    if (extendedName.indexOf("&") != -1)
     542        name = extendedName.slice(extendedName.indexOf("&")+1);
     543
    527544    var cmpTechTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager);
    528545    var template = cmpTechTempMan.GetTemplate(name);
    529546   
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    42474247    if (!cmpGarrisonHolder)
    42484248        return false;
    42494249
    4250     // Verify that the target is owned by this entity's player
     4250    // Verify that the target is owned by this entity's player or is mutual allied
    42514251    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
    4252     if (!cmpOwnership || !IsOwnedByPlayer(cmpOwnership.GetOwner(), target))
     4252    if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByMutualAllyOfPlayer(cmpOwnership.GetOwner(), target)))
    42534253        return false;
    42544254
    42554255    // Don't let animals garrison for now
  • binaries/data/mods/public/simulation/components/Player.js

     
    351351
    352352    var sharedLos = [];
    353353    for (var i = 0; i < cmpPlayerManager.GetNumPlayers(); ++i)
    354         if (this.IsAlly(i))
    355         {
    356             var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(i), IID_Player);
    357             if (cmpPlayer && cmpPlayer.IsAlly(this.playerID))
    358                 sharedLos.push(i);
    359         }
     354        if (this.IsMutualAlly(i))
     355            sharedLos.push(i);
    360356
    361357    cmpRangeManager.SetSharedLos(this.playerID, sharedLos);
    362358};
     
    424420    return this.diplomacy[id] > 0;
    425421};
    426422
     423/**
     424 * Check if given player is our ally, and we are its ally
     425 */
     426Player.prototype.IsMutualAlly = function(id)
     427{
     428    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     429    if (!cmpPlayerManager)
     430        return false;
     431    var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(id), IID_Player);
     432    return this.IsAlly(id) && cmpPlayer && cmpPlayer.IsAlly(this.playerID);
     433};
     434
    427435Player.prototype.SetEnemy = function(id)
    428436{
    429437    this.SetDiplomacyIndex(id, -1);
  • binaries/data/mods/public/simulation/components/GarrisonHolder.js

     
    220220};
    221221
    222222/**
     223 * Perform Eject on the selected entities
     224 */
     225GarrisonHolder.prototype.PerformEject = function(entities, forced)
     226{
     227    var ejectedEntities = [];
     228    var success = true;
     229    for each (var entity in entities)
     230    {
     231        if (this.Eject(entity, forced))
     232        {
     233            ejectedEntities.push(entity);
     234        }
     235        else
     236        {
     237            success = false;
     238        }
     239    }
     240   
     241    this.OrderWalkToRallyPoint(ejectedEntities);
     242    this.UpdateGarrisonFlag();
     243   
     244    return success;
     245};
     246
     247/**
    223248 * Unload units from the garrisoning entity and order them
    224249 * to move to the Rally Point
    225250 * Returns true if successful, false if not
    226251 */
    227252GarrisonHolder.prototype.Unload = function(entity, forced)
    228253{
    229     if (this.Eject(entity, forced))
    230     {
    231         this.OrderWalkToRallyPoint([entity]);
    232         this.UpdateGarrisonFlag();
    233         return true;
    234     }
    235    
    236     return false;
     254    return this.PerformEject([entity], forced);
    237255};
    238256
    239257/**
    240  * Unload one or all units that match a template from the
     258 * Unload one or all units that match a template/owner from the
    241259 * garrisoning entity and order them to move to the Rally Point
    242260 * Returns true if successful, false if not
    243261 */
    244 GarrisonHolder.prototype.UnloadTemplate = function(template, all, forced)
     262GarrisonHolder.prototype.UnloadTemplate = function(extendedTemplate, all, forced)
    245263{
    246     var ejectedEntities = [];
    247     var success = true;
     264    var index = extendedTemplate.indexOf("&");
     265    if (index == -1)
     266        return false;
     267    var owner = extendedTemplate.slice(1,index);
     268    var template = extendedTemplate.slice(index+1);
     269
     270    var entities = [];
    248271    for (var i = 0; i < this.entities.length; ++i)
    249272    {
    250273        var entity = this.entities[i];
     
    260283       
    261284        if (name != template)
    262285            continue;
     286        if (owner != Engine.QueryInterface(entity, IID_Ownership).GetOwner())
     287            continue;
    263288
    264         if (this.Eject(entity, forced))
    265         {
    266             --i; // Decrement 'i' as Eject() shortens the array.
    267             ejectedEntities.push(entity);
     289        entities.push(entity);
    268290
    269             // If 'all' is false, only ungarrison the first matched unit.
    270             if (!all)
    271                 break;
    272         }
    273         else
    274             success = false;
     291        // If 'all' is false, only ungarrison the first matched unit.
     292        if (!all)
     293            break;
    275294    }
    276295
    277     this.OrderWalkToRallyPoint(ejectedEntities);
    278     this.UpdateGarrisonFlag();
    279 
    280     return success;
     296    return this.PerformEject(entities, forced);
    281297};
    282298
    283299/**
    284  * Unload all units from the entity
     300 * Unload all units with same owner than the entity
    285301 * Returns true if all successful, false if not
    286302 */
    287 GarrisonHolder.prototype.UnloadAll = function(forced)
     303GarrisonHolder.prototype.UnloadAllOwn = function(forced)
    288304{
     305    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     306    if (!cmpOwnership)
     307        return false;
     308    var owner = cmpOwnership.GetOwner();
     309
    289310    // Make copy of entity list
    290311    var entities = [];
    291312    for each (var entity in this.entities)
    292313    {
    293         entities.push(entity);
     314        var cmpOwnership = Engine.QueryInterface(entity, IID_Ownership);
     315        if (cmpOwnership && cmpOwnership.GetOwner() == owner)
     316            entities.push(entity);
    294317    }
    295318   
    296     var ejectedEntities = [];
    297     var success = true;
    298     for each (var entity in entities)
    299     {
    300         if (this.Eject(entity, forced))
    301         {
    302             ejectedEntities.push(entity);
    303         }
    304         else
    305         {
    306             success = false;
    307         }
    308     }
    309    
    310     this.OrderWalkToRallyPoint(ejectedEntities);
    311     this.UpdateGarrisonFlag();
    312    
    313     return success;
     319    return this.PerformEject(entities, forced);
    314320};
    315321
    316322/**
     323 * Unload all units from the entity
     324 * Returns true if all successful, false if not
     325 */
     326GarrisonHolder.prototype.UnloadAll = function(forced)
     327{
     328    var entities = this.entities.slice(0);
     329    return this.PerformEject(entities, forced);
     330};
     331
     332/**
    317333 * Used to check if the garrisoning entity's health has fallen below
    318334 * a certain limit after which all garrisoned units are unloaded
    319335 */
     
    469485    }
    470486};
    471487
     488
     489/**
     490 * Eject all foreign garrisoned entities which are no more allied
     491 */
     492GarrisonHolder.prototype.OnDiplomacyChanged = function()
     493{
     494    for (var i = this.entities.length; i > 0; --i)
     495    {
     496        if (!IsOwnedByMutualAllyOfEntity(this.entity, this.entities[i-1]))
     497            this.Eject(this.entities[i-1], true);
     498    }
     499    this.UpdateGarrisonFlag();
     500};
     501
    472502Engine.RegisterComponentType(IID_GarrisonHolder, "GarrisonHolder", GarrisonHolder);
    473503