System Floating Bars

Steel

Software Engineer
Reaction score
109
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:
floating1.jpg


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

Attachments

  • Floating Bars2.0.w3x
    20.2 KB · Views: 656

Insane!

Shh I didn't edit this, go away.
Reaction score
122
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
Reaction score
109
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
 

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
Post the code of FloatingGlobals too?
 

cr4xzZz

Also known as azwraith_ftL.
Reaction score
51
>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.
Reaction score
51
> It wont go into the map.
Requires NewGen editor. I think he didn't note that in the first post...
 

Steel

Software Engineer
Reaction score
109
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
Reaction score
7
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
Reaction score
109
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
Reaction score
39
They want perfection.

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

~GaLs~

† Ғσſ ŧħə ѕαĸε Φƒ ~Ğ䣚~ †
Reaction score
180
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
Reaction score
109
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
Reaction score
509
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
Reaction score
509
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
Reaction score
1
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 Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top