Ticket #3488: 3488.4 - Testcase.diff

File 3488.4 - Testcase.diff, 8.1 KB (added by Stan, 8 years ago)

Little testcase if needed, you can only add an onager on the nearest tower, and all the other are for archers.

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

     
    3232
    3333BuildingAI.prototype.OnGarrisonedUnitsChanged = function(msg)
    3434{
     35    if(msg.visible)
     36        return;
    3537    let classes = this.template.GarrisonArrowClasses;
    3638
    3739    for (let ent of msg.added)
  • 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 
    233255    if (visibleGarrisonPoint)
    234     {
    235         visibleGarrisonPoint.entity = entity;
    236         cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset);
    237         let cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
    238         if (cmpUnitAI)
    239             cmpUnitAI.SetTurretStance();
     256    {   
     257        if (this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity))
     258        {
     259            visibleGarrisonPoint.entity = entity;
     260            cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset);
     261            let cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
     262            if (cmpUnitAI)
     263                cmpUnitAI.SetTurretStance();
     264        }
     265        else
     266            cmpPosition.MoveOutOfWorld();
    240267    }
    241268    else
    242269        cmpPosition.MoveOutOfWorld();
    243 
     270    // Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet.
     271    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [entity], "visible": this.IsVisiblyGarrisonned(entity), "removed": [] });
    244272    return true;
    245273};
    246274
     275/**
     276 * Garrison units inside the entity
     277 * @return true if successful, false if not
     278 */
    247279GarrisonHolder.prototype.PerformGarrison = function(entity)
    248280{
    249281    if (!this.HasEnoughHealth())
     
    278310    if (cmpAura && cmpAura.HasGarrisonAura())
    279311        cmpAura.ApplyGarrisonBonus(this.entity);
    280312
    281     Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
    282 
    283313    var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
    284314    if (cmpUnitAI && cmpUnitAI.IsUnderAlert())
    285315        Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity});
     
    326356
    327357    var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
    328358    this.entities.splice(entityIndex, 1);
    329 
     359    // Should only be called before the ejection has been performed else the visible Garrison Points will be empty.
     360    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "visible": this.IsVisiblyGarrisonned(entity), "removed": [entity] });
    330361    for (var vgp of this.visibleGarrisonPoints)
    331362    {
    332363        if (vgp.entity != entity)
     
    356387    cmpNewPosition.SetHeightOffset(0);
    357388    // TODO: what direction should they face in?
    358389
    359     Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
    360390
    361391    return true;
    362392};
     
    620650        if (cmpHealth && cmpHealth.GetHitpoints() == 0)
    621651        {
    622652            this.entities.splice(entityIndex, 1);
    623             Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
     653            Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "visible": this.IsVisiblyGarrisonned(entity), "removed": [msg.entity] });
    624654            this.UpdateGarrisonFlag();
    625655
    626656            for (var pt of this.visibleGarrisonPoints)
     
    634664
    635665/**
    636666 * Update list of garrisoned entities if one gets renamed (e.g. by promotion)
     667 * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint,
     668 * in case of promotion for example, and thus should always be allowed.
    637669 */
    638670GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
    639671{
     
    670702    }
    671703};
    672704
    673 
    674705/**
    675706 * Eject all foreign garrisoned entities which are no more allied
    676707 */
     
    712743    }
    713744
    714745    if (killedEntities.length > 0)
    715         Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : killedEntities });
     746        Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added": [], "visible": this.IsVisiblyGarrisonned(entity), "removed" : killedEntities });
    716747    this.UpdateGarrisonFlag();
    717748};
    718749
    719750/**
     751 * Gives insight about the unit type of garrisoning.
     752 * @return{bool} returns true if the unit is visible on the structure
     753 * @param {int} the entity's id
     754 */
     755GarrisonHolder.prototype.IsVisiblyGarrisonned = function(entity)
     756{
     757    for(let point of this.visibleGarrisonPoints)
     758        if (point.entity === entity)
     759            return true
     760    return false;
     761};
     762
     763/**
    720764 * Checks if an entity is ejectable on destroy if possible
    721765 */
    722766GarrisonHolder.prototype.IsEjectable = function(entity)
  • binaries/data/mods/public/simulation/templates/structures/maur_fortress.xml

     
    55    <SpecificName>Durg</SpecificName>
    66    <Tooltip>Train heroes and champion units.</Tooltip>
    77  </Identity>
     8  <GarrisonHolder>
     9    <Max>150</Max>
     10    <List datatype="tokens">
     11      Ranged
     12      Infantry
     13      Cavalry
     14      Elephant
     15    </List>
     16    <EjectHealth>0.1</EjectHealth>
     17    <EjectClassesOnDestroy datatype="tokens">Unit</EjectClassesOnDestroy>
     18    <BuffHeal>0</BuffHeal>
     19    <LoadingRange>2</LoadingRange>
     20    <VisibleGarrisonPoints>
     21      <Archer1>
     22        <X>10.5</X><Y>13.75</Y><Z>-9.5</Z>
     23        <VisibleGarrisonAllowedClasses datatype="tokens">
     24            Infantry+Ranged
     25        </VisibleGarrisonAllowedClasses>
     26      </Archer1>
     27      <Archer2>
     28        <X>-10.5</X><Y>13.75</Y><Z>9.5</Z>
     29        <VisibleGarrisonAllowedClasses datatype="tokens">
     30            Infantry+Ranged
     31        </VisibleGarrisonAllowedClasses>
     32      </Archer2>
     33      <Archer3>
     34        <X>-10.5</X><Y>13.75</Y><Z>-9.5</Z>
     35        <VisibleGarrisonAllowedClasses datatype="tokens">
     36            Infantry+Ranged
     37        </VisibleGarrisonAllowedClasses>
     38      </Archer3>
     39      <Archer4>
     40        <X>10.5</X><Y>13.75</Y><Z>9.5</Z>
     41        <VisibleGarrisonAllowedClasses datatype="tokens">
     42            Ranged+Catapult
     43        </VisibleGarrisonAllowedClasses>
     44      </Archer4>
     45    </VisibleGarrisonPoints>
     46  </GarrisonHolder>
    847  <ProductionQueue>
    948    <Entities datatype="tokens">
    1049      units/{civ}_hero_chanakya