System Floating Bars

Steel

Software Engineer
Version History:
Version 2.4:
-Greatly Simplified Code
-Fixed a string concatenation issue causing the system to crash

Version 2.3:
-Better map cleanup
-Better unit indexation
-Added in function RemoveBarUnit
-Modified existing functions for better leak / crash protection
-Split Gradient functions and Floating Bars into separate libraries
-Speed optimized

Version 2.2:
-Map properly cleans memory leaks.
-Mana bar properly disappears.
-Changed the syntax for AddBar, it takes in a boolean now. Example: call AddBar(u, true). The boolean of true or false tells the function if we want the mana bar added or not.
-Combined the Config trigger with the globals with the main structure of the system
Version 2.1:
-Map now tracks mana.
Version 2.0:
-Initial Release



FAQ
Q: Can this work for heroes/specific units exclusively?
A: Yes! You as the user determine which units have the bars above them. Please read the How to Use section below. It will be very useful.

Q: What is use? The game can have health bars already!
A: This was originally designed to show the HP bar without having to hold alt. The WC3 Engine now supports showing the health bar forever, but my system now also shows mana above the unit. You also are not required to have both the health and mana bar, you can have just the mana bar shown without the health. It's up to you.

Q: How does it work?
A: This system uses the ability of structs to house information. The older system used handles which made it very slow. This new system is much faster since it uses globals. The system doesn't use multiple timers to track each texttag, this is highly inefficient and extremely slow. The system uses 1 timer that traverses over every unit in the array and updates the texttags this way.


Requirements
-vJASS

Implementation
Step 1a - Copy the Category Floating Bars
Step 1b - Paste what you just copied into your map
Step 1c - Save your Map, any compile errors mean that you have pasted improperly or you do not use vJASS

Advanced Users Only
Step 2a - You can change the variables in the Configurables if you know how they will react


Functions to Use:
You should only ever use the following 2 functions
Basic Users:
AddBar(u, life, mana)
RemoveBarUnit(u)


Advanced Users:
function Addbar takes unit u, boolean life, boolean mana returns nothing
function RemoveBarUnit takes unit u returns boolean //If boolean returns false, unit is not found and it has no bars on it.

AddBar will create a bar ontop of the unit you deem. The boolean life and mana tell the system what you want to track.
For example say we just created a unit, you want to track the unit's life and mana you would do this DIRECTLY after you create the unit

//Track the last created unit's life and mana
call AddBar(bj_lastCreatedUnit, true, true)

//Track the last created unit's mana only
call AddBar(bj_lastCreatedUnit, false, true)

//Track the last created unit's life only
call AddBar(bj_lastCreatedUnit, true, false)

Starting to see the picture?

Now that you know how to add a bar, let me show you how to Add a bar....lets remove:
call RemoveBarUnit(GetTriggerUnit())

Very simple.

Floating Bars v2.4
JASS:
library FloatingBars initializer FloatingInit requires Gradient

globals

//========================================================================
//**********************    Configurable Settings!                     ********************
//========================================================================

string DisplayCharacter = "'"   //Character intended for display
integer BarLength       = 30    //How many DisplayCharacters are used
real BarSize            = 11.00 //Size of the text
real XOffSet            = -35.00//Offset over the unit by X
real YOffSet            = -40.00//Offset over the unit by Y
real XOffSetM           = -35.  //Offset over the unit by X (Mana version)
real YOffSetM           = -55.     //Offset over the unit by Y (Mana version)
real Frequency          = .04   //Recurrence of the timer that tracks the system

//========================================================================
//**********************DO NOT MODIFY BELOW THIS LINE!********************
//========================================================================

integer FS_MAX_BARS    = 100
integer FS_CURR_BARS   = 0
FloatingStruct array structlink
integer FS_COUNT = 0
endglobals

