Ticket #3488: 3488.13.diff

File 3488.13.diff, 8.8 KB (added by Stan, 8 years ago)

New version this time creating temporary objects as the game would replace the value of the variable by the name.

  • binaries/data/mods/public/simulation/components/BuildingAI.js

     
    3737    for (let ent of msg.added)
    3838    {
    3939        let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
    40         if (!cmpIdentity)
     40        if (msg.visible[ent] || !cmpIdentity)
    4141            continue;
    4242        if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
    4343            ++this.archersGarrisoned;
     
    4646    for (let ent of msg.removed)
    4747    {
    4848        let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
    49         if (!cmpIdentity)
     49        if (msg.visible[ent] || !cmpIdentity)
    5050            continue;
    5151        if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
    5252            --this.archersGarrisoned;
  • binaries/data/mods/public/simulation/components/GarrisonHolder.js

     
     1/**
     2 * @class Defines an entity's ability to garrison units.
     3 */
    14function GarrisonHolder() {}
    25
    36GarrisonHolder.prototype.Schema =
     
    4548                        "<element name='Z'>" +
    4649                            "<data type='decimal'/>" +
    4750                        "</element>" +
     51                        "<optional>" +
     52                            "<element name='VisibleGarrisonAllowedClasses'>" +
     53                                "<attribute name='datatype'>" +
     54                                    "<value>tokens</value>" +
     55                                "</attribute>" +
     56                                "<text/>" +
     57                            "</element>" +
     58                        "</optional>" +
    4859                    "</interleave>" +
    4960                "</element>" +
    5061            "</zeroOrMore>" +
     
    7283            o.x = +offset.X;
    7384            o.y = +offset.Y;
    7485            o.z = +offset.Z;
    75             this.visibleGarrisonPoints.push({"offset":o, "entity": null});
     86            this.visibleGarrisonPoints.push({ "offset": o, "entity": null, "allowedClass": offset.VisibleGarrisonAllowedClasses });
    7687        }
    7788    }
    7889};
     
    100111    return IsOwnedByPlayer(player, ent);
    101112};
    102113
    103 
    104114/**
    105115 * Return the list of entities garrisoned inside
    106116 */
     
    204214};
    205215
    206216/**
     217 * Returns true if the unit is allowed be visible on that garrison point, false otherwise.
     218 */
     219GarrisonHolder.prototype.AllowedToVisibleGarrisoning = function(visibleGarrisonPoint, entity)
     220{
     221    let allowedClassesList = visibleGarrisonPoint.allowedClass._string;
     222    // If classlist is empty, everybody can garrison.
     223    if (!allowedClassesList)
     224        return true;
     225   
     226    return MatchesClassList(Engine.QueryInterface(entity, IID_Identity).GetClassesList(), allowedClassesList);
     227};
     228
     229/**
    207230 * Garrison a unit inside.
    208231 * Returns true if successful, false if not
    209232 * The timer for AutoHeal is started here
     
    225248        {
    226249            if (vgp.entity)
    227250                continue;
    228             visibleGarrisonPoint = vgp;
    229             break;
     251            if (this.AllowedToVisibleGarrisoning(vgp, entity))
     252            {
     253                visibleGarrisonPoint = vgp;
     254                break;
     255            }
    230256        }
    231257    }
    232 
    233     if (visibleGarrisonPoint)
     258    if (visibleGarrisonPoint && this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity))
    234259    {
    235260        visibleGarrisonPoint.entity = entity;
    236261        cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset);
     
    241266    else
    242267        cmpPosition.MoveOutOfWorld();
    243268
     269    let visible = {};
     270    let key = "" + entity;
     271    visible[key] = this.IsVisiblyGarrisoned(entity);
     272    // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet.
     273    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     274        "added": [entity],
     275        "removed": [],
     276        "visible": visible
     277    });
    244278    return true;
    245279};
    246280
     281/**
     282 * Garrison units inside the entity
     283 * @return true if successful, false if not
     284 */
    247285GarrisonHolder.prototype.PerformGarrison = function(entity)
    248286{
    249287    if (!this.HasEnoughHealth())
     
    250288        return false;
    251289
    252290    // Check if the unit is allowed to be garrisoned inside the building
    253     if(!this.AllowedToGarrison(entity))
     291    if (!this.AllowedToGarrison(entity))
    254292        return false;
    255293
    256     // check the capacity
     294    // Check the capacity
    257295    var extraCount = 0;
    258296    var cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder);
    259297    if (cmpGarrisonHolder)
     
    278316    if (cmpAura && cmpAura.HasGarrisonAura())
    279317        cmpAura.ApplyGarrisonBonus(this.entity);
    280318
    281     Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
    282 
    283319    var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
    284320    if (cmpUnitAI && cmpUnitAI.IsUnderAlert())
    285321        Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity});
     
    326362
    327363    var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
    328364    this.entities.splice(entityIndex, 1);
    329 
     365   
     366    let visible = {};
     367    let key = "" + entity;
     368    visible[key] = this.IsVisiblyGarrisoned(entity);
     369    // Should only be called before the ejection has been performed else the visible Garrison Points will be empty.
     370    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     371        "added": [],
     372        "removed": [entity],
     373        "visible": visible
     374    });
    330375    for (var vgp of this.visibleGarrisonPoints)
    331376    {
    332377        if (vgp.entity != entity)
     
    356401    cmpNewPosition.SetHeightOffset(0);
    357402    // TODO: what direction should they face in?
    358403
    359     Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
    360404
    361405    return true;
    362406};
     
    597641 */
    598642GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg)
    599643{
     644    let msgEntity = msg.entity;
    600645    // the ownership change may be on the garrisonholder
    601     if (this.entity == msg.entity)
     646    if (this.entity == msgEntity)
    602647    {
    603648        var entities = [];
    604649        for each (var entity in this.entities)
     
    612657    }
    613658
    614659    // or on some of its garrisoned units
    615     var entityIndex = this.entities.indexOf(msg.entity);
     660    var entityIndex = this.entities.indexOf(msgEntity);
    616661    if (entityIndex != -1)
    617662    {
    618663        // If the entity is dead, remove it directly instead of ejecting the corpse
    619         var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health);
     664        var cmpHealth = Engine.QueryInterface(msgEntity, IID_Health);
    620665        if (cmpHealth && cmpHealth.GetHitpoints() == 0)
    621666        {
    622667            this.entities.splice(entityIndex, 1);
    623             Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
     668            let visible = {};
     669            let key = "" + msgEntity;
     670            visible[key] = this.IsVisiblyGarrisoned(msgEntity);
     671            Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     672                "added": [],
     673                "removed": [msgEntity],
     674                "visible": visible
     675            });
    624676            this.UpdateGarrisonFlag();
    625677
    626678            for (var pt of this.visibleGarrisonPoints)
    627                 if (pt.entity == msg.entity)
     679                if (pt.entity == msgEntity)
    628680                    pt.entity = null;
    629681        }
    630         else if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, msg.entity))
    631             this.EjectOrKill([msg.entity]);
     682        else if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, msgEntity))
     683            this.EjectOrKill([msgEntity]);
    632684    }
    633685};
    634686
    635687/**
    636688 * Update list of garrisoned entities if one gets renamed (e.g. by promotion)
     689 * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint,
     690 * in case of promotion for example, and thus should always be allowed.
    637691 */
    638692GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
    639693{
     
    670724    }
    671725};
    672726
    673 
    674727/**
    675728 * Eject all foreign garrisoned entities which are no more allied
    676729 */
     
    687740GarrisonHolder.prototype.EjectOrKill = function(entities)
    688741{
    689742    var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
    690     // Eject the units which can be ejected (if not in world, it generally means this holder
     743    // Eject the units which can be ejected (if not in world, it often means this holder
    691744    // is inside a holder which kills its entities, so do not eject)
    692745    if (cmpPosition.IsInWorld())
    693746    {
     
    710763        this.entities.splice(entityIndex, 1);
    711764        killedEntities.push(entity);
    712765    }
    713 
    714766    if (killedEntities.length > 0)
    715         Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : killedEntities });
     767    {
     768        let visibleEntitiesIds = {};
     769        for (let ent of killedEntities)
     770            visibleEntitiesIds[ent] = this.IsVisiblyGarrisoned(ent);
     771        Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     772            "added": [],
     773            "removed": killedEntities,
     774            "visible": visibleEntitiesIds
     775        });
     776    }
    716777    this.UpdateGarrisonFlag();
    717778};
    718779
    719780/**
     781 * Gives insight about the unit type of garrisoning.
     782 * @return{bool} returns true if the unit is visible on the structure
     783 * @param {int} the entity's id
     784 */
     785GarrisonHolder.prototype.IsVisiblyGarrisoned = function(entity)
     786{
     787    return this.visibleGarrisonPoints.some(point => point.entity == entity);
     788};
     789
     790/**
    720791 * Checks if an entity is ejectable on destroy if possible
    721792 */
    722793GarrisonHolder.prototype.IsEjectable = function(entity)