Ticket #3000: heropanel3.patch

File heropanel3.patch, 8.9 KB (added by Stephen Imhoff, 8 years ago)
  • binaries/data/mods/public/gui/session/session.js

    From 9a36be9a6acd2a475f108d65559f232e1feec676 Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Sat, 14 May 2016 11:03:03 +0900
    Subject: [PATCH] heros
    
    ---
     binaries/data/mods/public/gui/session/session.js   | 144 +++++++++++++++------
     .../gui/session/session_objects/hero_icon.xml      |  29 +++--
     2 files changed, 116 insertions(+), 57 deletions(-)
    
    diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js
    index f944549..a8c7591 100644
    a b const g_DefaultPopulationColor = "white";  
    88const g_PopulationAlertColor = "orange";
    99
    1010/**
     11 * Maximum number of heroes to display (must stay in sync with hero_icon.xml).
     12 */
     13const g_HeroPanelCount = 10;
     14
     15/**
    1116 * A random file will be played. TODO: more variety
    1217 */
    1318const g_Ambient = [ "audio/ambient/dayscape/day_temperate_gen_03.ogg" ];
    var g_AdditionalHighlight = [];  
    145150/**
    146151 * Blink the hero selection if that entity has lost health since the last turn.
    147152 */
    148 var g_PreviousHeroHitPoints;
     153var g_PreviousHeroes = [];
    149154
    150155/**
    151156 * Unit classes to be checked for the idle-worker-hotkey.
    function updateGUIObjects()  
    712717    if (g_ShowGuarding || g_ShowGuarded)
    713718        updateAdditionalHighlight();
    714719
    715     updateHero();
     720    updateHeroes();
    716721    updateGroups();
    717722    updateDebug();
    718723    updatePlayerDisplay();
    function updateGUIStatusBar(nameOfBar, points, maxPoints, direction)  
    788793}
    789794
    790795
    791 function updateHero()
     796function updateHeroes()
    792797{
    793798    let unitHeroPanel = Engine.GetGUIObjectByName("unitHeroPanel");
    794     let heroButton = Engine.GetGUIObjectByName("unitHeroButton");
    795 
    796799    let playerState = GetSimState().players[g_ViewedPlayer];
    797     if (!playerState || playerState.heroes.length <= 0)
     800    if (!playerState || playerState.heroes.length == 0)
    798801    {
    799         g_PreviousHeroHitPoints = undefined;
    800         unitHeroPanel.hidden = true;
     802        for (let hero of g_PreviousHeroes)
     803            Engine.GetGUIObjectByName("unitHeroButton[" + hero.button + "]").hidden = true;
     804        g_PreviousHeroes = [];
    801805        return;
    802806    }
    803807
    804     let heroImage = Engine.GetGUIObjectByName("unitHeroImage");
    805     let heroState = GetExtendedEntityState(playerState.heroes[0]);
    806     let template = GetTemplateData(heroState.template);
    807     heroImage.sprite = "stretched:session/portraits/" + template.icon;
    808     let hero = playerState.heroes[0];
    809 
    810     heroButton.onpress = function()
     808    let mapped = playerState.heroes.map(ent => {
     809        // Retain current ordering, if displayed previously.
     810        let previousIndex = g_PreviousHeroes.findIndex(hero => hero.ent == ent);
     811        if (previousIndex >= 0)
     812            return {
     813                "ent": ent,
     814                "index": previousIndex,
     815                "previous": g_PreviousHeroes[previousIndex]
     816            };
     817
     818        // Place new heroes at the end of the list.
     819        return {
     820            "ent": ent,
     821            "index": g_HeroPanelCount
     822        };
     823    }).sort((l, r) => l.index == r.index ? l.ent - r.ent : l.index - r.index);
     824
     825    let heroes = [];
     826    let usedSlots = new Array(g_HeroPanelCount).fill(false);
     827
     828    for (let displayIndex = 0; displayIndex < Math.min(g_HeroPanelCount, mapped.length); ++displayIndex)
    811829    {
    812         if (!Engine.HotkeyIsPressed("selection.add"))
    813             g_Selection.reset();
    814         g_Selection.addList([hero]);
    815     };
    816     heroButton.ondoublepress = function() { selectAndMoveTo(getEntityOrHolder(hero)); };
    817     unitHeroPanel.hidden = false;
     830        let hero = mapped[displayIndex];
     831
     832        // Find the first unused one if new, otherwise reuse previous.
     833        let buttonSlot = hero.previous ?
     834            hero.previous.button :
     835            usedSlots.findIndex(slot => !slot);
     836
     837        usedSlots[buttonSlot] = true;
     838
     839        let heroButton = Engine.GetGUIObjectByName("unitHeroButton[" + buttonSlot + "]");
     840        let heroState = GetExtendedEntityState(hero.ent);
     841        let template = GetTemplateData(heroState.template);
     842
     843        if (!hero.previous)
     844        {
     845            heroButton.onPress = function()
     846            {
     847                if (!Engine.HotkeyIsPressed("selection.add"))
     848                    g_Selection.reset();
     849                g_Selection.addList([hero.ent]);
     850            };
     851
     852            heroButton.onDoublePress = function() {
     853                selectAndMoveTo(getEntityOrHolder(hero.ent));
     854            };
     855
     856            heroButton.hidden = false;
     857
     858            // Ensure no pre-existing animations.
     859            stopColorFade("heroHitOverlay[" + buttonSlot + "]");
     860
     861            let heroImage = Engine.GetGUIObjectByName("unitHeroImage[" + buttonSlot + "]");
     862            heroImage.sprite = "stretched:session/portraits/" + template.icon;
     863        }
     864
     865        heroButton.tooltip = createHeroTooltip(heroState, template);
     866        updateGUIStatusBar("heroHealthBar[" + buttonSlot + "]",
     867                heroState.hitpoints, heroState.maxHitpoints);
    818868
     869        setPanelObjectPosition(heroButton, displayIndex, g_HeroPanelCount);
     870
     871        // If the health of the hero changed since the last update, trigger the animation.
     872        if (hero.previous && hero.previous.player == g_ViewedPlayer &&
     873            hero.previous.hitpoints > heroState.hitpoints)
     874        {
     875            startColorFade("heroHitOverlay[" + buttonSlot + "]", 100, 0,
     876                    colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
     877        }
     878
     879        heroes.push({
     880            "ent": hero.ent,
     881            "button": buttonSlot,
     882            "hitpoints": heroState.hitpoints,
     883            "player": g_ViewedPlayer
     884        });
     885    }
     886
     887    // In case heroes were removed and their slot/button was freed, hide it.
     888    for (let hero of g_PreviousHeroes.filter(prev => !usedSlots[prev.button]))
     889        Engine.GetGUIObjectByName("unitHeroButton[" + hero.button + "]").hidden = true;
     890
     891    g_PreviousHeroes = heroes;
     892}
     893
     894function createHeroTooltip(heroState, template)
     895{
    819896    // Setup tooltip
    820897    let tooltip = "[font=\"sans-bold-16\"]" + template.name.specific + "[/font]";
    821     let healthLabel = "[font=\"sans-bold-13\"]" + translate("Health:") + "[/font]";
    822     tooltip += "\n" + sprintf(translate("%(label)s %(current)s / %(max)s"), {
    823         "label": healthLabel,
     898    tooltip += "\n" + sprintf(translate("%(label)s %(current)s / %(max)s"), {
     899        "label": "[font=\"sans-bold-13\"]" + translate("Health:") + "[/font]",
    824900        "current": Math.ceil(heroState.hitpoints),
    825901        "max": Math.ceil(heroState.maxHitpoints)
    826902    });
    function updateHero()  
    830906    tooltip += "\n" + getArmorTooltip(heroState.armour);
    831907    if (template.tooltip)
    832908        tooltip += "\n" + template.tooltip;
    833 
    834     heroButton.tooltip = tooltip;
    835 
    836     // update heros health bar
    837     updateGUIStatusBar("heroHealthBar", heroState.hitpoints, heroState.maxHitpoints);
    838 
    839     let heroHP = {
    840         "hitpoints": heroState.hitpoints,
    841         "player": g_ViewedPlayer
    842     };
    843 
    844     if (!g_PreviousHeroHitPoints)
    845         g_PreviousHeroHitPoints = heroHP;
    846 
    847     // if the health of the hero changed since the last update, trigger the animation
    848     if (g_PreviousHeroHitPoints.player == heroHP.player && g_PreviousHeroHitPoints.hitpoints > heroHP.hitpoints)
    849         startColorFade("heroHitOverlay", 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
    850 
    851     g_PreviousHeroHitPoints = heroHP;
     909    return tooltip;
    852910}
    853911
    854912function updateGroups()
  • binaries/data/mods/public/gui/session/session_objects/hero_icon.xml

    diff --git a/binaries/data/mods/public/gui/session/session_objects/hero_icon.xml b/binaries/data/mods/public/gui/session/session_objects/hero_icon.xml
    index 35d7053..6219006 100644
    a b  
    22<object
    33    name="unitHeroPanel"
    44    size="0 36 50 93"
    5     hidden="true"
     5    hidden="false"
    66>
    7     <object name="unitHeroButton" size="0 0 50 50" type="button" style="iconButton"
    8         tooltip_style="sessionToolTip">
    9         <object name="unitHeroImage" size="5 5 100%-5 100%-5" type="image" ghost="true"/>
    10         <object name="heroHitOverlay" hidden="true" type="image" ghost="true" size="5 5 100%-5 100%-5"/>
    11     </object>
    12     <!-- Hero Health bar -->
    13     <object size="3 100%-7 100%-3 100%-2" name="heroHealthSection" ghost="true">
    14         <object size="0 0 100% 5" name="heroHealth" type="image" ghost="true">
    15             <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
    16             <object type="image" sprite="healthBackground" ghost="true"/>
    17             <object type="image" sprite="healthForeground" ghost="true" name="heroHealthBar"/>
    18             <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
     7    <repeat count="10" var="n">
     8        <object name="unitHeroButton[n]" size="0 0 50 50" type="button" hidden="true" style="iconButton" tooltip_style="sessionToolTip">
     9            <object name="unitHeroImage[n]" size="5 5 100%-5 100%-5" type="image" ghost="true"/>
     10            <object name="heroHitOverlay[n]" hidden="true" type="image" ghost="true" size="5 5 100%-5 100%-5"/>
     11            <!-- Hero Health bar -->
     12            <object size="3 100%-7 100%-3 100%-2" name="heroHealthSection[n]" ghost="true">
     13                <object size="0 0 100% 5" name="heroHealth[n]" type="image" ghost="true">
     14                    <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
     15                    <object type="image" sprite="healthBackground" ghost="true"/>
     16                    <object type="image" sprite="healthForeground" ghost="true" name="heroHealthBar[n]"/>
     17                    <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
     18                </object>
     19            </object>
    1920        </object>
    20     </object>
     21    </repeat>
    2122</object>