struct FloatingStruct
unit u
texttag t
texttag tm
    static method create takes unit whichUnit, boolean life, boolean mana returns FloatingStruct
        local FloatingStruct fs = FloatingStruct.allocate()
        set fs.u = whichUnit
        if life then
            if FS_CURR_BARS<=100 then
                set fs.t    = CreateTextTag()
                set FS_CURR_BARS=FS_CURR_BARS+1
                call SetTextTagText(fs.t, "|c0000FF00", BarSize * 0.023 / 10)
                call SetTextTagPos(fs.t,GetUnitX(whichUnit)+XOffSet,GetUnitY(whichUnit)+YOffSet,200)
                call SetTextTagPermanent(fs.t,true)
                call SetTextTagColor(fs.t,255,255,255,255)
                call SetTextTagVisibility(fs.t,IsUnitVisible(fs.u,GetLocalPlayer()))
            debug else
            debug call BJDebugMsg("Text tax limit reached")
            endif
        endif

        if ((GetUnitState(whichUnit, UNIT_STATE_MANA)>1) and mana) then
            if FS_CURR_BARS<=100 then           
                set fs.tm    = CreateTextTag()
                debug call BJDebugMsg("Text Tag Created")
                set FS_CURR_BARS=FS_CURR_BARS+1
                call SetTextTagText(fs.tm, "|c000000FF", BarSize * 0.023 / 10)
                call SetTextTagPos(fs.tm,GetUnitX(whichUnit)+XOffSetM,GetUnitY(whichUnit)+YOffSetM,200)
                call SetTextTagPermanent(fs.tm,true)
                call SetTextTagColor(fs.tm,255,255,255,255)
                call SetTextTagVisibility(fs.tm,IsUnitVisible(fs.u,GetLocalPlayer()))
            debug else
            debug call BJDebugMsg("Text tax limit reached")
            endif
        endif
        return fs
    endmethod

    private method onDestroy takes nothing returns nothing
    set this.u = null
    
    if (not(this.t==null)) then
        call DestroyTextTag(this.t)
        set FS_CURR_BARS=FS_CURR_BARS-1
        set this.t=null
    endif
    
    if (not(this.tm==null)) then
        call DestroyTextTag(this.tm)
        set FS_CURR_BARS=FS_CURR_BARS-1
        set this.tm=null
    endif    
    
    set FS_COUNT=FS_COUNT-1
    endmethod
endstruct

function RecycleIndex takes integer i returns nothing
loop
    exitwhen i>FS_COUNT
    set structlink<i>=structlink[i+1]
    set i = i + 1
endloop
endfunction

function RemoveBarInt takes integer i returns nothing
call structlink<i>.destroy()
call RecycleIndex(i)
endfunction

function FindUnitIndex takes unit u returns integer
local integer i = 1
loop
    exitwhen ((i&gt;FS_COUNT) or (structlink<i>.u==null))
    if structlink<i>.u==u then
        return i
    endif
    set i = i + 1
endloop
return -1
endfunction

function RemoveBarUnit takes unit u returns boolean
local integer i = FindUnitIndex(u)
if (i==-1) then
    debug call BJDebugMsg(&quot;Error unit not in index&quot;)
    return false
else
    call RemoveBarInt(i)
endif
return true
endfunction

function UpdateBar takes integer in, string barstr, texttag t, unitstate curr, unitstate max returns nothing
    local integer   i       = 0
    local integer   j       = 0
    local boolean   update  = false   

        loop
            exitwhen i==BarLength
            if (not update) and (GetUnitState(structlink[in].u, curr) &lt; (i * ((GetUnitState(structlink[in].u, max))/BarLength))+1) then
                set update = true
                set barstr = barstr+&quot;|r|cFF000000&quot;
            else
                set barstr = barstr+DisplayCharacter
            endif
            set i = i + 1
        endloop
        set barstr = barstr+&quot;|r&quot;    
        call SetTextTagText(t, barstr, BarSize * 0.023 / 10)
        call SetTextTagVisibility(t,IsUnitVisible(structlink[in].u,GetLocalPlayer()))

endfunction

function BarTimer takes nothing returns nothing
    local integer i=0

    loop
        exitwhen (i&gt;FS_COUNT or structlink<i>.u==null)
        if (not(structlink<i>.t==null)) then
            call UpdateBar(i,&quot;|c00&quot;+gradientchild(GetUnitState(structlink<i>.u, UNIT_STATE_LIFE),GetUnitState(structlink<i>.u, UNIT_STATE_MAX_LIFE)), structlink<i>.t, UNIT_STATE_LIFE, UNIT_STATE_MAX_LIFE)
            call SetTextTagPos(structlink<i>.t,GetUnitX(structlink<i>.u)+XOffSet,GetUnitY(structlink<i>.u)+YOffSet,180)            
            debug else
            debug call BJDebugMsg(&quot;structlink<i>.t == null&quot;)
        endif
        
        
        //Mana        
        if (not(structlink<i>.tm==null)) then
            call UpdateBar(i,&quot;|c000000FF&quot;, structlink<i>.tm, UNIT_STATE_MANA, UNIT_STATE_MAX_MANA)
            call SetTextTagPos(structlink<i>.tm,GetUnitX(structlink<i>.u)+XOffSetM,GetUnitY(structlink<i>.u)+YOffSetM,180)       
            debug else
            debug call BJDebugMsg(&quot;structlink<i>.tm == null&quot;)
        endif      
        
        if GetUnitState(structlink<i>.u, UNIT_STATE_LIFE) &lt;= 0 then
        call RemoveBarInt(i)
        endif             
        
        
        set i=i+1        
    endloop 
