Ticket #1902: hero_health.patch

File hero_health.patch, 11.5 KB (added by Michael, 10 years ago)

Hero healthbar and faded color overlay in case of attack.

  • binaries/data/mods/public/gui/common/colorFades.js

     
     1/*
     2    DESCRIPTION : Some functions to make colour fades on GUI elements (f.e. used for hero and group icons)
     3    NOTES       :
     4*/
     5
     6// Used for storing object names of running color fades in order to stop them, if the fade is restarted before the old ended
     7var g_colorFade = {};
     8g_colorFade["id"] = {};
     9g_colorFade["tick"] = {};
     10
     11/**
     12 * starts fading a colour of a GUI object using the sprite argument
     13 * name: name of the object which colour should be faded
     14 * changeInterval: interval in ms when the next colour change should be made
     15 * duration: maximal duration of the complete fade
     16 * colour: RGB + opacity object with keys r,g,b and o
     17 * fun_colorTransform: function which transform the colors;
     18 *                    arguments: [colour object, tickCounter]
     19 * fun_smoothRestart [optional]: a function, which returns a smooth tick counter, if the fade should be started;
     20 *                              arguments: [tickCounter of current fade; not smaller than 1 or it restarts at 0] returns: smooth tick counter value
     21 * tickCounter [optional]: should not be set by hand! - how often the function was called recursively
     22 */
     23function fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)
     24{
     25    // get the overlay
     26    var overlay = Engine.GetGUIObjectByName(name);
     27    if (overlay)
     28    {
     29        // check, if fade overlay was started just now
     30        if (!tickCounter)
     31        {
     32            tickCounter = 1;
     33            overlay.hidden = false;
     34                       
     35            // check, if another animation is running and restart it, if it's the case
     36            if (isColourFadeRunning(name))
     37            {
     38                restartColourFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, g_colorFade.tick[name]);
     39                return;
     40            }
     41        }
     42       
     43        // get colors
     44        fun_colorTransform(colour, tickCounter);
     45       
     46        // set new colour
     47        overlay.sprite="colour: "+colour.r+" "+colour.g+" "+colour.b+" "+colour.o;
     48
     49        // recusive call, if duration is positive
     50        duration-= changeInterval;
     51        if (duration > 0 && colour.o > 0)
     52        {
     53            var id = setTimeout(function() { fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, ++tickCounter); }, changeInterval);
     54            g_colorFade.id[name] = id;
     55            g_colorFade.tick[name] = tickCounter;
     56        }
     57        else {
     58            overlay.hidden = true;
     59            stopColourFade(name);
     60        }
     61    }
     62}
     63
     64
     65/**
     66 * checks, if a colour fade on that object is running
     67 * name: name of the object which colour fade should be checked
     68 * return: true a running fade was found
     69 */
     70function isColourFadeRunning(name)
     71{
     72    return name in g_colorFade.id;
     73}
     74
     75/**
     76 * stops fading a colour
     77 * name: name of the object which colour fade should be stopped
     78 * return: true a running fade was stopped
     79 */
     80function stopColourFade(name, doNotHideOverlay)
     81{
     82    if (isColourFadeRunning(name))
     83    {
     84        clearTimeout(g_colorFade.id[name]);
     85        delete g_colorFade.id[name];
     86        delete g_colorFade.tick[name];
     87       
     88        // get the overlay and hide it
     89        if (doNotHideOverlay != true)
     90        {
     91            var overlay = Engine.GetGUIObjectByName(name);
     92            if(overlay)
     93                overlay.hidden = true;
     94        }
     95   
     96        return true;
     97    }
     98    return false;
     99}
     100
     101/**
     102 * restarts a colour fade
     103 * see paramter in fadeColour function
     104 */
     105function restartColourFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)
     106{
     107    if (isColourFadeRunning(name))
     108    {
     109        // check, if fade can be restarted smoothly
     110        if (fun_smoothRestart)
     111        {
     112            tickCounter = fun_smoothRestart(colour, tickCounter);
     113            // set new function to existing timer
     114            var fun = function() { fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter); };
     115            setNewTimerFunction(g_colorFade.id[name], fun);
     116        }
     117        // stop it and restart it
     118        else
     119        {
     120            stopColourFade(name, true);
     121            fadeColour(name, changeInterval, duration, colour, fun_colorTransform);
     122        }
     123    }
     124}
     125
     126/********************************************************************************************************/
     127/*                                      PREDEFINED FUNCTIONS                                            */
     128/********************************************************************************************************/
     129
     130/**
     131 * rgb: colour object with keys r,g,b and o
     132 * tickCounter: how often the fade was executed
     133 */
     134function colourFade_attackUnit(rgb, tickCounter)
     135{
     136
     137    // blinking
     138    if (tickCounter < 50)
     139    {
     140        // slow that process down
     141        if (tickCounter%5 != 0)
     142            return;
     143           
     144        rgb.g = rgb.g == 0 ? 255 : rgb.g = 0;
     145        rgb.b = rgb.b == 0 ? 255 : rgb.b = 0;
     146    }
     147    // wait a short time and then colour fade from red to grey to nothing
     148    else if ( tickCounter > 54)
     149    {
     150        rgb.g = rgb.g < 255 ? rgb.g += 3*Math.sqrt(tickCounter-50) : 255;
     151        rgb.b = rgb.g;
     152       
     153        // start with fading it out
     154        if (rgb.g > 100)
     155            rgb.o = rgb.o > 3 ? rgb.o -= 3 : 0;
     156    }
     157}
     158
     159/**
     160 * makes a smooth fade, if the attack on the unit has not stopped yet
     161 * rgb: colour object with keys r,g,b and o
     162 * tickCounter: how often the fade was executed
     163 */
     164function smoothColourFadeRestart_attackUnit(rgb, tickCounter)
     165{
     166    // check, if in blinking phase
     167    if (tickCounter < 50)
     168    {
     169        // get rgb to current state
     170        for (var i = 1; i <= tickCounter; i++)
     171            colourFade_attackUnit(rgb, i);
     172        // set the tick counter back to start
     173        return (tickCounter%10)+1;
     174    }
     175    return 1;
     176}
     177 No newline at end of file
  • binaries/data/mods/public/gui/common/timer.js

     
    44
    55/**
    66 * Set a timeout to call func() after 'delay' msecs.
     7 * func: function to call
     8 * delay: delay in ms
    79 * Returns an id that can be passed to clearTimeout.
    810 */
    911function setTimeout(func, delay)
     
    1315    return id;
    1416}
    1517
     18/**
     19 * deletes a timer
     20 * id: of the timer
     21 */
    1622function clearTimeout(id)
    1723{
    1824    delete g_Timers[id];
     
    1925}
    2026
    2127/**
     28* alters an function call
     29* id: of the timer
     30* func: function to call
     31*/
     32function setNewTimerFunction(id, func)
     33{
     34    if (id in g_Timers) {
     35        g_Timers[id][1] = func;
     36    }
     37}
     38
     39/**
    2240 * If you want to use timers, then you must call this function regularly
    2341 * (e.g. in a Tick handler)
    2442 */
  • binaries/data/mods/public/gui/session/session.js

     
    5151var g_ShowGuarded = false;
    5252var g_AdditionalHighlight = [];
    5353
     54// for saving the hitpoins of the hero (is there a better way to do that?)
     55var g_heroHitpoints = undefined;
     56
    5457function GetSimState()
    5558{
    5659    if (!g_SimState)
     
    485488    var battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());
    486489    if (battleState)
    487490        global.music.setState(global.music.states[battleState]);
     491   
    488492}
    489493
     494/**
     495* updates a status bar on the GUI
     496* nameOfBar: name of the bar
     497* points: points to show
     498* maxPoints: max points
     499* direction: gets less from (right to left) 0; (top to bottom) 1; (left to right) 2; (bottom to top) 3;
     500*/
     501function updateGUIStatusBar(nameOfBar, points, maxPoints, direction)
     502{
     503    // check, if optional direction parameter is valid.
     504    if (!direction || !(direction>=0 && direction<4))
     505        direction = 0;
     506
     507    // get the bar and update it
     508    var statusBar = Engine.GetGUIObjectByName(nameOfBar);
     509    if (statusBar)
     510    {
     511        var healthSize = statusBar.size;
     512        var value = 100*Math.max(0, Math.min(1, points / maxPoints));
     513       
     514        // inverse bar
     515        if(direction == 2 || direction == 3)
     516            value = 100 - value;
     517
     518        if(direction == 0)
     519            healthSize.rright = value;
     520        else if(direction == 1)
     521            healthSize.rbottom = value;
     522        else if(direction == 2)
     523            healthSize.rleft = value;
     524        else if(direction == 3)
     525            healthSize.rtop = value;
     526       
     527        // update bar
     528        statusBar.size = healthSize;
     529    }
     530}
     531
     532
    490533function updateHero()
    491534{
    492535    var simState = GetSimState();
    493536    var playerState = simState.players[Engine.GetPlayerID()];
     537    var unitHeroPanel = Engine.GetGUIObjectByName("unitHeroPanel");
    494538    var heroButton = Engine.GetGUIObjectByName("unitHeroButton");
    495539
    496540    if (!playerState || playerState.heroes.length <= 0)
    497541    {
    498         heroButton.hidden = true;
     542        g_heroHitpoints = undefined;
     543        unitHeroPanel.hidden = true;
    499544        return;
    500545    }
    501546
     
    512557        g_Selection.addList([hero]);
    513558    };
    514559    heroButton.ondoublepress = function() { selectAndMoveTo(getEntityOrHolder(hero)); };
    515     heroButton.hidden = false;
     560    unitHeroPanel.hidden = false;
    516561
    517562    // Setup tooltip
    518563    var tooltip = "[font=\"serif-bold-16\"]" + template.name.specific + "[/font]";
     
    527572    tooltip += "\n" + template.tooltip;
    528573
    529574    heroButton.tooltip = tooltip;
    530 };
     575   
     576    // update heros health bar
     577    updateGUIStatusBar("heroHealthBar", heroState.hitpoints, heroState.maxHitpoints);
     578   
     579    // define the hit points if not defined
     580    if (!g_heroHitpoints)
     581        g_heroHitpoints = heroState.hitpoints;
     582   
     583    // check, if the health of the hero changed since the last update
     584    if (heroState.hitpoints < g_heroHitpoints)
     585    {   
     586        g_heroHitpoints = heroState.hitpoints;
     587        // trigger the animation
     588        fadeColour("heroHitOverlay", 100, 10000, {"r": 175,"g": 0,"b": 0,"o": 100}, colourFade_attackUnit, smoothColourFadeRestart_attackUnit);
     589        return;
     590    }
     591}
    531592
     593
     594
    532595function updateGroups()
    533596{
    534597    var guiName = "Group";
  • binaries/data/mods/public/gui/session/session.xml

     
    77    <script file="gui/common/functions_global_object.js" />
    88    <script file="gui/common/music.js"/>
    99    <script file="gui/common/timer.js"/>
     10    <script file="gui/common/colorFades.js"/>
    1011    <script file="gui/session/session.js"/>
    1112    <script file="gui/session/selection.js"/>
    1213    <script file="gui/session/placement.js"/>
     
    864865    <!-- ================================  ================================ -->
    865866    <!-- Hero Selection -->
    866867    <!-- ================================  ================================ -->
    867     <object
     868<object
    868869        name="unitHeroPanel"
    869         size="0 36 50 86"
     870        size="0 36 50 93"
     871        hidden="true"
    870872    >
    871         <object name="unitHeroButton" size="0 0 50 50" type="button" hidden="false" style="iconButton"
     873        <object name="unitHeroButton" size="0 0 50 50" type="button" style="iconButton"
    872874            tooltip_style="sessionToolTip" tooltip="Attack and Armor">
    873875            <object name="unitHeroImage" size="5 5 100%-5 100%-5" type="image" ghost="true"/>
     876            <object name="heroHitOverlay" hidden="true" type="image" ghost="true" size="5 5 100%-5 100%-5"/>
    874877        </object>
     878        <!-- Hero Health bar -->
     879            <object size="3 100%-7 100%-3 100%-2" name="heroHealthSection" ghost="true">
     880                <object size="0 0 100% 5" name="heroHealth" type="image" ghost="true">
     881                    <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
     882                    <object type="image" sprite="healthBackground" ghost="true"/>
     883                    <object type="image" sprite="healthForeground" ghost="true" name="heroHealthBar"/>
     884                    <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
     885                </object>
     886            </object>
     887        <!-- Hit overlay -->
     888       
    875889    </object>
    876890   
    877891    <!-- ================================  ================================ -->