Ticket #3180: auravisualisation.2.diff

File auravisualisation.2.diff, 19.7 KB (added by sanderd17, 9 years ago)
  • binaries/data/mods/public/simulation/components/AuraManager.js

     
    3939    return k;
    4040};
    4141
    42 AuraManager.prototype.ApplyBonus = function(value, ent, data, key)
     42AuraManager.prototype.ApplyBonus = function(value, ents, data, key)
    4343{
    44     var dataList = this.ensureExists("modifications", value, ent, key, {"add":0, "multiply":1});
     44    for (let ent of ents)
     45    {
     46        var dataList = this.ensureExists("modifications", value, ent, key, {"add":0, "multiply":1});
    4547
    46     dataList.push(data);
     48        dataList.push(data);
    4749
    48     if (dataList.length > 1)
    49         return;
     50        if (dataList.length > 1)
     51            continue;
    5052
    51     // first time added this aura
    52     if (data.multiply)
    53         this.modificationsCache[value][ent].multiply *= data.multiply;
     53        // first time added this aura
     54        if (data.multiply)
     55            this.modificationsCache[value][ent].multiply *= data.multiply;
    5456
    55     if (data.add)
    56         this.modificationsCache[value][ent].add += data.add;
    57 
    58     // post message to the entity to notify it about the change
    59     Engine.PostMessage(ent, MT_ValueModification, { "entities": [ent], "component": value.split("/")[0], "valueNames": [value] });
     57        if (data.add)
     58            this.modificationsCache[value][ent].add += data.add;
     59        // post message to the entity to notify it about the change
     60        Engine.PostMessage(ent, MT_ValueModification, { "entities": [ent], "component": value.split("/")[0], "valueNames": [value] });
     61    }
    6062};
    6163
    6264AuraManager.prototype.ApplyTemplateBonus = function(value, player, classes, data, key)
     
    8486    Engine.PostMessage(SYSTEM_ENTITY, MT_TemplateModification, { "player": player, "component": value.split("/")[0], "valueNames": [value] });
    8587};
    8688
    87 AuraManager.prototype.RemoveBonus = function(value, ent, key)
     89AuraManager.prototype.RemoveBonus = function(value, ents, key)
    8890{
    89     var v = this.modifications[value];
    90     if (!v)
    91         return;
    92     var e = v[ent];
    93     if (!e)
    94         return;
    95     var dataList = e[key];
    96     if (!dataList || !dataList.length)
    97         return;
     91    for (let ent of ents)
     92    {
     93        var v = this.modifications[value];
     94        if (!v)
     95            continue;
     96        var e = v[ent];
     97        if (!e)
     98            continue;
     99        var dataList = e[key];
     100        if (!dataList || !dataList.length)
     101            continue;
    98102
    99     // get the applied data to remove again
    100     var data = dataList.pop();
     103        // get the applied data to remove again
     104        var data = dataList.pop();
    101105
    102     if (dataList.length > 0)
    103         return;
     106        if (dataList.length > 0)
     107            continue;
    104108
    105     // out of last aura of this kind, remove modifications
    106     if (data.add)
    107         this.modificationsCache[value][ent].add -= data.add;
     109        // out of last aura of this kind, remove modifications
     110        if (data.add)
     111            this.modificationsCache[value][ent].add -= data.add;
    108112
    109     if (data.multiply)
    110         this.modificationsCache[value][ent].multiply /= data.multiply;
    111 
    112     // post message to the entity to notify it about the change
    113     Engine.PostMessage(ent, MT_ValueModification, { "entities": [ent], "component": value.split("/")[0], "valueNames": [value] });
     113        if (data.multiply)
     114            this.modificationsCache[value][ent].multiply /= data.multiply;
     115        // post message to the entity to notify it about the change
     116        Engine.PostMessage(ent, MT_ValueModification, { "entities": [ent], "component": value.split("/")[0], "valueNames": [value] });
     117    }
    114118};
    115119
    116120AuraManager.prototype.RemoveTemplateBonus = function(value, player, classes, key)
  • binaries/data/mods/public/simulation/components/Auras.js

     
    4747                        "<text/>" +
    4848                    "</element>" +
    4949                "</optional>" +
     50                "<optional>" +
     51                    "<element name='OverlayIcon' a:help='Icon to show on the entities affected by this aura'>" +
     52                        "<text/>" +
     53                    "</element>" +
     54                "</optional>" +
    5055                "<element name='Affects' a:help='Affected classes'>" +
    5156                    "<text/>" +
    5257                "</element>" +
     
    103108    return Object.keys(this.template);
    104109};
    105110
     111Auras.prototype.GetOverlayIcon = function(name)
     112{
     113    return this.template[name].OverlayIcon || "";
     114};
     115
     116Auras.prototype.GetAffectedEntities = function(name)
     117{
     118    return this[name].targetUnits;
     119};
     120
    106121Auras.prototype.GetRange = function(name)
    107122{
    108123    if (!this.IsRangeAura(name))
     
    136151
    137152    this.affectedPlayers[name] = [];
    138153
    139     var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
     154    var cmpPlayer = QueryOwnerInterface(this.entity);
    140155
    141156    if (!cmpPlayer)
    142157        return;
    143158
    144     var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
    145     var numPlayers = cmpPlayerManager.GetNumPlayers();
     159    var numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
    146160
    147161    for (var i = 0; i < numPlayers; ++i)
    148162    {
    149         for each (var p in affectedPlayers)
     163        for (let p of affectedPlayers)
    150164        {
    151165            if (p == "Player" ? cmpPlayer.GetPlayerID() == i : cmpPlayer["Is" + p](i))
    152166            {
     
    159173
    160174Auras.prototype.HasFormationAura = function()
    161175{
    162     return this.GetAuraNames().some(this.IsFormationAura.bind(this));
     176    return this.GetAuraNames().some(n => this.IsFormationAura(n));
    163177};
    164178
    165179Auras.prototype.HasGarrisonAura = function()
    166180{
    167     return this.GetAuraNames().some(this.IsGarrisonAura.bind(this));
     181    return this.GetAuraNames().some(n => this.IsGarrisonAura(n));
    168182};
    169183
    170184Auras.prototype.HasGarrisonedUnitsAura = function()
    171185{
    172     return this.GetAuraNames().some(this.IsGarrisonedUnitsAura.bind(this));
     186    return this.GetAuraNames().some(n => this.IsGarrisonedUnitsAura(n));
    173187};
    174188
    175189Auras.prototype.GetType = function(name)
     
    211225    var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    212226    var auraNames = this.GetAuraNames();
    213227    // remove all bonuses
    214     for each (var name in auraNames)
     228    for (let name of auraNames)
    215229    {
    216230        if (!this[name])
    217231            continue;
     
    219233        if (this.IsGlobalAura(name))
    220234            this.RemoveTemplateBonus(name);
    221235
    222         for each(var ent in this[name].targetUnits)
    223             this.RemoveBonus(name, ent);
     236        this.RemoveBonus(name, this[name].targetUnits);
    224237
    225238        if (this[name].rangeQuery)
    226239            cmpRangeManager.DestroyActiveQuery(this[name].rangeQuery);
    227240    }
    228241
    229     for each (var name in auraNames)
     242    for (let name of auraNames)
    230243    {
    231244        // only calculate the affected players on re-applying the bonuses
    232245        // this makes sure the template bonuses are removed from the correct players
     
    277290
    278291Auras.prototype.OnRangeUpdate = function(msg)
    279292{
    280     var auraNames = this.GetAuraNames();
    281     for each (var n in auraNames)
     293    var auraNames = this.GetAuraNames().filter(n => msg.tag == this[n].rangeQuery);
     294    for (let name of auraNames)
    282295    {
    283         if (msg.tag == this[n].rangeQuery)
    284         {
    285             var name = n;
    286             break;
    287         }
     296        this.ApplyBonus(name, msg.added);
     297        this.RemoveBonus(name, msg.removed);
    288298    }
    289 
    290     if (!name)
    291         return;
    292 
    293     var targetUnits = this[name].targetUnits;
    294     var classes = this.GetClasses(name);
    295 
    296     if (msg.added.length > 0)
    297     {
    298         var validList = this.GiveMembersWithValidClass(name, msg.added);
    299         for each (var e in validList)
    300         {
    301             targetUnits.push(e);
    302             this.ApplyBonus(name, e);
    303         }
    304     }
    305 
    306     if (msg.removed.length > 0)
    307     {
    308         for each (var e in msg.removed)
    309         {
    310             targetUnits.splice(targetUnits.indexOf(e), 1);
    311             this.RemoveBonus(name, e);
    312         }
    313     }
    314 
    315299};
    316300
    317301Auras.prototype.OnGarrisonedUnitsChanged = function(msg)
    318302{
    319     var auraNames = this.GetAuraNames();
    320     for each (var name in auraNames)
     303    var auraNames = this.GetAuraNames().filter(n => this.IsGarrisonedUnitsAura(n));
     304    for (let name of auraNames)
    321305    {
    322         if (!this.IsGarrisonedUnitsAura(name))
    323             continue;
    324         for each (var ent in msg.added)
    325             this.ApplyBonus(name, ent);
    326         for each (var ent in msg.removed)
    327             this.RemoveBonus(name, ent);
     306        this.ApplyBonus(name, msg.added);
     307        this.RemoveBonus(name, msg.removed);
    328308    }
    329309};
    330310
    331311Auras.prototype.ApplyFormationBonus = function(memberList)
    332312{
    333     var auraNames = this.GetAuraNames();
    334     for each (var name in auraNames)
    335     {
    336         if (!this.IsFormationAura(name))
    337             continue;
    338 
    339         var validList = this.GiveMembersWithValidClass(name, memberList);
    340         for each (var ent in validList)
    341         {
    342             this[name].targetUnits.push(ent);
    343             this.ApplyBonus(name,ent);
    344         }
    345     }
     313    var auraNames = this.GetAuraNames().filter(n => this.IsFormationAura(n));
     314    for (let name of auraNames)
     315        this.ApplyBonus(name, memberList);
    346316};
    347317
    348318Auras.prototype.ApplyGarrisonBonus = function(structure)
    349319{
    350     var auraNames = this.GetAuraNames();
    351     for each (var name in auraNames)
    352     {
    353         if (!this.IsGarrisonAura(name))
    354             continue;
    355 
    356         var validList = this.GiveMembersWithValidClass(name, [structure]);
    357         if (validList.length)
    358         {
    359             this[name].targetUnits.push(validList[0]);
    360             this.ApplyBonus(name,validList[0]);
    361         }
    362     }
     320    var auraNames = this.GetAuraNames().filter(n => this.IsGarrisonAura(n));
     321    for (let name of auraNames)
     322        this.ApplyBonus(name, [structure]);
    363323};
    364324
    365325Auras.prototype.ApplyTemplateBonus = function(name, players)
     
    370330    var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
    371331    var classes = this.GetClasses(name);
    372332
    373     for each (var mod in modifications)
    374         for each (var player in players)
     333    for (let mod of modifications)
     334        for (let player of players)
    375335            cmpAuraManager.ApplyTemplateBonus(mod.value, player, classes, mod, this.templateName + "/" + name + "/" + mod.value);
    376336};
    377337
    378338Auras.prototype.RemoveFormationBonus = function(memberList)
    379339{
    380     var auraNames = this.GetAuraNames();
    381     for each (var name in auraNames)
    382     {
    383         if (!this.IsFormationAura(name))
    384             continue;
    385 
    386         for each (var ent in memberList)
    387         {
    388             this.RemoveBonus(name,ent);
    389             this[name].targetUnits.splice(this[name].targetUnits.indexOf(ent), 1);
    390         }
    391     }
     340    var auraNames = this.GetAuraNames().filter(n => this.IsFormationAura(n));
     341    for (let name of auraNames)
     342        this.RemoveBonus(name, memberList);
    392343};
    393344
    394345Auras.prototype.RemoveGarrisonBonus = function(structure)
    395346{
    396     var auraNames = this.GetAuraNames();
    397     for each (var name in auraNames)
    398     {
    399         if (!this.IsGarrisonAura(name))
    400             continue;
    401 
    402         this.RemoveBonus(name,structure);
    403         this[name].targetUnits.splice(this[name].targetUnits.indexOf(structure), 1);
    404     }
     347    var auraNames = this.GetAuraNames().filter(n => this.IsGarrisonAura(n));
     348    for (let name of auraNames)
     349        this.RemoveBonus(name, [structure]);
    405350};
    406351
    407352Auras.prototype.RemoveTemplateBonus = function(name)
     
    419364            cmpAuraManager.RemoveTemplateBonus(mod.value, player, classes, this.templateName + "/" + name + "/" + mod.value);
    420365};
    421366
    422 Auras.prototype.ApplyBonus = function(name, ent)
     367Auras.prototype.ApplyBonus = function(name, ents)
    423368{
     369    var validEnts = this.GiveMembersWithValidClass(name, ents);
     370    if (!validEnts.length)
     371        return;
     372    this[name].targetUnits = this[name].targetUnits.concat(validEnts);
    424373    var modifications = this.GetModifications(name);
    425374    var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
    426     for each (var mod in modifications)
    427         cmpAuraManager.ApplyBonus(mod.value, ent, mod, this.templateName + "/" + name + "/" + mod.value);
    428 
     375    for each (let mod in modifications)
     376        cmpAuraManager.ApplyBonus(mod.value, validEnts, mod, this.templateName + "/" + name + "/" + mod.value);
     377    // update status bars if this has an icon
     378    if (!this.GetOverlayIcon(name))
     379        return;
     380    for (let ent of validEnts)
     381    {
     382        var cmpStatusBars = Engine.QueryInterface(ent, IID_StatusBars)
     383        if (cmpStatusBars)
     384            cmpStatusBars.AddAuraSource(this.entity, name);
     385    }
    429386};
    430387
    431 Auras.prototype.RemoveBonus = function(name, ent)
     388Auras.prototype.RemoveBonus = function(name, ents)
    432389{
     390    var validEnts = this.GiveMembersWithValidClass(name, ents);
     391    if (!validEnts.length)
     392        return;
     393    this[name].targetUnits = this[name].targetUnits.filter(v => validEnts.indexOf(v) == -1);
    433394    var modifications = this.GetModifications(name);
    434395    var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
    435 
    436     for each (var mod in modifications)
    437         cmpAuraManager.RemoveBonus(mod.value, ent, this.templateName + "/" + name + "/" + mod.value);
     396    for each (let mod in modifications)
     397        cmpAuraManager.RemoveBonus(mod.value, validEnts, this.templateName + "/" + name + "/" + mod.value);
     398    // update status bars if this has an icon
     399    if (!this.GetOverlayIcon(name))
     400        return;
     401    for (let ent of validEnts)
     402    {
     403        var cmpStatusBars = Engine.QueryInterface(ent, IID_StatusBars)
     404        if (cmpStatusBars)
     405            cmpStatusBars.RemoveAuraSource(this.entity, name);
     406    }
    438407};
    439408
    440409Auras.prototype.OnOwnershipChanged = function(msg)
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    3232    this.timeNotificationID = 1;
    3333    this.timeNotifications = [];
    3434    this.entsRallyPointsDisplayed = [];
     35    this.entsWithAuraAndStatusBars = new Set();
    3536};
    3637
    3738/*
     
    855856    }
    856857};
    857858
     859GuiInterface.prototype.GetEntitiesWithStatusBars = function()
     860{
     861    return [...this.entsWithAuraAndStatusBars];
     862};
     863
    858864GuiInterface.prototype.SetStatusBars = function(player, cmd)
    859865{
    860     for each (var ent in cmd.entities)
     866    let affectedEnts = [];
     867    for (let ent of cmd.entities)
    861868    {
    862         var cmpStatusBars = Engine.QueryInterface(ent, IID_StatusBars);
     869        let cmpStatusBars = Engine.QueryInterface(ent, IID_StatusBars);
     870        if (!cmpStatusBars)
     871            continue;
     872        cmpStatusBars.SetEnabled(cmd.enabled);
     873
     874        let cmpAuras = Engine.QueryInterface(ent, IID_Auras);
     875        if (!cmpAuras)
     876            continue;
     877
     878        for (let name of cmpAuras.GetAuraNames())
     879        {
     880            if (!cmpAuras.GetOverlayIcon(name))
     881                continue;
     882            affectedEnts = affectedEnts.concat(cmpAuras.GetAffectedEntities(name));
     883            if (cmd.enabled)
     884                this.entsWithAuraAndStatusBars.add(ent);
     885            else
     886                this.entsWithAuraAndStatusBars.delete(ent);
     887        }
     888    }
     889
     890    // make the affected ents unique
     891    affectedEnts = new Set(affectedEnts);
     892    for (let ent of affectedEnts)
     893    {
     894        let cmpStatusBars = Engine.QueryInterface(ent, IID_StatusBars)
    863895        if (cmpStatusBars)
    864             cmpStatusBars.SetEnabled(cmd.enabled);
     896            cmpStatusBars.RegenerateSprites();
    865897    }
    866898};
    867899
  • binaries/data/mods/public/simulation/components/StatusBars.js

     
    1414StatusBars.prototype.Init = function()
    1515{
    1616    this.enabled = false;
     17    this.auraSources = {};
    1718};
    1819
    19 // Because this is enabled directly by the GUI and is not
    20 // network-synchronised (it only affects local rendering),
    21 // we disable serialization in order to prevent OOS errors
    22 StatusBars.prototype.Serialize = null;
     20StatusBars.prototype.Serialize = function()
     21{
     22    return {"auraSources": this.auraSources};
     23};
    2324
    24 StatusBars.prototype.Deserialize = function()
     25StatusBars.prototype.Deserialize = function(data)
    2526{
    26     // Use default initialisation
    2727    this.Init();
     28    this.auraSources = data.auraSources;
    2829};
    2930
    3031StatusBars.prototype.SetEnabled = function(enabled)
     
    3334    if (enabled == this.enabled)
    3435        return;
    3536
     37    this.enabled = enabled;
     38
    3639    // Update the displayed sprites
     40    this.RegenerateSprites();
     41};
    3742
    38     this.enabled = enabled;
    39 
    40     if (enabled)
    41         this.RegenerateSprites();
     43StatusBars.prototype.AddAuraSource = function(source, auraName)
     44{
     45    if (this.auraSources[source])
     46        this.auraSources[source].push(auraName);
    4247    else
    43         this.ResetSprites();
     48        this.auraSources[source] = [auraName];
     49    this.RegenerateSprites();
    4450};
    4551
     52StatusBars.prototype.RemoveAuraSource = function(source, auraName)
     53{
     54    let names = this.auraSources[source];
     55    names.splice(names.indexOf(auraName), 1);
     56    this.RegenerateSprites();
     57};
     58
    4659StatusBars.prototype.OnHealthChanged = function(msg)
    4760{
    4861    if (this.enabled)
     
    6174        this.RegenerateSprites();
    6275};
    6376
    64 StatusBars.prototype.ResetSprites = function()
     77StatusBars.prototype.RegenerateSprites = function()
    6578{
    66     var cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer);
     79    let cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer);
    6780    cmpOverlayRenderer.Reset();
     81
     82    let yoffset = 0;
     83    if (this.enabled)
     84        yoffset = this.AddBars(cmpOverlayRenderer, yoffset);
     85    yoffset = this.AddAuraIcons(cmpOverlayRenderer, yoffset);
     86    return yoffset;
    6887};
    6988
    70 StatusBars.prototype.RegenerateSprites = function()
     89// Internal helper functions
     90StatusBars.prototype.AddAuraIcons = function(cmpOverlayRenderer, yoffset)
    7191{
    72     var cmpOverlayRenderer = Engine.QueryInterface(this.entity, IID_OverlayRenderer);
    73     cmpOverlayRenderer.Reset();
     92    let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
     93    let sources = cmpGuiInterface.GetEntitiesWithStatusBars().filter(e => this.auraSources[e] && this.auraSources[e].length);
    7494
     95    if (!sources.length)
     96        return yoffset;
     97
     98    let iconSet = new Set();
     99    for (let ent of sources)
     100    {
     101        let cmpAuras = Engine.QueryInterface(ent, IID_Auras);
     102        if (!cmpAuras) // probably the ent just died
     103            continue;
     104        for (let name of this.auraSources[ent])
     105            iconSet.add(cmpAuras.GetOverlayIcon(name));
     106    }
     107
     108    // World-space offset from the unit's position
     109    var offset = { "x": 0, "y": +this.template.HeightOffset, "z": 0 };
     110
     111    let iconSize = +this.template.BarWidth / 2;
     112    let xoffset = -iconSize * (iconSet.size - 1) * 0.6
     113    for (let icon of iconSet)
     114    {
     115        cmpOverlayRenderer.AddSprite(
     116            icon,
     117            { "x": xoffset - iconSize/2, "y": yoffset },
     118            { "x": xoffset + iconSize/2, "y": yoffset + iconSize },
     119            offset
     120        );
     121        xoffset += iconSize * 1.2;
     122    }
     123
     124    return yoffset + iconSize + this.template.BarHeight / 2;
     125};
     126
     127StatusBars.prototype.AddBars = function(cmpOverlayRenderer, yoffset)
     128{
    75129    // Size of health bar (in world-space units)
    76130    var width = +this.template.BarWidth;
    77131    var height = +this.template.BarHeight;
     
    79133    // World-space offset from the unit's position
    80134    var offset = { "x": 0, "y": +this.template.HeightOffset, "z": 0 };
    81135
    82     // Billboard offset of next bar
    83     var yoffset = 0;
    84 
    85136    var AddBar = function(type, amount)
    86137    {
    87138        cmpOverlayRenderer.AddSprite(
    88139            "art/textures/ui/session/icons/"+type+"_bg.png",
    89             { "x": -width/2, "y": -height/2 + yoffset },
    90             { "x": width/2, "y": height/2 + yoffset },
     140            { "x": -width/2, "y":yoffset },
     141            { "x": width/2, "y": height + yoffset },
    91142            offset
    92143        );
    93144
    94145        cmpOverlayRenderer.AddSprite(
    95146            "art/textures/ui/session/icons/"+type+"_fg.png",
    96             { "x": -width/2, "y": -height/2 + yoffset },
    97             { "x": width*(amount - 0.5), "y": height/2 + yoffset },
     147            { "x": -width/2, "y": yoffset },
     148            { "x": width*(amount - 0.5), "y": height + yoffset },
    98149            offset
    99150        );
    100151
    101         yoffset -= height * 1.2;
     152        yoffset += height * 1.2;
    102153    };
    103154
    104155    var cmpMirage = Engine.QueryInterface(this.entity, IID_Mirage);
     
    119170    else if (cmpMirage && cmpMirage.ResourceSupply())
    120171        AddBar("supply", cmpMirage.IsInfinite() ? 1 : cmpMirage.GetAmount() / cmpMirage.GetMaxAmount());
    121172
     173    return yoffset;
    122174    /*
    123175    // Rank icon disabled for now - see discussion around
    124176    // http://www.wildfiregames.com/forum/index.php?s=&showtopic=13608&view=findpost&p=212154
  • binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml

     
    1010      </Modifications>
    1111      <AuraName>Healing Aura</AuraName>
    1212      <AuraDescription>Heals nearby units at 1 HP per second.</AuraDescription>
     13      <OverlayIcon>art/textures/ui/session/auras/heal.png</OverlayIcon>
    1314    </heal>
    1415  </Auras>
    1516  <BuildRestrictions>