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: 700
Ehh not too usefull, but cool :)
could you make a version thake floats below there feet?

and looks like its vjass is it?
 
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
 
Post the code of FloatingGlobals too?
 
>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
 
> It wont go into the map.
Requires NewGen editor. I think he didn't note that in the first post...
 
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.
 
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).
 
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?
 
They want perfection.

And very nice, if only I didn't use so many units at the same time I could use :(
 
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)
 
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.
 
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.
 
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...
 
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:
    alternatively if you not making at least 23 an hour you could work in an Aldi warehouse
  • Varine Varine:
    Yeah I've been thinking about using AI for shit. I'm on vacation next week so I'm going to spend some time reorganizing everything and getting all my shit back in order
  • Varine Varine:
    lol I technically make less than 23 right now because I'm on salary and am there all the time, but it's a lot more than a normal wage still. I also have a meeting soon to renegotiate my pay because I want about a 25% increase to account for what I'm actually doing or a re-evaluation of our duties so that that my responsibilities are more in line with my pay. Depending on how that goes I'm prepared to give notice and move on, I don't mind taking less money so I'd have time for the rest of my life, but I'd rather they just fucking pay me enough to justify the commitment on my end. Plus right now I hold pretty much all the cards since I'm the only one actually qualified for my position.
    +1
  • Varine Varine:
    The other chef was there before me and got his position by virtue of being the only adult when the old general manager got married and didn't want to deal with the kitchen all the time, and happened to be in the position when the GM quit. New GM is fine with front of house but doesn't know enough about the kitchen side to really do anything or notice that I'm the one primarily maintaining it. Last time I left they hired like 3 people to replace me and there was still a noticeable drop in quality, so I got offered like 6 dollars an hour more and a pretty significant summer bonus to come back
  • Varine Varine:
    So honestly even if I leave I think it would last a couple of months until it's obvious that I am not exactly replaceable and then I would be in an even better position.
  • Varine Varine:
    But as of right now I have two other job offers that are reasonably close to what my hourly equivalency would be, and I would probably have more time for my other projects. The gap would be pretty easy to fill up if I had time to do my side jobs. I use to do some catering and private events, personal lessons, consultations, ect, and I charge like 120 an hour for those. But they aren't consistent enough for a full time job, too small of a town. And I'm not allowed to move for another year until my probation is over
  • Varine Varine:
    I guess I could get it transferred, but that seems like a hassle.
  • Varine Varine:
    Plus I have a storage room full of broken consoles I need to fix. I need to build a little reflow oven so I can manufacture some mod chips still, but it'll get there.
    +1
  • Varine Varine:
    I would like to get out of cooking in general at some point in the next ten years, but for the time being I can make decent money and pump that into savings. I've been taking some engineering classes online, but those aren't exactly career oriented at the moment, but I think getting into electronic or computer engineering of some sort would be ideal. I'm just going to keep taking some classes here and there until there's one that I am really into.
    +2
  • The Helper The Helper:
    There is money in fixing and reselling consoles. Problem is people know that so they are doing it
  • The Helper The Helper:
    If you can find a source of broken consoles though you can make money fixing them - sometimes some big money
  • Varine Varine:
    I was buying them on Ebay, but it's pretty competitive, so more recently I've just been telling the thrift stores to call me and I will come take all their electronics they can't sell. I've volunteered there before and people use them like a dump sometimes, and so they just have a massive amount of broken shit they throw away
  • Varine Varine:
    The local GoodWill was pretty into it, surprisingly the animal shelter store was not. The lady I talked to there seemed to think I was trying to steal stuff or something, she wasn't very nice about it. Like I'm just trying to stop you having to throw a bunch of electronics away, if you can sell it great. I'd probably pay you for the broken shit too if you wanted
  • Varine Varine:
    Then I make posts on Facebook yard sale pages sometimes saying I want your old electronics, but Facebook being Facebook people on there are also wary about why I want it, then want a bunch of money like it's going to be very worth it
  • Varine Varine:
    Sooner than later I'm going to get my archives business going a little more. I need some office space that is kind of hard to get at the moment, but without it, I have to be like "Yeah so go ahead and just leave your family heirlooms and hundred year old photographs here at my shitty apartment and give me a thousand dollars, and next month I'll give you a thumb drive. I promise I'll take care of them!"
    +1
  • Varine Varine:
    I can do some things with them at their home, but when people have thousands of slides and very delicate newspaper clippings and things, not really practical. I
  • Varine Varine:
    I would be there for days, even with my camera set up slides can take a long time, and if they want perfect captures I really need to use my scanners that are professionally made for that. My camera rig works well for what it is, but for enlargements and things it's not as good.
  • Varine Varine:
    I've only had a couple clients with that so far, though. I don't have a website or anything yet though.
  • Varine Varine:
    Console repair can be worthwhile, but it's also not a thing I can do at scale in my house. I just don't have room for the equipment. I need an office that I can segregate out for archival and then electronic restoration.
  • Varine Varine:
    But in order for that to be real, I need more time, and for more time I need to work less, and to work less I need a different job, and for a different job I need more money to fall back on so that I can make enough to just pay like, rent and utilities and use my savings to find these projects
    +1
  • Varine Varine:
    Another couple years. I just need to take it slow and it'll get there.
  • jonas jonas:
    any chance to get that stolen money back?
  • jonas jonas:
    Maybe you can do console repair just as a side thing, especially if there's so much competition business might be slow. Or do you need a lot of special equipment for that?
  • jonas jonas:
    I recently bought a used sauna and the preowner told me some component is broken, I took a look and it was just a burnt fuse, really cheap to fix. I was real proud of my self since I usually have two left hands for this kinda stuff :p
  • tom_mai78101 tom_mai78101:
    I am still playing Shapez 2. What an awful thing to happen, Varine, and hopefully everything has been sorted out soon. Always use multi-factor authentication whenever you have the opportunity to do so.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top