endfunction

function AddBar takes unit u, boolean life, boolean mana returns nothing
if (not(FindUnitIndex(u)==-1)) then
debug call BJDebugMsg(&quot;Error: Duplicate Floating Bar Creation Called&quot;)
return
endif
set structlink[FS_COUNT] = FloatingStruct.create(u, life, mana)
set FS_COUNT = FS_COUNT + 1
endfunction

function FloatingInit takes nothing returns nothing
local timer t = CreateTimer()
set FS_COUNT = 0
call TimerStart(t,Frequency,true,function BarTimer)
endfunction
endlibrary
</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>


Gradient v2.4
JASS:
library Gradient
function s2hex takes string str returns integer
if (str == &quot;F&quot;) then
return 15
elseif (str==&quot;E&quot;) then
return 14
elseif (str==&quot;D&quot;) then
return 13
elseif (str==&quot;C&quot;) then
return 12
elseif (str==&quot;B&quot;) then
return 11
elseif (str==&quot;A&quot;) then
return 10
endif
return S2I(str)
endfunction

function hex2s takes integer i returns string
if (i == 15) then
return &quot;F&quot;
elseif (i==14) then
return &quot;E&quot;
elseif (i==13) then
return &quot;D&quot;
elseif (i==12) then
return &quot;C&quot;
elseif (i==11) then
return &quot;B&quot;
elseif (i==10) then
return &quot;A&quot;
elseif (i&gt;15) then
return &quot;F&quot;
elseif (i&lt;0) then
return &quot;0&quot;
endif
return I2S(i)
endfunction

function gradient takes string str returns string
local integer i = 1
local string r1 = SubString(str,0,1)
local string r2 = SubString(str,1,2)
local string g1 = SubString(str,2,3)
local string g2= SubString(str,3,4)
local string b1 = SubString(str,4,5)
local string b2 = SubString(str,5,6)
local integer x
    set x = s2hex(r1)+2
    set r1 = hex2s(x)
    
    set x = s2hex(r2)+2
    set r2 = hex2s(x)
    
    set x = s2hex(g1)-2
    set g1 = hex2s(x)
    
    set x=s2hex(g2)-2
    set g2 = hex2s(x)  
    set str = r1+r2+g1+g2+b1+b2

return str
endfunction

function gradientchild takes real curr, real max returns string
local integer i = 1
local string str = &quot;00FF00&quot;
local real percent = (curr/max)*100
local integer x = R2I((100-percent)/12.5)
        loop
            exitwhen i&gt;x
            set str = gradient(str)
            set i = i +1
        endloop
return str
endfunction
endlibrary

Screenshot:


Download Me (v2.4)!
Download Me (v2.3)!
Download Me (v2.2)!
Download Me (v2.1)!
Download Me (v2.0)!
 

Attachments

Insane!

Shh I didn't edit this, go away.
Ehh not too usefull, but cool :)
could you make a version thake floats below there feet?

and looks like its vjass is it?
 

Steel

Software Engineer
Ehh not too usefull, but cool :)
could you make a version thake floats below there feet?

and looks like its vjass is it?
It could float at there feet, configure it. There is an XOffSet and YOffSet that you can change to modify the location of the bar in respect to the unit.

Yes it is in vJass
 

cr4xzZz

Also known as azwraith_ftL.
>Ehh not too usefull, but cool
Excuse me? It is useful in my opinion. A lot useful. Many maps need something like this, like DotA for example. +rep for the sys
 

cr4xzZz

Also known as azwraith_ftL.
> It wont go into the map.
Requires NewGen editor. I think he didn't note that in the first post...
 

