Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
Now I want to make every human race player has a status bar of happyness. every 10 sec It's gonna decay as 1, while every kill of certain units It'll raise to 5 etc etc. when that happyness bar below to %70 3 random units riot etc etc %50 6 random units riot every 20 min and so on... I can make few things on that system but I think I'll need help to detecting and showing the bar by game. Any Ideas how to do it?
Now I want to make every human race player has a status bar of happyness. every 10 sec It's gonna decay as 1, while every kill of certain units It'll raise to 5 etc etc. when that happyness bar below to %70 3 random units riot etc etc %50 6 random units riot every 20 min and so on... I can make few things on that system but I think I'll need help to detecting and showing the bar by game. Any Ideas how to do it?
One easy way of having a bar is to have several dots in a floating text and shift where the color is. Say it's green and gray and each dot represents 4% or something, you'll have 25 dots. Should look decent.
I have a charge-up attack using this way of indicating current level and it lookes like this:
I do this by having a string with the "max amount of dots" like this (|c<color>.........................), with a color-indicator at the start, substring to the "correct level", put a the next color indicator (in this example a "color-reset" |r) with as many dots, then substring to correct length.
JASS:
function RiotText takes integer currentPercent returns string
local string indicatorDots = "........................."
local integer percentToDots = currentPercent / 4
local string indicatorText = "|c003C14DC" + SubString(indicatorDots, 0, percentToDots + 1) + "|r"
return indicatorText + SubString(indicatorDots, percentToDots, StringLength(indicatorDots))
endfunction
Do you get the idea?
The "currentPecent" parameter is basically number between 0-100, we calculate number of colored dots from it ("percentToDots").
We first set the "indicatorText" to the total number of dots, add color and "pick out" number of blue dots, then add "remaining" number of dots to the "indicatorText"
Call it from a GUI-trigger
Custom script: set udg_temp_string = RiotText(udg_percentInteger)
Floating Text - Change text of riot_floating_texts[(Player number of (Triggering player))] to temp_string using font size 9.00
You'll need to setup the riot_cloating_texts before doing this (create them, set their position etc.), and have a string-variable called "temp_string".
I index these with player number of Triggering player, but that should probably be something else...
well... ya know... I don't know jass yet haven't learned it but I got the idea. the problem is that bar doesn't have to be near units or something fancy. All I need a right top of selection where It'll show the percentage of total morale of race. might be bar too but It's totally optional. like I said the real point of that is understandable by player. ya know something like human campaing in reign of chaos/heartglen where It was showing the time limit of game? yea something like that but Instead It'll show just 100/100 thing. hope I clearly explained myself.
I changed it to fit his use-case better, but for simplicity, I use "how I use it" for this example.
First I have a trigger somewhere (above the "actual trigger") with this util function:
JASS:
//Max dots must be less than 25, or increase number of dots in "indicatorDots" variable to have a higher max.
function ChargeString takes integer currentDots, integer maxDots returns string
local string indicatorDots = "........................."
local string indicatorText = "|c003C14DC" + SubString(indicatorDots, 0, currentDots + 1) + "|r"
return SubString(indicatorText + SubString(indicatorDots, currentDots, StringLength(indicatorDots)), 0, 13 + maxDots) //12 chars for color-code + reset, then + 1, because index thingies...
endfunction
What it does is make first "currentDots" the hard-coded color, then "reset color" and have additional dots up to maxDots. The "|c003C14DC" is just a color and can be changed to your favorite color.
Then use it to charge up, and update a floating text, you need an integer variable that you need to keep track of "current charge" and the floatingtext.
I use a hashtable in this example.
Setup a floating text and save it.
Note that (Key ChargeUpFloatingText) is String hash.
TextSetup
Events
Unit - A unit Starts the effect of an ability
Conditions
Actions
Custom script: set udg_temp_string = ChargeString(0, 20)
Floating Text - Create floating text that reads temp_string above (Triggering unit) with Z offset 70.00, using font size 9.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Hashtable - Save Handle Of(Last created floating text) as (Key (Triggering unit)) of (Key ChargeUpFloatingText) in heroes_hash
Hashtable - Save 0 as (Key (Triggering unit)) of (Key ChargeUp Value) in heroes_hash
Trigger - Turn on TextTick <gen>
Then update it in the "tick" trigger. Update the "charge counter", update the floating text.
Note that I don't have a way of keeping track of the unit with this minimal example, but otherwise MUI (each unit can have one).
TextTick
Events
Time - Every 0.10 seconds of game time
Conditions
Actions
Set temp_unit = Bounty Hunter 0158 <gen>
Custom script: set udg_temp_integer1 = GetHandleId(udg_temp_unit)
Set temp_floating_text = (Load temp_integer1 of (Key ChargeUpFloatingText) in heroes_hashIf the label is not found, this function returns NULL.)
Set temp_integer2 = (Load temp_integer1 of (Key ChargeUp Value) from heroes_hash) + 1
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
temp_integer2 Less than 20
Then - Actions
Hashtable - Save temp_integer2 as temp_integer1 of (Key ChargeUp Value) in heroes_hash
Custom script: set udg_temp_string = ChargeString(udg_temp_integer2, 20)
Else - Actions
Hashtable - Save 0 as temp_integer1 of (Key ChargeUp Value) in heroes_hash
Custom script: set udg_temp_string = ChargeString(0, 20)
Floating Text - Change text of temp_floating_text to temp_string using font size 9.00
Also note that this example does not keep tracks of what the unit is doing, updates the floating-text-position if unit moves and it "cycles" back to 0 upon reaching the max (20).
Of course, you want to have events if channeling stops, a way of destroying the floating text, etc.
This is my "low-tech bar-system"
Was this example good?
Edit: Attached test map (saved with version 1.31.1)
Did a lot of experimentation to see what "style" I like the best, and I think some very small font with high refresh rate looks quite good (but had to increase the dot amount for 5 sec to 84). Also, I changed the hashtable to a dynamic indexing method, since I'm more comfortable with that.
But a question: Is there a way that I can only show the channel text to the caster?
JASS:
//Max dots must be less than 33, or increase number of dots in "indicatorDots" variable to have a higher max.
function ChargeString takes integer currentDots, integer maxDots returns string
local string indicatorDots = "...................................................................................."
local string indicatorText = "|c00d9ab57" + SubString(indicatorDots, 0, currentDots + 1) + "|r" + SubString(indicatorDots, currentDots, StringLength(indicatorDots))
return SubString(indicatorText, 0, 13 + maxDots) //12 chars for color-code + reset, then + 1, because index thingies...
endfunction
Text Setup Dyn
Events
Unit - A unit Starts the effect of an ability
Conditions
Actions
Set VariableSet A_Index = (A_Index + 1)
Set VariableSet A_Caster[A_Index] = (Triggering unit)
Set VariableSet A_Point[1] = (Position of A_Caster[A_Index])
Set VariableSet A_Point[2] = (A_Point[1] offset by 90.00 towards 180.00 degrees.)
Set VariableSet A_Counter[A_Index] = 0
-------- 5 sec channel --------
Set VariableSet A_Counter_Max[A_Index] = 83
Set VariableSet A_Mod[A_Index] = 0
-------- --------
Custom script: set udg_temp_string = ChargeString(0, udg_A_Counter_Max[udg_A_Index])
-------- --------
Floating Text - Create floating text that reads temp_string at A_Point[2] with Z offset 95.00, using font size 4.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Set VariableSet A_Text[A_Index] = (Last created floating text)
Thanks Uncle, can you please check the below trigger to check if that is correct? (the 2nd one)
@ThompZon I adjusted the trigger again a bit, and I think now it looks even better than before:
The bar is now always the same size (150 blocks), but the speed at which it fills can be adjusted based on the channel time.
Java:
//Max dots must be less than 151, or increase number of dots in "indicatorDots" variable to have a higher max.
function ChargeString takes integer currentDots, integer maxDots returns string
local string indicatorDots = "lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
local string indicatorText = "|c00d9ab57" + SubString(indicatorDots, 0, currentDots + 1) + "|r" + SubString(indicatorDots, currentDots, StringLength(indicatorDots))
return SubString(indicatorText, 0, 13 + maxDots) //12 chars for color-code + reset, then + 1, because index thingies...
endfunction
Text Setup Dyn
Events
Unit - A unit Starts the effect of an ability
Conditions
Actions
Set VariableSet A_Index = (A_Index + 1)
Set VariableSet A_Caster[A_Index] = (Triggering unit)
Set VariableSet A_Point[1] = (Position of A_Caster[A_Index])
Set VariableSet A_Point[2] = (A_Point[1] offset by 87.00 towards 180.00 degrees.)
Set VariableSet A_Counter[A_Index] = 0.00
-------- --------
-------- SELECT THE CHANNEL TIME, E.G 2 = 2 SECONDS --------
Set VariableSet A_ChannelTick[A_Index] = ((150.00 / 2.00) x 0.03)
-------- --------
Custom script: set udg_temp_string = ChargeString(0, 150)
-------- --------
Floating Text - Create floating text that reads temp_string at A_Point[2] with Z offset 95.00, using font size 2.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Set VariableSet A_Text[A_Index] = (Last created floating text)
Floating Text - Hide A_Text[A_Index] for (All players)
Custom script: if GetLocalPlayer() == GetTriggerPlayer() then
Floating Text - Show A_Text[A_Index] for (All players matching ((Matching player) Equal to (Owner of A_Caster[A_Index])).)
You don't need to check for Local Players. You can Hide/Show floating text for a specific player.
Delete this:
Custom script: if GetLocalPlayer() == GetTriggerPlayer() then
Custom script: endif
And simplify it to this:
Floating Text - Show (Last created floating text) for (Player group((Triggering player)))
^ Note that this leaks a Player Group.
Also, you may get some floating point error issues since you're increasing a real (A_Counter). It's value may get rounded down. You can use an Integer to count up the number of Ticks needed to get around this issue.
One last unimportant thing, you don't need to Turn Off/Turn On the trigger since it uses a Timer which can be Paused. That's only necessary for Periodic Interval Events since they don't turn off otherwise.
The bar is now always the same size (150 blocks), but the speed at which it fills can be adjusted based on the channel time.
Java:
//Max dots must be less than 151, or increase number of dots in "indicatorDots" variable to have a higher max.
function ChargeString takes integer currentDots, integer maxDots returns string
local string indicatorDots = "lllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll"
local string indicatorText = "|c00d9ab57" + SubString(indicatorDots, 0, currentDots + 1) + "|r" + SubString(indicatorDots, currentDots, StringLength(indicatorDots))
return SubString(indicatorText, 0, 13 + maxDots) //12 chars for color-code + reset, then + 1, because index thingies...
endfunction
Text Setup Dyn
Events
Unit - A unit Starts the effect of an ability
Conditions
Actions
Set VariableSet A_Index = (A_Index + 1)
Set VariableSet A_Caster[A_Index] = (Triggering unit)
Set VariableSet A_Point[1] = (Position of A_Caster[A_Index])
Set VariableSet A_Point[2] = (A_Point[1] offset by 87.00 towards 180.00 degrees.)
Set VariableSet A_Counter[A_Index] = 0.00
-------- --------
-------- SELECT THE CHANNEL TIME, E.G 2 = 2 SECONDS --------
Set VariableSet A_ChannelTick[A_Index] = ((150.00 / 2.00) x 0.03)
-------- --------
Custom script: set udg_temp_string = ChargeString(0, 150)
-------- --------
Floating Text - Create floating text that reads temp_string at A_Point[2] with Z offset 95.00, using font size 2.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Set VariableSet A_Text[A_Index] = (Last created floating text)
Floating Text - Hide A_Text[A_Index] for (All players)
Custom script: if GetLocalPlayer() == GetTriggerPlayer() then
Floating Text - Show A_Text[A_Index] for (All players matching ((Matching player) Equal to (Owner of A_Caster[A_Index])).)
Cool. Looks good.
For a channeling bar, this looks better than dots for sure!
If you have an arcade-style charging up attack, dots might look better than "l" for that case
Floating Text - Create floating text that reads Channel_String at Channel_Point[2] with Z offset 95.00, using font size 2.00, color (100.00%, 100.00%, 100.00%), and 0.00% transparency
Set VariableSet Bl_Text[Bl_Index] = (Last created floating text)
Floating Text - Hide Bl_Text[Bl_Index] for (All players)
Set VariableSet Global_PlayerGroup = (Player group((Triggering player)))
Floating Text - Show Bl_Text[Bl_Index] for Global_PlayerGroup
Also, you may get some floating point error issues since you're increasing a real (A_Counter). It's value may get rounded down. You can use an Integer to count up the number of Ticks needed to get around this issue.
My thinking was: I have 150 "blocks to fill" in for example 2 seconds (2 second channel time). Since my timer works on a 0.03 interval, I need to fill the block by 2.25 units per interval, for it to be full in 2 seconds.
with integer numbers (which I understood can only be whole numbers), I cannot do this calculation. Or did you have a different solution?
The floating point thing is more of an issue when you need precision like: If DurationVariable Equal to 5.00 then do stuff...
In your case it's fine, I just wanted to mention it so that you're aware in the future when working with Reals like this.
But what people usually do to account for the floating point error is add a very small amount to their calculation like for example:
Set RealDuration = RealDuration + 0.03
Set IntDuration = Int(RealDuration + 0.001)
So when RealDuration is converted to an Integer it's also increased by 0.001 beforehand. This way if it was at a value like 0.99999 when it was supposed to be 1.0, it will be bumped up to a value that's equal to or slightly greater than 1.0 and as a result the conversion rounding will be correct. The floating point error is always an extremely small lack of precision that results in the value being slightly smaller.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.