• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Struggling with math involved with Cast Bar (Lua)

Status
Not open for further replies.

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,534
So i'm using this: GenericBar

The GenericBar has 100 animations, Animation Index 0 representing an empty bar and Index 100 representing a full bar.

And i'm using it in my map to represent how long you must wait before you can take an action. The bar fills up over time and once it reaches 100% you are able to do something (it's turn-based and turns work like the Final Fantasy games).

I have the bar working just fine using the code below. This function runs once every 0.01 seconds:
Lua:
function Example()
    --CastBar = The unit using the GenericBar model
    --Increment = Integer starting at 0 that determines the animation index of CastBar
    if Increment < 100 then
        Increment = Increment + 1
        SetUnitAnimationByIndex(CastBar, Increment)
    end
end
Now how would I go about adjusting this to take into consideration increases and decreases to the rate at which the bar fills up (i'm calling it CdRate, short for Cooldown Rate).

For example, let's say I want the Cast Bar to fill up from 0 to 100% over 1.00 second by default.

Then I increase CdRate by 20% -> The Cast Bar now fills to 100% over 0.80 seconds.

Any ideas on how to make this work properly? How can I apply that to the Animation Index?


Also, I wanted to use a formula like this to determine the time that it takes for the bar to fill:
(BaseCd / (1 + CdRate)

CdRate would be equal to 0.00 by default, and increase by 0.01 for every 1% increase and decrease by 0.01 for every 1% decrease.

The part I struggle with is getting the Cast Bar (GenericBar) to reflect this using it's Animation Index.

Thanks for taking the time to read this!
 
Last edited:
Level 25
Joined
Sep 26, 2009
Messages
2,378
What you want to calculate is an inverse rule of three.
You have base speed and base time - 100% speed takes 1 second to fill the bar from 0% to 100%. Now you want to either calculate the new speed or the new time. Let's say you want the new time to be 0.8 seconds, so the question is how much you have to increase the speed in order for the new time to be equal to 0.8 sec.
Now you have three values (base speed, base time, new time) and need to calculate one variable (new speed) - hence rule of three. Since lower time means higher speed, it is inverse rule of three.

Code:
Speed                 Time
100% ................ 1.0 sec
  X% ................ 0.8 sec
You get the following calculation:
Code:
100 / X = 0.8 / 1.0
100 / X = 0.8
100 = 0.8X
125 = 1X

X = 125%

So in order for the bar to fill from 0% to 100% over 0.8 seconds, you need to set the speed to 125% (not 20% !).

Now to calculate the increment rate. In your case it is simple, because your 100% speed will fill the bar over 1 second and your functions runs every 0.01, meaning your increment rate is also 0.01.
So if you change in the above calculation the 100% speed for 0.01 rate, you get the new rate you want: 0.0125.
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,534
Thanks for the responses, unfortunately i'm still a bit confused.

So here is a function that increases the rate of which the Cast Bar (I'm calling it Action_Bar) fills up.
Action_Bar_Base = 5.0 --- This is how long it takes for the bar to fill
Action_Bar_Rate = 0.0 --- This value increases or decreases the base time
Lua:
function Increase_Rate()
    Action_Bar_Rate = Action_Bar_Rate + 0.10
    Action_Bar_Time = (Action_Bar_Base / (1 + Action_Bar_Rate))
    -- Action Bar Time = (5.0 / (1.0 + 0.10)
end
Action_Bar_Time is set to 4.54 after running this function.

Now I have a Timer that runs every 0.01 seconds:
Lua:
TimerStart(Action_Bar_Timer, 0.01, true, function()
    Increment = Increment + ?
    SetUnitAnimationByIndex(CastBar, ?)
end)
I'm lost on what to do with 4.54. How do I get an Integer value out of this that represents an Animation Index from 1 to 100?

I'll keep trying to get what you guys suggested to work for me, thanks again.
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,534
4.54 / (5 / 100) = 90.8
Math - Absolute = 90 (or 91 I'm not sure if it' rounds up.)
Thus the bar becomes 90/100

Or you can be silly.
(4.54 * 100) / (5 * 100) / 100)) = 90.8
Not sure what you mean by the bar becomes 90/100. Sorry for my ignorance.

I want it so like, if the total time it takes to fill is 5.00 seconds, then the bar would have it's animation index increased once every 0.05 seconds. So the Animation spreads evenly over the duration.

Time passed:
0.05 = play anim 1 (1% full)
0.10 = play anim 2 (2% full)
0.15 = play anim 3 (3% full)
...
4.95 = play anim 99 (99% full)
5.00 = play anim 100 (100% full)

Not sure how to get this value with a Time of 4.54. Maybe you guys already answered this and i'm just not understsanding.
 
Level 24
Joined
Feb 9, 2009
Messages
1,787
@Uncle
90 / 100 as a fraction of a bar representing 100.

X = the the current time value (currently 0.00 if it's fresh)
Y = the maximum time value (as you say 5.00 seconds.)
Z = the animation index of 100.

X(0.00) / (Y(5.00) / Z(100)) = 0

==================================
TIME passes, lets say 1.15 seconds has passed.

X(1.15) / (Y(5.00) / Z(100)) = 21
Math - Abs ()
thus 21% of the bar is filled by using this value.

==================================
TIME passes, lets say 3.45 seconds has passed.

X(3.45) / (Y(5.00) / Z(100)) = 69
Math - Abs ()
thus 69% of the bar is filled by using this value.

Also did you take a look at the map I attached, it's most likely the same bar and is doing the exact same thing.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,534
@Uncle
90 / 100 as a fraction of a bar representing 100.

X = the the current time value (currently 0.00 if it's fresh)
Y = the maximum time value (as you say 5.00 seconds.)
Z = the animation index of 100.

X(0.00) / (Y(5.00) / Z(100)) = 0

==================================
TIME passes, lets say 1.15 seconds has passed.

X(1.15) / (Y(5.00) / Z(100)) = 21
Math - Abs ()
thus 21% of the bar is filled by using this value.

==================================
TIME passes, lets say 3.45 seconds has passed.

X(3.45) / (Y(5.00) / Z(100)) = 69
Math - Abs ()
thus 69% of the bar is filled by using this value.

Also did you take a look at the map I attached, it's most likely the same bar and is doing the exact same thing.
Awesome, thank you for breaking it down like this. It makes a lot more sense to me now.

And I got it working in my map with some minor tweaks:
Lua:
--This function runs every 0.01 seconds, increasing the elapsed time (Action_Bar_Value) and calculating the Index for the Action Bar (GenericBar)
function Action_Bar_Timer(p, setindex)
    --setindex is a local integer that starts at 0 and increases over time eventually reaching 100
    if setindex < 100 then
        p.Action_Bar_Value = p.Action_Bar_Value + 0.1
        setindex = Set_Index(p)
        SetUnitAnimationByIndex(p.Action_Bar, setindex)
    end
end


--This function calculates the Animation Index using the X/Y/Z formula, which is then multiplied by 1000 to move its decimal point (so it'd be 1.0 instead of 0.001)
function Set_Index(p, i)
    return R2I((p.Action_Bar_Value[i] / p.Action_Bar_Time / 100)*1000)
end


--This function increases the rate that the bar fills which reduces the overall Time it takes to fill (default time is 5.00 seconds --- aka Action_Bar_Base)
function Increase_Action_Bar(p)
    p.Action_Bar_Rate = p.Action_Bar_Rate + 0.01
    p.Action_Bar_Time = (p.Action_Bar_Base / (1 + p.Action_Bar_Rate))
end
I couldn't get math.abs to work (not sure why) but I managed to get it all working with this approach. Thanks a bunch!
 
Last edited:
Status
Not open for further replies.
Top