Steel

Software Engineer
Does it remove the bar when the unit dies?

Also, there's a limit of 99 floating texts at once.
Yup, there is a simple check in there if the unit's current life is 0 it calls the remove function.

As for 99 floating texts, I think that's actually plenty. Essentially with this system you could use AddBar to whatever unit you would like and not EVERY unit.
 

xfirenzx

New Member
Hey, I just tested this and the mana bar did not disappear. Hopefully you can fix that in future versions because i would really like to use this in my map (I will give credit).
 

Steel

Software Engineer
Hey, I just tested this and the mana bar did not disappear. Hopefully you can fix that in future versions because i would really like to use this in my map (I will give credit).
Fixed in version 2.2

Moderators: What does this system need to be approved?
 

Cidzero

Imma firin mah lazer!!!1!1
They want perfection.

And very nice, if only I didn't use so many units at the same time I could use :(
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
You should really add some debug message as a warning and code to stop the system when the amount of bars is reaching about 80 , to prevent people from extreme usage.

This system is quite useful for something like, coding a custom barrier, which is completely triggered barrier. It can act as the barrier's hp bar.
(This might also require modification on system thought)
 

Steel

Software Engineer
This system is quite useful for something like, coding a custom barrier, which is completely triggered barrier. It can act as the barrier's hp bar.
(This might also require modification on system thought)
That is the exact reason I created this system for my own map.
 

PurgeandFire

zxcvmkgdfg
Is NewGen editor better than World Editor? If it is.. Where should I download it?
Yes, it has extra features for JASS, but not for GUI. It helps the map though, with the DLLs mainly like War3err. You can go to the "Extensions" tab to enable/disable certain stuff. Then you can test the map by saving it and opening it in NewGen wc3.

Great system, probably most useful for RPGs.
 

PurgeandFire

zxcvmkgdfg
Haha, oddly the new patch can have you press ALT and keep it like that. :p

But this is still useful for specifications and mana...
 

Gripen2

New Member
Is it possible to make the bars only on one unit instead of all.

Like the bars display only on the ( Cant remember the word :banghead: ) "Speficied" unit.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    My grandmother just passed away, she was 95. I might be going to Florida for a week.
  • The Helper The Helper:
    I have a buddy in Florida who has an extra office space for me with a computer so I can do anything so likely I will be going up there wednesday or thursday
  • Ghan Ghan:
    Let me know if there's anything I can do to help.
  • The Helper The Helper:
    thank you Ghan
  • jonas jonas:
    Sorry for your loss
    +1
  • Varine Varine:
    I'm sorry to hear that bro
  • Varine Varine:
    Not to distract but is anyone aware of any software to help visually impaired people interact with their PC?
  • Varine Varine:
    Also what's the best way to ship a PC? Should I just wrap the fuck out of it in the case or put the components in static bags and wrapped up individually?
  • Ghan Ghan:
    The GPU is the biggest danger typically.
  • Ghan Ghan:
    Some of the pre-built vendors use expanding foam to fill in the case and secure the GPU. Otherwise it might be best to remove it and ship it separately.
  • Ghan Ghan:
    Similar if the machine has a large tower CPU cooler installed. Those can experience huge forces and destroy the socket during shipment if they are heavy.
  • Varine Varine:
    So mainly just the heavier things that jut out? I'm planning on pulling out the SSD's too and anything that I don't have well secured. I'll probably be good leaving the motherboard and PSU screwed in there though if I bundle it up?
  • Ghan Ghan:
    Yeah, I'd expect those to be fine. It's mainly the heavy stuff that is also long/tall where dropping the case would cause it to exert a ton of force on the mount. The motherboard will be fine screwed into the board unless the case itself is somehow severely damaged.
  • Varine Varine:
    I have the original packaging for it, so I was going to just put it back in there
  • Varine Varine:
    I don't think I have the boxes for the components though and so I don't want to have a bunch of loose shit bouncing around
  • The Helper The Helper:
    damn I just read that lol
  • The Helper The Helper:
    when i read up and saw spray in foam I was like oh shit
  • The Helper The Helper:
    going to do the last controller giveaway in the NUON Dome forum because I just cannot sell them since I got them for free from a deceased NUON Legend. It is my last one from that.

    Members online

    No members online now.

    Affiliates

    Hive Workshop NUON Dome
    Top