Ticket #3488: 3488.10.diff

File 3488.10.diff, 7.6 KB (added by Stan, 8 years ago)

Should fix most of the issues and be a little more clean.

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

     
    3636
    3737    for (let ent of msg.added)
    3838    {
    39         let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
    40         if (!cmpIdentity)
     39        let cmpIdentity = Engine.QueryInterface(ent.id, IID_Identity);
     40        if (ent.visible || !cmpIdentity)
    4141            continue;
    4242        if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
    4343            ++this.archersGarrisoned;
     
    4545
    4646    for (let ent of msg.removed)
    4747    {
    48         let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
    49         if (!cmpIdentity)
     48        let cmpIdentity = Engine.QueryInterface(ent.id, IID_Identity);
     49        if (ent.visible || !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
     
    229252            break;
    230253        }
    231254    }
    232 
    233     if (visibleGarrisonPoint)
     255    if (visibleGarrisonPoint && this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity))
    234256    {
    235257        visibleGarrisonPoint.entity = entity;
    236258        cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset);
     
    240262    }
    241263    else
    242264        cmpPosition.MoveOutOfWorld();
    243 
     265    // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet.
     266    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     267        "added": [{ "id": entity, "visible": this.IsVisiblyGarrisoned(entity) }],
     268        "removed": []
     269    });
    244270    return true;
    245271};
    246272
     273/**
     274 * Garrison units inside the entity
     275 * @return true if successful, false if not
     276 */
    247277GarrisonHolder.prototype.PerformGarrison = function(entity)
    248278{
    249279    if (!this.HasEnoughHealth())
     
    250280        return false;
    251281
    252282    // Check if the unit is allowed to be garrisoned inside the building
    253     if(!this.AllowedToGarrison(entity))
     283    if (!this.AllowedToGarrison(entity))
    254284        return false;
    255285
    256     // check the capacity
     286    // Check the capacity
    257287    var extraCount = 0;
    258288    var cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder);
    259289    if (cmpGarrisonHolder)
     
    278308    if (cmpAura && cmpAura.HasGarrisonAura())
    279309        cmpAura.ApplyGarrisonBonus(this.entity);
    280310
    281     Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
    282 
    283311    var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
    284312    if (cmpUnitAI && cmpUnitAI.IsUnderAlert())
    285313        Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity});
     
    326354
    327355    var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
    328356    this.entities.splice(entityIndex, 1);
    329 
     357    // Should only be called before the ejection has been performed else the visible Garrison Points will be empty.
     358    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     359        "added": [],
     360        "removed": [{ "id": entity, "visible": this.IsVisiblyGarrisoned(entity) }]
     361    });
    330362    for (var vgp of this.visibleGarrisonPoints)
    331363    {
    332364        if (vgp.entity != entity)
     
    356388    cmpNewPosition.SetHeightOffset(0);
    357389    // TODO: what direction should they face in?
    358390
    359     Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
    360391
    361392    return true;
    362393};
     
    620651        if (cmpHealth && cmpHealth.GetHitpoints() == 0)
    621652        {
    622653            this.entities.splice(entityIndex, 1);
    623             Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
     654            Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     655                "added": [],
     656                "removed": [{ "id": msg.entity, "visible": this.IsVisiblyGarrisoned(msg.entity) }]
     657            });
    624658            this.UpdateGarrisonFlag();
    625659
    626660            for (var pt of this.visibleGarrisonPoints)
     
    634668
    635669/**
    636670 * Update list of garrisoned entities if one gets renamed (e.g. by promotion)
     671 * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint,
     672 * in case of promotion for example, and thus should always be allowed.
    637673 */
    638674GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
    639675{
     
    670706    }
    671707};
    672708
    673 
    674709/**
    675710 * Eject all foreign garrisoned entities which are no more allied
    676711 */
     
    687722GarrisonHolder.prototype.EjectOrKill = function(entities)
    688723{
    689724    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
     725    // Eject the units which can be ejected (if not in world, it often means this holder
    691726    // is inside a holder which kills its entities, so do not eject)
    692727    if (cmpPosition.IsInWorld())
    693728    {
     
    710745        this.entities.splice(entityIndex, 1);
    711746        killedEntities.push(entity);
    712747    }
    713 
    714748    if (killedEntities.length > 0)
    715         Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : killedEntities });
     749    {
     750        let killedEntitiesObjects = [];
     751        for (let ent of killedEntities)
     752        {
     753            killedEntitiesObjects.push({"id": ent, "visible": this.IsVisiblyGarrisoned(ent)});
     754        }
     755        Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
     756            "added": [],
     757            "removed": killedEntitiesObjects
     758        });
     759    }
    716760    this.UpdateGarrisonFlag();
    717761};
    718762
    719763/**
     764 * Gives insight about the unit type of garrisoning.
     765 * @return{bool} returns true if the unit is visible on the structure
     766 * @param {int} the entity's id
     767 */
     768GarrisonHolder.prototype.IsVisiblyGarrisoned = function(entity)
     769{
     770    return this.visibleGarrisonPoints.some(point => point.entity === entity);
     771};
     772
     773/**
    720774 * Checks if an entity is ejectable on destroy if possible
    721775 */
    722776GarrisonHolder.prototype.IsEjectable = function(entity)