Ticket #1807: garrison.patch

File garrison.patch, 24.1 KB (added by mimo, 11 years ago)
  • 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

     
    206206        var playerState = simState.players[entState.player];
    207207        var playerOwned = (targetState.player == entState.player);
    208208        var allyOwned = playerState.isAlly[targetState.player];
     209        var mutualAllyOwned = playerState.isMutualAlly[targetState.player];
    209210        var enemyOwned = playerState.isEnemy[targetState.player];
    210211        var gaiaOwned = (targetState.player == 0);
    211212
     
    214215
    215216        // default to walking there
    216217        var data = {command: "walk"};
    217         if (targetState.garrisonHolder && playerOwned)
     218        if (targetState.garrisonHolder && (playerOwned || mutualAllyOwned))
    218219        {
    219220            data.command = "garrison";
    220221            data.target = target;
     
    286287        var playerState = simState.players[entState.player];
    287288        var playerOwned = (targetState.player == entState.player);
    288289        var allyOwned = playerState.isAlly[targetState.player];
     290        var mutualAllyOwned = playerState.isMutualAlly[targetState.player];
    289291        var neutralOwned = playerState.isNeutral[targetState.player];
    290292        var enemyOwned = playerState.isEnemy[targetState.player];
    291293        var gaiaOwned = (targetState.player == 0);
     
    297299        switch (action)
    298300        {
    299301        case "garrison":
    300             if (hasClass(entState, "Unit") && targetState.garrisonHolder && playerOwned)
     302            if (hasClass(entState, "Unit") && targetState.garrisonHolder && (playerOwned || mutualAllyOwned))
    301303            {
    302304                var allowedClasses = targetState.garrisonHolder.allowedClasses;
    303305                for each (var unitClass in entState.identity.classes)
     
    16771679        var unitName = getEntityName(template);
    16781680
    16791681        var playerID = Engine.GetPlayerID();
     1682        var simState = Engine.GuiInterfaceCall("GetSimulationState");
     1683
    16801684        if (entState.player == playerID || g_DevSettings.controlAll)
    16811685        {
    16821686            switch (commandName)
     
    17251729                break;
    17261730            }
    17271731        }
     1732        else if (simState.players[playerID].isMutualAlly[entState.player])
     1733        {
     1734            switch (commandName)
     1735            {
     1736            case "garrison":
     1737                inputState = INPUT_PRESELECTEDACTION;
     1738                preSelectedAction = ACTION_GARRISON;
     1739                break;
     1740            //case "unload-all":
     1741            //  unloadAll();
     1742            //  break;
     1743            default:
     1744                break;
     1745            }
     1746        }
    17281747    }
    17291748}
    17301749
  • binaries/data/mods/public/gui/session/unit_commands.js

     
    670670                button.tooltip += "\n" + GetTechnologyData(entType).requirementsTooltip;
    671671                grayscale = "grayscale:";
    672672            }
     673
     674            if (guiName == GARRISON)
     675            {
     676                var ents = garrisonGroups.getEntsByName(item);
     677                var entplayer = GetEntityState(ents[0]).player;
     678                button.sprite = "colour: " + g_Players[entplayer].color.r + " " + g_Players[entplayer].color.g + " " + g_Players[entplayer].color.b;
     679
     680                var player = Engine.GetPlayerID();
     681                if(player != unitEntState.player && !g_DevSettings.controlAll)
     682                {
     683                    if (entplayer != player)
     684                    {
     685                        button.enabled = false;
     686                        grayscale = "grayscale:";
     687                    }
     688                }
     689            }
    673690           
    674691            icon.sprite = "stretched:" + grayscale + "session/portraits/" + template.icon;
    675692           
     
    964981
    965982    // If the selection is friendly units, add the command panels
    966983    var player = Engine.GetPlayerID();
    967     if (entState.player == player || g_DevSettings.controlAll)
    968     {
    969         // Get player state to check some constraints
    970         // e.g. presence of a hero or build limits
    971         var simState = Engine.GuiInterfaceCall("GetSimulationState");
    972         var playerState = simState.players[player];
     984    // Get player state to check some constraints
     985    // e.g. presence of a hero or build limits
     986    var simState = Engine.GuiInterfaceCall("GetSimulationState");
     987    var playerState = simState.players[player];
    973988
     989    if (entState.player == player || g_DevSettings.controlAll)
     990    {
     991
    974992        if (selection.length > 1)
    975993            setupUnitPanel(SELECTION, usedPanels, entState, playerState, g_Selection.groups.getTemplateNames(),
    976994                function (entType) { changePrimarySelectionGroup(entType); } );
     
    9851003            var groups = new EntityGroups();
    9861004            for (var i in selection)
    9871005            {
    988                 state = GetEntityState(selection[i]);
     1006                var state = GetEntityState(selection[i]);
    9891007                if (state.garrisonHolder)
    9901008                    groups.add(state.garrisonHolder.entities)
    9911009            }
     
    11521170        supplementalDetailsPanel.hidden = false;
    11531171        commandsPanel.hidden = false;
    11541172    }
     1173    else if (playerState.isMutualAlly[entState.player]) // owned by allied player
     1174    {
     1175
     1176        if (entState.garrisonHolder)
     1177        {
     1178            var groups = new EntityGroups();
     1179            for (var i in selection)
     1180            {
     1181                var state = GetEntityState(selection[i]);
     1182                if (state.garrisonHolder)
     1183                    groups.add(state.garrisonHolder.entities)
     1184            }
     1185
     1186            setupUnitPanel(GARRISON, usedPanels, entState, playerState, groups.getTemplateNames(),
     1187                function (item) { unloadTemplate(item); } );
     1188
     1189            supplementalDetailsPanel.hidden = false;
     1190        }
     1191        else
     1192        {
     1193            supplementalDetailsPanel.hidden = true;
     1194        }
     1195
     1196        commandsPanel.hidden = true;
     1197    }
    11551198    else // owned by another player
    11561199    {
    11571200        supplementalDetailsPanel.hidden = true;
  • binaries/data/mods/public/simulation/helpers/Player.js

     
    207207    if (cmpOwnership)
    208208        owner = cmpOwnership.GetOwner();
    209209
    210     // Figure out which player controls the foundation being built
     210    // Figure out which player controls the target entity
    211211    var targetOwner = 0;
    212212    var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
    213213    if (cmpOwnershipTarget)
     
    224224}
    225225
    226226/**
     227 * Returns true if the entity 'target' is owned by a mutual ally of
     228 * the owner of 'entity'.
     229 */
     230function IsOwnedByMutualAllyOfEntity(entity, target)
     231{
     232    // Figure out which player controls us
     233    var owner = 0;
     234    var cmpOwnership = Engine.QueryInterface(entity, IID_Ownership);
     235    if (cmpOwnership)
     236        owner = cmpOwnership.GetOwner();
     237
     238    // Figure out which player controls the target entity
     239    var targetOwner = 0;
     240    var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
     241    if (cmpOwnershipTarget)
     242        targetOwner = cmpOwnershipTarget.GetOwner();
     243
     244    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     245    var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(owner), IID_Player);
     246
     247    // Check for allied diplomacy status
     248    if (cmpPlayer.IsMutualAlly(targetOwner))
     249        return true;
     250
     251    return false;
     252}
     253
     254/**
    227255 * Returns true if the entity 'target' is owned by player
    228256 */
    229257function IsOwnedByPlayer(player, target)
     
    262290}
    263291
    264292/**
     293 * Returns true if the entity 'target' is owned by a mutual ally of player
     294 */
     295function IsOwnedByMutualAllyOfPlayer(player, target)
     296{
     297    var targetOwner = 0;
     298    var cmpOwnershipTarget = Engine.QueryInterface(target, IID_Ownership);
     299    if (cmpOwnershipTarget)
     300        targetOwner = cmpOwnershipTarget.GetOwner();
     301
     302    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     303    var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(player), IID_Player);
     304
     305    // Check for allied diplomacy status
     306    if (cmpPlayer.IsMutualAlly(targetOwner))
     307        return true;
     308
     309    return false;
     310}
     311
     312/**
    265313 * Returns true if the entity 'target' is owned by someone neutral to player
    266314 */
    267315function IsOwnedByNeutralOfPlayer(player,target)
     
    305353Engine.RegisterGlobal("QueryOwnerInterface", QueryOwnerInterface);
    306354Engine.RegisterGlobal("QueryPlayerIDInterface", QueryPlayerIDInterface);
    307355Engine.RegisterGlobal("IsOwnedByAllyOfEntity", IsOwnedByAllyOfEntity);
     356Engine.RegisterGlobal("IsOwnedByMutualAllyOfEntity", IsOwnedByMutualAllyOfEntity);
    308357Engine.RegisterGlobal("IsOwnedByPlayer", IsOwnedByPlayer);
    309358Engine.RegisterGlobal("IsOwnedByGaia", IsOwnedByGaia);
    310359Engine.RegisterGlobal("IsOwnedByAllyOfPlayer", IsOwnedByAllyOfPlayer);
     360Engine.RegisterGlobal("IsOwnedByMutualAllyOfPlayer", IsOwnedByMutualAllyOfPlayer);
    311361Engine.RegisterGlobal("IsOwnedByNeutralOfPlayer", IsOwnedByNeutralOfPlayer);
    312362Engine.RegisterGlobal("IsOwnedByEnemyOfPlayer", IsOwnedByEnemyOfPlayer);
  • binaries/data/mods/public/simulation/helpers/Commands.js

     
    8282        break;
    8383
    8484    case "walk":
    85         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     85        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    8686        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    8787            cmpUnitAI.Walk(cmd.x, cmd.z, cmd.queued);
    8888        });
     
    9696        }
    9797
    9898        // See UnitAI.CanAttack for target checks
    99         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     99        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    100100        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    101101            cmpUnitAI.Attack(cmd.target, cmd.queued);
    102102        });
     
    109109            warn("Invalid command: heal target is not owned by player "+player+" or their ally: "+uneval(cmd));
    110110        }
    111111
    112         // See UnitAI.CanHeal for target checks
    113         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     112        // See UnitAI.CanHeal for target checks TODO may-be the includeMutualAllies should be set to true in FilterEntityList
     113        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    114114        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    115115            cmpUnitAI.Heal(cmd.target, cmd.queued);
    116116        });
     
    124124            warn("Invalid command: repair target is not owned by ally of player "+player+": "+uneval(cmd));
    125125        }
    126126
    127         // See UnitAI.CanRepair for target checks
    128         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     127        // See UnitAI.CanRepair for target checks TODO may-be the includeMutualAllies should be set to true in FilterEntityList
     128        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    129129        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    130130            cmpUnitAI.Repair(cmd.target, cmd.autocontinue, cmd.queued);
    131131        });
     
    139139        }
    140140
    141141        // See UnitAI.CanGather for target checks
    142         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     142        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    143143        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    144144            cmpUnitAI.Gather(cmd.target, cmd.queued);
    145145        });
    146146        break;
    147147       
    148148    case "gather-near-position":
    149         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     149        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    150150        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    151151            cmpUnitAI.GatherNearPosition(cmd.x, cmd.z, cmd.resourceType, cmd.resourceTemplate, cmd.queued);
    152152        });
     
    161161        }
    162162
    163163        // See UnitAI.CanReturnResource for target checks
    164         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     164        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    165165        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    166166            cmpUnitAI.ReturnResource(cmd.target, cmd.queued);
    167167        });
    168168        break;
    169169
    170170    case "train":
    171         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     171        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    172172       
    173173        // Check entity limits
    174174        var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
     
    216216
    217217    case "research":
    218218        // Verify that the building can be controlled by the player
    219         if (CanControlUnit(cmd.entity, player, controlAllUnits))
     219        if (CanControlUnit(cmd.entity, player, false, controlAllUnits))
    220220        {
    221221            var cmpTechnologyManager = QueryOwnerInterface(cmd.entity, IID_TechnologyManager);
    222222            // TODO: Enable this check once the AI gets technology support
     
    239239
    240240    case "stop-production":
    241241        // Verify that the building can be controlled by the player
    242         if (CanControlUnit(cmd.entity, player, controlAllUnits))
     242        if (CanControlUnit(cmd.entity, player, false, controlAllUnits))
    243243        {
    244244            var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue);
    245245            if (queue)
     
    260260        break;
    261261
    262262    case "delete-entities":
    263         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     263        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    264264        for each (var ent in entities)
    265265        {
    266266            var cmpHealth = Engine.QueryInterface(ent, IID_Health);
     
    276276        break;
    277277
    278278    case "set-rallypoint":
    279         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     279        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    280280        for each (var ent in entities)
    281281        {
    282282            var cmpRallyPoint = Engine.QueryInterface(ent, IID_RallyPoint);
     
    292292        break;
    293293
    294294    case "unset-rallypoint":
    295         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     295        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    296296        for each (var ent in entities)
    297297        {
    298298            var cmpRallyPoint = Engine.QueryInterface(ent, IID_RallyPoint);
     
    308308
    309309    case "garrison":
    310310        // Verify that the building can be controlled by the player
    311         if (CanControlUnit(cmd.target, player, controlAllUnits))
     311        if (CanControlUnit(cmd.target, player, true, controlAllUnits))
    312312        {
    313             var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     313            var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    314314            GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    315315                cmpUnitAI.Garrison(cmd.target, cmd.queued);
    316316            });
     
    322322        break;
    323323
    324324    case "stop":
    325         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     325        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    326326        GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) {
    327327            cmpUnitAI.Stop(cmd.queued);
    328328        });
     
    330330
    331331    case "unload":
    332332        // Verify that the building can be controlled by the player
    333         if (CanControlUnit(cmd.garrisonHolder, player, controlAllUnits))
     333        if (CanControlUnit(cmd.garrisonHolder, player, true, controlAllUnits))
    334334        {
    335335            var cmpGarrisonHolder = Engine.QueryInterface(cmd.garrisonHolder, IID_GarrisonHolder);
    336336            var notUngarrisoned = 0;
    337             for each (ent in cmd.entities)
     337            var entities = FilterEntityList(cmd.entities, player, IsOwnedByPlayer(player, cmd.garrisonHolder), controlAllUnits);
     338            for each (var ent in entities)
    338339                if (!cmpGarrisonHolder || !cmpGarrisonHolder.Unload(ent))
    339340                    notUngarrisoned++;
    340341
     
    348349        break;
    349350
    350351    case "unload-template":
    351         var selected = FilterEntityList(cmd.garrisonHolders, player, controlAllUnits);
     352        var selected = FilterEntityList(cmd.garrisonHolders, player, true, controlAllUnits);
     353        var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
    352354        for each (var garrisonHolder in selected)
    353355        {
    354356            var cmpGarrisonHolder = Engine.QueryInterface(garrisonHolder, IID_GarrisonHolder);
    355             if (!cmpGarrisonHolder || !cmpGarrisonHolder.UnloadTemplate(cmd.template, cmd.all))
    356                 notifyUnloadFailure(player, garrisonHolder)
     357            if (cmpGarrisonHolder)
     358            {
     359                // check that we are allowed to unload entities corresponding to this template
     360                var entities = FilterEntityList(cmpGarrisonHolder.entities, player, IsOwnedByPlayer(player, garrisonHolder), controlAllUnits);
     361                for each (var ent in entities)
     362                {
     363                    // Units with multiple ranks are grouped together.
     364                    var cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
     365                    var name = cmpIdentity.GetSelectionGroupName();
     366                    if (!name)
     367                        name = cmpTemplateManager.GetCurrentTemplateName(ent);
     368                    if (name == cmd.template)
     369                    {
     370                        if (!cmpGarrisonHolder.UnloadTemplate(cmd.template, cmd.all))
     371                            notifyUnloadFailure(player, garrisonHolder);
     372                        break;
     373                    }
     374                }
     375            }
    357376        }
    358377        break;
    359378
    360379    case "unload-all":
    361         var selected = FilterEntityList(cmd.garrisonHolders, player, controlAllUnits);
     380        var selected = FilterEntityList(cmd.garrisonHolders, player, false, controlAllUnits);
    362381        for each (var garrisonHolder in selected)
    363382        {
    364383            var cmpGarrisonHolder = Engine.QueryInterface(garrisonHolder, IID_GarrisonHolder);
     
    368387        break;
    369388
    370389    case "formation":
    371         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     390        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    372391        GetFormationUnitAIs(entities, player, cmd.name).forEach(function(cmpUnitAI) {
    373392            cmpUnitAI.MoveIntoFormation(cmd);
    374393        });
     
    388407        break;
    389408
    390409    case "stance":
    391         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     410        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    392411        for each (var ent in entities)
    393412        {
    394413            var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     
    398417        break;
    399418
    400419    case "wall-to-gate":
    401         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     420        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    402421        for each (var ent in entities)
    403422        {
    404423            TryTransformWallToGate(ent, cmpPlayer, cmd.template);
     
    406425        break;
    407426
    408427    case "lock-gate":
    409         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     428        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    410429        for each (var ent in entities)
    411430        {
    412431            var cmpGate = Engine.QueryInterface(ent, IID_Gate);
     
    454473        break;
    455474
    456475    case "pack":
    457         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     476        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    458477        for each (var ent in entities)
    459478        {
    460479            var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     
    469488        break;
    470489
    471490    case "cancel-pack":
    472         var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     491        var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    473492        for each (var ent in entities)
    474493        {
    475494            var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     
    558577     */
    559578   
    560579    // Check whether we can control these units
    561     var entities = FilterEntityList(cmd.entities, player, controlAllUnits);
     580    var entities = FilterEntityList(cmd.entities, player, false, controlAllUnits);
    562581    if (!entities.length)
    563582        return false;
    564583   
     
    11811200
    11821201/**
    11831202 * Check if player can control this entity
    1184  * returns: true if the entity is valid and owned by the player if
     1203 * returns: true if the entity is valid and owned by the player
     1204 *              or includeMutualAllies is true and the entity is owned by an ally
    11851205 *      or control all units is activated for the player, else false
    11861206 */
    1187 function CanControlUnit(entity, player, controlAll)
     1207function CanControlUnit(entity, player, includeMutualAllies, controlAll)
    11881208{
    1189     return (IsOwnedByPlayer(player, entity) || controlAll);
     1209    return (IsOwnedByPlayer(player, entity) || (includeMutualAllies && IsOwnedByMutualAllyOfPlayer(player, entity)) || controlAll);
    11901210}
    11911211
    11921212/**
    11931213 * Filter entities which the player can control
    11941214 */
    1195 function FilterEntityList(entities, player, controlAll)
     1215function FilterEntityList(entities, player, includeMutualAllies, controlAll)
    11961216{
    1197     return entities.filter(function(ent) { return CanControlUnit(ent, player, controlAll);} );
     1217    return entities.filter(function(ent) { return CanControlUnit(ent, player, includeMutualAllies, controlAll);} );
    11981218}
    11991219
    12001220/**
  • 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(),
  • binaries/data/mods/public/simulation/components/GarrisonHolder.js

     
    477477    }
    478478};
    479479
     480
     481/**
     482 * Eject all foreign garrisoned entities which are no more allied
     483 */
     484GarrisonHolder.prototype.OnDiplomacyChanged = function()
     485{
     486    for (var i = this.entities.length; i > 0; --i)
     487    {
     488        if (!IsOwnedByMutualAllyOfEntity(this.entity, this.entities[i-1]))
     489            this.Eject(this.entities[i-1], true);
     490    }
     491    this.UpdateGarrisonFlag();
     492};
     493
    480494Engine.RegisterComponentType(IID_GarrisonHolder, "GarrisonHolder", GarrisonHolder);
    481495
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    39563956    if (!cmpGarrisonHolder)
    39573957        return false;
    39583958
    3959     // Verify that the target is owned by this entity's player
     3959    // Verify that the target is owned by this entity's player or is mutual allied
    39603960    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
    3961     if (!cmpOwnership || !IsOwnedByPlayer(cmpOwnership.GetOwner(), target))
     3961    if (!cmpOwnership || !(IsOwnedByPlayer(cmpOwnership.GetOwner(), target) || IsOwnedByMutualAllyOfPlayer(cmpOwnership.GetOwner(), target)))
    39623962        return false;
    39633963
    39643964    // Don't let animals garrison for now
  • binaries/data/mods/public/simulation/components/Player.js

     
    337337
    338338    var sharedLos = [];
    339339    for (var i = 0; i < cmpPlayerManager.GetNumPlayers(); ++i)
    340         if (this.IsAlly(i))
    341         {
    342             var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(i), IID_Player);
    343             if (cmpPlayer && cmpPlayer.IsAlly(this.playerID))
    344                 sharedLos.push(i);
    345         }
     340        if (this.IsMutualAlly(i))
     341            sharedLos.push(i);
    346342
    347343    cmpRangeManager.SetSharedLos(this.playerID, sharedLos);
    348344};
     
    410406    return this.diplomacy[id] > 0;
    411407};
    412408
     409/**
     410 * Check if given player is our ally, and we are its ally
     411 */
     412Player.prototype.IsMutualAlly = function(id)
     413{
     414    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     415    if (!cmpPlayerManager)
     416        return false;
     417    var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(id), IID_Player);
     418    return this.IsAlly(id) && cmpPlayer && cmpPlayer.IsAlly(this.playerID);
     419};
     420
    413421Player.prototype.SetEnemy = function(id)
    414422{
    415423    this.SetDiplomacyIndex(id, -1);