//TESH.scrollpos=-1
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
//TESH.scrollpos=-1
//TESH.alwaysfold=0
// *************************************************************
// * TTBars -- Version 1.5.0
// * by Deaod
// *************************************************************
// *
// * CREDITS:
// * - Ammorth (found a bug)
// * - Anitarf (suggestions)
// * - Ddyq (helped testing)
// * - Vexorian (JassHelper, ARGB)
// * - PitzerMike (JassNewGenPack)
// * - Pipedream (Grimoire)
// *
// * - cohadar (used PUI for demonstration purposes)
// * - zwiebelchen (used a modified version of a script he wrote (CastingBar) for demonstration puposes)
// *
// * HOW TO USE:
// * * declare a variable of type TTBar or TTGradBar
// * - TTGradBar only has the additional feature of adding Gradients. TTBar and TTGradBar are identical in all other regards.
// *
// * * use [TTBar or TTGradBar].create(string char, integer numochars, real size, real x, real y, real z)
// * - char is the basic string the bar is made out of
// * - numochars is the number of chars this bar consits of
// * - size is the textsize of the bar
// * - x is the x-coord of the point where this bar is created
// * - y is the y-coord of the point where this bar is created
// * - z is the height offset above the ground
// *
// * * add a gradient by using YourBar.AddGradient(real threshold, ARGB color)
// * !! This is a feature of TTGradBar. Will not work with TTBar !!
// * - threshold is the value the bar must be equal to or lower than to apply the color specified in colorstring
// * - example input would be "ARGB.create(SOME_ALPHA, SOME_RED, SOME_GREEN, SOME_BLUE)" or "0xAARRGGBB"
// * Look at ARGB's manual for detailed reference
// * - there exists an alternative version named AddGradientString(real, threshold, string color),
// * where the color argument is formatted as follows: "|cAARRGGBB"
// *
// * * you can change the value of the bar at any time by using "set YourBar.Value=newval"
// * - value is a percentage
// * --> use 100 to fill it completely, use 0 to display an empty bar
// *
// * * you can lock this bar to a unit using YourBar.LockToUnit(unit u, real xOffset, real yOffset, real zOffset)
// * - u is the unit this bar is locked to
// * - xOffset is the offset in x from the position of the unit the bar is locked to
// * - yOffset is the offset in y from the position of the unit the bar is locked to
// * - zOffset is the height offset above ground level
// *
// * * of course you can also unlock the bar via YourBar.Unlock()
// *
// * * you can change the foreground color with YourBar.SetForeground(ARGB color)
// * !! Gradients are preferred over this !!
// * - example input would be "ARGB.create(SOME_ALPHA, SOME_RED, SOME_GREEN, SOME_BLUE)" or "0xAARRGGBB"
// * Look at ARGB's manual for detailed reference
// * - there exitsts an alternative version named SetForegroundString(string color),
// * which takes a string formatted as follows: "|cAARRGGBB"
// *
// * * you can change the background color with YouBar.SetBackground(ARGB color)
// * - example input would be "ARGB.create(SOME_ALPHA, SOME_RED, SOME_GREEN, SOME_BLUE)" or "0xAARRGGBB"
// * Look at ARGB's manual for detailed reference
// *
// * * want to show the bar to more players? Use YourBar.ChangeVisibility(force disp)
// * - disp should contain all players this bar should be displayed to; note that you have to destroy this parameter for yourself
// * inserting null will show the bar to all players
// *
// * * you can change the size of the bar any time by using "set YourBar.Size=newval"
// *
// * * you can read and write a bar's X, Y and Z coordinate by using the X, and X= operators (Y and Z respectively as well).
// * I added another method, YourBar.SetPosXY(real x, real y), which sets the bars X and Y coordinate, for speed reasons.
// *
// * * you have access to XOffset and YOffset members (both are of type real). They are only important when locking a bar to a unit.
// * You can probably guess by their names what i added them for.
// *
// * * you can read/change a bars primitive char by reading/changing the member Char
// *
// * * you can read/change a bars number of chars by reading/changing the member Width
// *
// * * you can fade out bars when destroying them using YourBar.FadeOut(real overTime, boolean followThrough, real xVel, real yVel)
// * - overTime is the time fading should take
// * - followThrough changes whether the TTBar instance should be destroyed on the spot
// * of if it should destroy it when the fading is finished
// * "true" destroys the TTBar instance when the fading is finished
// * "false" destroys the TTBar instance on the spot
// * - xVel and yVel can only be used if the Bar is not locked to a unit
// * and move the bar into x and y direction (respectively) by the amount specified
// *
// *************************************************************
library TTBARS uses ARGB, TimerUtils
globals
// TTBar
private constant integer DEFAULT_BACKGROUND = 0xFF000000 // 0xAARRGGBB // alpha channel is non-functional (blame blizzard for that)
private constant real TICK = 1./64 // in seconds // how often are bars moved to a units pos?
// TTBar and TTGradBar
private constant integer DEFAULT_FOREGROUND = 0xFFFFFFFF // 0xAARRGGBB
// TTGradBar
private constant integer MAX_GRADIENTS = 10 // Maximum number of gradients you can add
endglobals
// I dont recommend to change anything below this line
globals
private force tmp
private TTBar array Bars
private integer Count=0
private timer T=CreateTimer()
endglobals
struct TTBar
private texttag t
// background color
private ARGB bg_color
// foreground color
private string fg_color
// Position
private real x
private real y
private real z
// Text
private string txt
private real textsize
// locking to units
private integer lockindex
private boolean locked
private unit u
real XOffset
real YOffset
// misc
private force disp
private real Value2 // value
private integer NUM_CHARS // number of chars this bar uses
private string char // primitive char/string
private string ptext // primitive text without colors
private static method CopyForce takes nothing returns nothing
call ForceAddPlayer(tmp, GetEnumPlayer())
endmethod
private static method LockCallback takes nothing returns nothing
local integer i=Count-1
local TTBar s
loop
exitwhen i<0
set s=Bars[i]
set s.x=GetUnitX(s.u)
set s.y=GetUnitY(s.u)
call SetTextTagPos(s.t, s.x+s.XOffset, s.y+s.YOffset, s.z)
set i=i-1
endloop
endmethod
method operator Size takes nothing returns real
return .textsize/0.0023
endmethod
method operator Size= takes real size returns nothing
set .textsize=TextTagSize2Height(size)
endmethod
method operator Value takes nothing returns real
return .Value2*100.
endmethod
method operator Value= takes real newval returns nothing
local integer chars
local integer i=0
// keep newval inside possible boundaries
if newval>100. then
set newval=100.
elseif newval<0. then
set newval=0.
endif
set .Value2=newval/100. // set the new value
set .txt=.fg_color
set chars=(R2I((.Value2*.NUM_CHARS*StringLength(.char))+0.5)/StringLength(.char))*StringLength(.char) // calculate the number of chars needed to display the new value
set .txt=.txt+SubString(.ptext, 0, chars)
set .txt=.txt+"|r"
set .txt=.txt+SubString(.ptext, 0, StringLength(.ptext)-chars)
if .t!=null then
call SetTextTagText(.t, .txt, .textsize)
endif
endmethod
method operator X takes nothing returns real
return .x
endmethod
method operator X= takes real x returns nothing
set .x=x
if .t!=null and not .locked then
call SetTextTagPos(.t, .x, .y, .z)
endif
endmethod
method operator Y takes nothing returns real
return .y
endmethod
method operator Y= takes real y returns nothing
set .y=y
if .t!=null and not .locked then
call SetTextTagPos(.t, .x, .y, .z)
endif
endmethod
method operator Z takes nothing returns real
return .z
endmethod
method operator Z= takes real z returns nothing
set .z=z
if .t!=null then
call SetTextTagPos(.t, .x, .y, .z)
endif
endmethod
method operator Locked takes nothing returns boolean
return .locked
endmethod
private method RebuildText takes nothing returns nothing
local integer i=0
set .ptext=""
loop
exitwhen i>=.NUM_CHARS
set .ptext=.ptext+.char
set i=i+1
endloop
endmethod
method operator Char takes nothing returns string
return .char
endmethod
method operator Char= takes string new returns nothing
if new=="|" then
set new="||"
endif
set .char=new
call .RebuildText()
set .Value=.Value
endmethod
method operator Width takes nothing returns integer
return .NUM_CHARS
endmethod
method operator Width= takes integer new returns nothing
set .NUM_CHARS=new
call .RebuildText()
set .Value=.Value
endmethod
method SetPosXY takes real x, real y returns nothing // added for speed reasons
set .x=x
set .y=y
if .t!=null and not .locked then
call SetTextTagPos(.t, .x, .y, .z)
endif
endmethod
method SetBackground takes ARGB color returns nothing
set .bg_color=color
if .t!=null then
call SetTextTagColor(.t, .bg_color.red, .bg_color.green, .bg_color.blue, .bg_color.alpha)
endif
endmethod
method SetForeground takes ARGB color returns nothing
set .fg_color=SubString(color.str(""), 0, 10)
set .Value=.Value
endmethod
method SetForegroundString takes string color returns nothing
set .fg_color=color
set .Value=.Value
endmethod
method ChangeVisibility takes force disp returns nothing
if disp!=null then
if .disp==null then
set .disp=CreateForce()
else
call ForceClear(.disp)
endif
set tmp=.disp
call ForForce(disp, function TTBar.CopyForce)
if IsPlayerInForce(GetLocalPlayer(), .disp) and .t==null then
set .t=CreateTextTag()
if .t!=null then
call SetTextTagColor(.t, .bg_color.red, .bg_color.green, .bg_color.blue, .bg_color.alpha)
call SetTextTagText(.t, .txt, .textsize)
call SetTextTagPos(.t, .x, .y, .z)
debug else
debug call BJDebugMsg("TTBARS: TextTag limit reached!")
endif
elseif .t!=null and not IsPlayerInForce(GetLocalPlayer(), .disp) then
call DestroyTextTag(.t)
set .t=null
endif
else
if .t==null then
set .t=CreateTextTag()
if .t!=null then
call SetTextTagColor(.t, .bg_color.red, .bg_color.green, .bg_color.blue, .bg_color.alpha)
call SetTextTagText(.t, .txt, .textsize)
call SetTextTagPos(.t, .x, .y, .z)
debug else
debug call BJDebugMsg("TTBARS: TextTag limit reached!")
endif
endif
endif
endmethod
method LockToUnit takes unit u, real xOffset, real yOffset, real zOffset returns nothing
if not .locked then
set Bars[Count]=this
set .u=u
set .locked=true
set .lockindex=Count
set .XOffset=xOffset
set .YOffset=yOffset
set .Z=zOffset
if Count==0 then
call TimerStart(T, TICK, true, function thistype.LockCallback)
endif
set Count=Count+1
endif
endmethod
method Unlock takes nothing returns nothing
local integer i=0
if not .locked then
return
endif
set Count=Count-1
if Count==0 then
call PauseTimer(T)
endif
set Bars[.lockindex]=Bars[Count]
set Bars[Count].lockindex=.lockindex
set .locked=false
endmethod
static method create takes string char, integer numochars, real size, real x, real y, real z returns TTBar
local TTBar s=TTBar.allocate()
set s.t=CreateTextTag()
debug if s.t==null then
debug call BJDebugMsg("TTBARS: TextTag limit reached!")
debug endif
set s.bg_color=ARGB(DEFAULT_BACKGROUND)
set s.x=x
set s.y=y
set s.z=z
set s.textsize=TextTagSize2Height(size)
set s.fg_color=SubString(ARGB(DEFAULT_FOREGROUND).str(""), 0, 10)
set s.NUM_CHARS=numochars
if char=="|" then // ugly hack
set s.char="||"
else
set s.char=char
endif
set s.locked=false
set s.Value=0
if s.t!=null then
call SetTextTagPos(s.t, s.x, s.y, s.z)
call SetTextTagColor(s.t, s.bg_color.red, s.bg_color.green, s.bg_color.blue, s.bg_color.alpha)
call SetTextTagText(s.t, s.txt, s.textsize)
endif
call s.RebuildText()
return s
endmethod
method onDestroy takes nothing returns nothing
if .t!=null then
call DestroyTextTag(.t)
set .t=null
endif
if .locked then
call .Unlock()
set .u=null
endif
endmethod
private static method FadeOutCallback takes nothing returns nothing
local thistype s=thistype(GetTimerData(GetExpiredTimer()))
set s.t=null
call s.destroy()
call ReleaseTimer(GetExpiredTimer())
endmethod
method FadeOut takes real overTime, boolean followThrough, real xVel, real yVel returns nothing
local timer t
if .t!=null then
call SetTextTagLifespan(.t, overTime)
call SetTextTagAge(.t, 0)
call SetTextTagFadepoint(.t, 0)
call SetTextTagPermanent(.t, false)
if not .locked then
call SetTextTagVelocity(.t, TextTagSpeed2Velocity(xVel), TextTagSpeed2Velocity(yVel))
endif
endif
if followThrough then
set t=NewTimer()
call SetTimerData(t, this)
call TimerStart(t, overTime, false, function thistype.FadeOutCallback)
else
set .t=null
call .destroy()
endif
endmethod
endstruct
struct TTGradBar
private delegate TTBar Bar
private string fg_color
private string array GradientColor[MAX_GRADIENTS]
private real array GradientValue[MAX_GRADIENTS]
private integer GradCnt
static method create takes string char, integer numochars, real size, real x, real y, real z returns TTGradBar
local TTGradBar s=TTGradBar.allocate()
set s.Bar=TTBar.create(char, numochars, size, x, y, z)
set s.GradCnt=0
set s.fg_color=SubString(ARGB(DEFAULT_FOREGROUND).str(""), 0, 10)
return s
endmethod
method AddGradient takes real threshold, ARGB color returns nothing
if .GradCnt>=MAX_GRADIENTS then
debug call BJDebugMsg("TTGradBar: Cannot add any more Gradients to TTGradBar "+I2S(this)+"!")
return
endif
if threshold>100 then
set threshold=100
elseif threshold<0 then
set threshold=0
endif
set .GradientValue[.GradCnt]=threshold
set .GradientColor[.GradCnt]=SubString(color.str(""), 0, 10)
set .GradCnt=.GradCnt+1
endmethod
method AddGradientString takes real threshold, string color returns nothing
if .GradCnt>=MAX_GRADIENTS then
debug call BJDebugMsg("TTGradBar: Cannot add any more Gradients to TTGradBar "+I2S(this)+"!")
return
endif
if threshold>100 then
set threshold=100
elseif threshold<0 then
set threshold=0
endif
set .GradientValue[.GradCnt]=threshold
set .GradientColor[.GradCnt]=color
set .GradCnt=.GradCnt+1
endmethod
method operator Value= takes real newval returns nothing
local integer i=0
local real k
local integer j
local integer l=0
// keep newval inside possible boundaries
if newval>100 then
set newval=100
elseif newval<0 then
set newval=0
endif
set k=110 // some value above 100 will work just as well
// find appropriate gradient
loop
exitwhen i>=.GradCnt
if newval<=.GradientValue[i] and ((.GradientValue[i]-newval)<k) then
set k=.GradientValue[i]-newval
set j=i
set l=l+1 // count how many gradients have been considered for use
endif
set i=i+1
endloop
// colorize the bar
if l>0 then
call .Bar.SetForegroundString(.GradientColor[j])
else
call .Bar.SetForegroundString(.fg_color)
endif
set .Bar.Value=newval
endmethod
method SetForeground takes ARGB color returns nothing
set .fg_color=SubString(color.str(""), 0, 10)
set .Value=.Value
endmethod
method SetForegroundString takes string color returns nothing
set .fg_color=color
set .Value=.Value
endmethod
method onDestroy takes nothing returns nothing
call .Bar.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library ARGB initializer init
//******************************************************************************
//*
//* ARGB
//* ====
//* For your color needs.
//*
//* An ARGB object is a by-value struct, this means that assigning copies the
//* contents of the struct and that you don't have to use .destroy(), the
//* downside is that you cannot assign its members (can't do set c.r= 123 )
//*
//* This library should have plenty of uses, for example, if your spell involves
//* some unit recoloring you can allow users to input the color in the config
//* section as 0xAARRGGBB and you can then use this to decode that stuff.
//*
//* You can also easily merge two colors and make fading effects using ARGB.mix
//*
//* There's ARGB.fromPlayer which gets an ARGB object containing the player's
//* color. Then you can use the previous utilities on it.
//*
//* The .str() instance method can recolor a string, and the recolorUnit method
//* will apply the ARGB on a unit
//*
//* For other uses, you can use the .red, .green, .blue and .alpha members to get
//* an ARGB object's color value (from 0 to 255).
//*
//********************************************************************************
//=================================================================================
globals
private string array i2cc
endglobals
//this double naming stuff is beginning to make me insane, if only TriggerEvaluate() wasn't so slow...
struct ARGB extends array
static method create takes integer a, integer r, integer g, integer b returns ARGB
return ARGB(b + g*0x100 + r*0x10000 + a*0x1000000)
endmethod
static method fromPlayer takes player p returns ARGB
local playercolor pc=GetPlayerColor(p)
if(pc==PLAYER_COLOR_RED) then
return 0xFFFF0303
elseif(pc==PLAYER_COLOR_BLUE) then
return 0xFF0042FF
elseif(pc==PLAYER_COLOR_CYAN) then
return 0xFF1CB619
elseif(pc==PLAYER_COLOR_PURPLE) then
return 0xFF540081
elseif(pc==PLAYER_COLOR_YELLOW) then
return 0xFFFFFF01
elseif(pc==PLAYER_COLOR_ORANGE) then
return 0xFFFE8A0E
elseif(pc==PLAYER_COLOR_GREEN) then
return 0xFF20C000
elseif(pc==PLAYER_COLOR_PINK) then
return 0xFFE55BB0
elseif(pc==PLAYER_COLOR_LIGHT_GRAY) then
return 0xFF959697
elseif(pc==PLAYER_COLOR_LIGHT_BLUE) then
return 0xFF7EBFF1
elseif(pc==PLAYER_COLOR_AQUA) then
return 0xFF106246
elseif(pc==PLAYER_COLOR_BROWN) then
return 0xFF4E2A04
endif
return 0xFF111111
endmethod
method operator alpha takes nothing returns integer
if( integer(this) <0) then
return 0x80+(-(-integer(this)+0x80000000))/0x1000000
else
return (integer(this))/0x1000000
endif
endmethod
method operator red takes nothing returns integer
local integer c=integer(this)*0x100
if(c<0) then
return 0x80+(-(-c+0x80000000))/0x1000000
else
return c/0x1000000
endif
endmethod
method operator green takes nothing returns integer
local integer c=integer(this)*0x10000
if(c<0) then
return 0x80+(-(-c+0x80000000))/0x1000000
else
return c/0x1000000
endif
endmethod
method operator blue takes nothing returns integer
local integer c=integer(this)*0x1000000
if(c<0) then
return 0x80+(-(-c+0x80000000))/0x1000000
else
return c/0x1000000
endif
endmethod
//====================================================================
// Mixes two colors, s would be a number 0<=s<=1 that determines
// the weight given to color c2.
//
// mix(c1,c2,0) = c1
// mix(c1,c2,1) = c2
// mix(c1,c2,0.5) = Mixing the colors c1 and c2 in equal proportions.
//
static method mix takes ARGB c1, ARGB c2, real s returns ARGB
//widest function ever
return ARGB( R2I(c2.blue*s+c1.blue*(1-s)+0.5) + R2I(c2.green*s+c1.green*(1-s)+0.5)*0x100 + R2I(c2.red*s+c1.red*(1-s)+0.5)*0x10000 + R2I(c2.alpha*s+c1.alpha*(1-s)+0.5)*0x1000000)
endmethod
method str takes string s returns string
return "|c"+i2cc[.alpha]+i2cc[.red]+i2cc[.green]+i2cc[.blue]+s+"|r"
endmethod
method recolorUnit takes unit u returns nothing
local integer a
local integer r
local integer g
local integer b
local integer col=integer(this)
if (col<0) then
set col=-(-col+0x80000000)
set a=0x80+col/0x1000000
set col=col-(a-0x80)*0x1000000
else
set a=col/0x1000000
set col=col-a*0x1000000
endif
set r=col/0x10000
set col=col-r*0x10000
set g=col/0x100
set b=col-g*0x100
call SetUnitVertexColor(u,r,g,b,a)
endmethod
endstruct
private function init takes nothing returns nothing
local integer i=0
// Don't run textmacros you don't own!
//! textmacro ARGB_CHAR takes int, chr
set i=0
loop
exitwhen i==16
set i2cc[$int$*16+i]="$chr$"+i2cc[$int$*16+i]
set i2cc[i*16+$int$]=i2cc[i*16+$int$]+"$chr$"
set i=i+1
endloop
//! endtextmacro
//! runtextmacro ARGB_CHAR( "0","0")
//! runtextmacro ARGB_CHAR( "1","1")
//! runtextmacro ARGB_CHAR( "2","2")
//! runtextmacro ARGB_CHAR( "3","3")
//! runtextmacro ARGB_CHAR( "4","4")
//! runtextmacro ARGB_CHAR( "5","5")
//! runtextmacro ARGB_CHAR( "6","6")
//! runtextmacro ARGB_CHAR( "7","7")
//! runtextmacro ARGB_CHAR( "8","8")
//! runtextmacro ARGB_CHAR( "9","9")
//! runtextmacro ARGB_CHAR("10","A")
//! runtextmacro ARGB_CHAR("11","B")
//! runtextmacro ARGB_CHAR("12","C")
//! runtextmacro ARGB_CHAR("13","D")
//! runtextmacro ARGB_CHAR("14","E")
//! runtextmacro ARGB_CHAR("15","F")
endfunction
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library PUI initializer Init
//==============================================================================
globals
//-----------------------------------------------
private constant real INDEX_DECAY_TIME = 5. // seconds
//-----------------------------------------------
private constant real PERIOD = 0.03125 // 32 fps
//-----------------------------------------------
private constant integer DECAY_TICKS = R2I(INDEX_DECAY_TIME/PERIOD)
//-----------------------------------------------
private integer array Indexz
private unit array Unitz
private integer array Decayz
private integer array Tickz
private integer maxindex = 0
private integer topindex = 0
private integer decayindex = 0
private integer checker = 0
private integer decayer = 0
private integer tick = 0
endglobals
//==============================================================================
private function PeriodicRecycler takes nothing returns boolean
local integer temp
set tick = tick + 1
if topindex > decayindex then
set checker = checker + 1
if checker > topindex then
set checker = decayindex + 1
endif
if (GetUnitUserData(Unitz[checker])==0) then
set decayindex = decayindex + 1
set Unitz[checker] = Unitz[decayindex]
// swap(checker, decayindex)
set temp = Indexz[checker]
set Indexz[checker] = Indexz[decayindex]
set Indexz[decayindex] = temp
set Decayz[decayindex] = DECAY_TICKS
set Tickz[decayindex] = tick
endif
endif
if decayindex > 0 then
set decayer = decayer + 1
if decayer > decayindex then
set decayer = 1
endif
set Decayz[decayer] = Decayz[decayer] - (tick-Tickz[decayer])
if Decayz[decayer] > 0 then
set Tickz[decayer] = tick
else
// swap(decayer, decayindex)
set temp = Indexz[decayer]
set Indexz[decayer] = Indexz[decayindex]
set Indexz[decayindex] = temp
set Unitz[decayindex] = Unitz[topindex]
// swap(decayindex, topindex)
set temp = Indexz[decayindex]
set Indexz[decayindex] = Indexz[topindex]
set Indexz[topindex] = temp
set decayindex = decayindex - 1
set topindex = topindex - 1
endif
endif
return false
endfunction
//==============================================================================
// Main and only function exported by this library
//==============================================================================
function GetUnitIndex takes unit whichUnit returns integer
local integer index
debug if whichUnit == null then
debug call BJDebugMsg("|c00FF0000ERROR: PUI - Index requested for null unit")
debug return 0
debug endif
set index = GetUnitUserData(whichUnit)
if index == 0 then
set topindex = topindex + 1
if topindex > maxindex then
set maxindex = topindex
set Indexz[topindex] = topindex
endif
set index = Indexz[topindex]
set Unitz[topindex] = whichUnit
call SetUnitUserData(whichUnit, index)
set index = GetUnitUserData(whichUnit)
// this happens when requesting unit index for removed unit
debug if index == 0 then
debug call BJDebugMsg("|c00FFCC00WARNING: PUI - Bad unit handle")
debug endif
//debug call BJDebugMsg("|c00FFCC00PUI: Index assigned #" + I2S(index))
endif
return index
endfunction
//==============================================================================
private function DisplayStats takes nothing returns nothing
call BJDebugMsg("=============================================")
call BJDebugMsg("Biggest index ever = " + I2S(maxindex))
call BJDebugMsg("Indexes in use = " + I2S(topindex-decayindex))
call BJDebugMsg("Decaying indexes = " + I2S(decayindex))
call BJDebugMsg("Released indexes = " + I2S(maxindex-topindex))
call BJDebugMsg("=============================================")
endfunction
//===========================================================================
private function DisplaySelectedEnum takes nothing returns nothing
call BJDebugMsg( "PUI(" + ( GetUnitName(GetEnumUnit()) + ( ") = " + I2S(GetUnitUserData(GetEnumUnit())) ) ) )
endfunction
//===========================================================================
private function DisplaySelected takes nothing returns nothing
local group g = CreateGroup()
call SyncSelections()
call GroupEnumUnitsSelected(g, Player(0), null)
call ForGroup(g, function DisplaySelectedEnum)
call DestroyGroup(g)
set g = null
endfunction
//==============================================================================
private function Init takes nothing returns nothing
local trigger trig
set trig = CreateTrigger()
call TriggerRegisterTimerEvent( trig, PERIOD, true )
call TriggerAddCondition( trig, Condition(function PeriodicRecycler) )
debug set trig = CreateTrigger()
debug call TriggerRegisterPlayerChatEvent( trig, Player(0), "-pui", true )
debug call TriggerAddAction( trig, function DisplaySelected )
debug set trig = CreateTrigger()
debug call TriggerRegisterPlayerChatEvent( trig, Player(0), "-puistats", true )
debug call TriggerAddAction( trig, function DisplayStats )
endfunction
endlibrary
//===========================================================================
// Allowed PUI_PROPERTY TYPES are: unit, integer, real, boolean, string
// Do NOT put handles that need to be destroyed here (timer, trigger, ...)
// Instead put them in a struct and use PUI textmacro
//===========================================================================
//! textmacro PUI_PROPERTY takes VISIBILITY, TYPE, NAME, DEFAULT
$VISIBILITY$ struct $NAME$
private static unit array pui_unit
private static $TYPE$ array pui_data
//-----------------------------------------------------------------------
// Returns default value when first time used
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns $TYPE$
local integer pui = GetUnitIndex(whichUnit)
if .pui_unit[pui] != whichUnit then
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = $DEFAULT$
endif
return .pui_data[pui]
endmethod
//-----------------------------------------------------------------------
static method operator[]= takes unit whichUnit, $TYPE$ whichData returns nothing
local integer pui = GetUnitIndex(whichUnit)
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = whichData
endmethod
endstruct
//! endtextmacro
//===========================================================================
// Never destroy PUI structs directly.
// Use .release() instead, will call .destroy()
//===========================================================================
//! textmacro PUI
private static unit array pui_unit
private static integer array pui_data
private static integer array pui_id
//-----------------------------------------------------------------------
// Returns zero if no struct is attached to unit
//-----------------------------------------------------------------------
static method operator[] takes unit whichUnit returns integer
local integer pui = GetUnitIndex(whichUnit)
if .pui_data[pui] != 0 then
if .pui_unit[pui] != whichUnit then
// recycled handle detected
call .destroy(.pui_data[pui])
set .pui_unit[pui] = null
set .pui_data[pui] = 0
endif
endif
return .pui_data[pui]
endmethod
//-----------------------------------------------------------------------
// This will overwrite already attached struct if any
//-----------------------------------------------------------------------
static method operator[]= takes unit whichUnit, integer whichData returns nothing
local integer pui = GetUnitIndex(whichUnit)
if .pui_data[pui] != 0 then
call .destroy(.pui_data[pui])
endif
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = whichData
set .pui_id[whichData] = pui
endmethod
//-----------------------------------------------------------------------
// If you do not call release struct will be destroyed when unit handle gets recycled
//-----------------------------------------------------------------------
method release takes nothing returns nothing
local integer pui= .pui_id[integer(this)]
call .destroy()
set .pui_unit[pui] = null
set .pui_data[pui] = 0
endmethod
//! endtextmacro
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library_once TimerUtils initializer init
//*********************************************************************
//* TimerUtils (Blue flavor for 1.23b or later)
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//* limit, which means that if more than 408000 handle ids
//* are used in your map, TimerUtils might fail, this
//* value is quite big and it is much bigger than the
//* timer limit in Red flavor.
//*
//********************************************************************
//==================================================================================================
globals
private hashtable hasht //I <3 blizz
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
call SaveInteger(hasht,0, GetHandleId(t), value)
endfunction
function GetTimerData takes timer t returns integer
return LoadInteger(hasht, 0, GetHandleId(t))
endfunction
//==========================================================================================
globals
private timer array tT
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
set tT[0]=CreateTimer()
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
set hasht = InitHashtable()
endfunction
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library CastingBar uses TTBARS, ARGB
// Zwiebelchen's Casting Bar System
// redone.
// Requires NewGen, such as Warcraft III Patch 1.24b
globals
private constant integer NUMBER_OF_BAR_BITS = 40 // The number of the commas/apostrophes/whatever you use to fill an entire bar
// It's not recommended to set this higher than 100, since it will cause lag due to the bad string handling of Warcraft III
// Use a bigger Size instead.
// Never set this to 0, since it will create a divide by 0 error.
private constant string BAR_BIT = "'" // The letter used for the Bar
private constant integer COLOR = 0xFF33CCFF // The hex color code for the bar - Leave out the "|r" at the end!
private constant integer COLOR_CHANNEL = 0xFF00FF00 // The hex color code for the Channeling bar - Leave out the "|r" at the end!
private constant integer BACKGROUND_COLOR = 0xFF000033 // The hex color codes for the Background of the Bar
private constant integer BACKGROUND_COLOR_CHANNEL = 0xFF003300 // The hex color codes for the Background of the Channeling Bar
private constant real CASTING_BAR_X_OFFSET = 0 // The X Offset of the bar position to the unit. + being east
private constant real CASTING_BAR_Y_OFFSET = 0 // The Y Offset of the bar position to the unit. + being north
// Set these values to 0 if you want to use a third person camera or do the math
// and get an equation depending on the camera angle if you want to use a 3D camera.
// It may need a little bit of trying to find good values for these
private constant real CASTING_BAR_Z_OFFSET = 0 // The Z Offset of the bar position to the unit.
private constant real CASTING_BAR_SIZE = 8 // The size of the bar font
private constant real CASTING_BAR_FADE_OUT = 0.5
private constant real TICK = 0.02 // The frequency the bars get updated - recommended value: 0.02
endglobals
//----------------------------------------------------------------------------------------
//Use call Castingbar(Castingtime, Orderstring, Casterunit, VisiblyModifier, ChannelingBool) to attach a casting bar to a unit.
// variables: real Castingtime --> Only use casting times above 0.3 seconds, otherwise it will look strange
// string Orderstring --> The Orderstring of the ability. Used to determine wether the unit moves
// during the casting. Set this to "_" to disable the orderstring check.
// unit Casterunit --> Obviously the caster
// integer Visibly Modifier --> Changes Visibility of the Casting bar
// 0: Only the owner of the casting unit sees the bar
// 1: All Allies of the Player can see the bar
// 2: All Players can see the bar
// boolean Channeled --> false: ordinary cast; true: channeled cast
private struct Data
TTBar bar
unit c
real t
real tt
string order
private integer i
private static thistype array Structs
private static timer T=CreateTimer()
private static integer Count=0
method onDestroy takes nothing returns nothing
call .bar.FadeOut(CASTING_BAR_FADE_OUT, true, 0,0)
// clean your struct here
set .Count=.Count-1
set .Structs[.i]=.Structs[.Count]
set .Structs[.i].i=.i
if .Count==0 then
call PauseTimer(.T)
endif
endmethod
private static method Callback takes nothing returns nothing
local integer i=.Count-1
local thistype s
loop
exitwhen i<0
set s=.Structs[i]
//
if GetUnitCurrentOrder(s.c)==OrderId(s.order) or s.order=="_" then
set s.t=s.t+TICK
set s.bar.Value=100*s.t/s.tt
if s.t>=s.tt then
call s.destroy()
endif
else
call s.destroy()
endif
// do your things here, dont forget to call s.destroy() somewhen
//
set i=i-1
endloop
endmethod
static method create takes unit caster, real time, string order, force disp, boolean channel returns thistype
local thistype s=.allocate()
set s.bar=TTBar.create(BAR_BIT, NUMBER_OF_BAR_BITS, CASTING_BAR_SIZE, GetUnitX(caster)+CASTING_BAR_X_OFFSET,GetUnitY(caster)+CASTING_BAR_Y_OFFSET,CASTING_BAR_Z_OFFSET)
call s.bar.ChangeVisibility(disp)
call s.bar.LockToUnit(caster, CASTING_BAR_X_OFFSET, CASTING_BAR_Y_OFFSET, CASTING_BAR_Z_OFFSET)
if channel then
call s.bar.SetBackground(ARGB(BACKGROUND_COLOR_CHANNEL))
call s.bar.SetForeground(ARGB(COLOR_CHANNEL))
else
call s.bar.SetBackground(ARGB(BACKGROUND_COLOR))
call s.bar.SetForeground(ARGB(COLOR))
endif
set s.c=caster
set s.t=0
set s.tt=time
set s.order=order
// initialize the struct here
set .Structs[.Count]=s
set s.i=.Count
if .Count==0 then
call TimerStart(.T, TICK, true, function thistype.Callback)
endif
set .Count=.Count+1
return s
endmethod
endstruct
function Castingbar takes real Casttime, string Order, unit Caster, integer ShowCastingBar, boolean Channeled returns nothing
local force TextTagForce=null
local player LocalPlayer = GetOwningPlayer(Caster)
if ShowCastingBar == 0 then
set TextTagForce = CreateForce()
call ForceAddPlayer(TextTagForce, LocalPlayer)
elseif ShowCastingBar == 1 then
set TextTagForce = CreateForce()
call ForceEnumAllies(TextTagForce, LocalPlayer, null)
endif
call Data.create(Caster, Casttime, Order, TextTagForce, Channeled)
if TextTagForce!=null then
call DestroyForce(TextTagForce)
set TextTagForce = null
endif
endfunction
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library RAGE initializer Init uses PUI, TTBARS, ARGB
globals
private constant integer BAR_BG_RED = 0x40 // Background Red of the bar
private constant integer BAR_BG_GREEN = 0x40 // Background Green of the bar
private constant integer BAR_BG_BLUE = 0x40 // Background Blue of the bar
private constant integer BAR_ALPHA = 0xFF // Alpha of the bar
private constant string BAR_BASE_STRING = "|" //
private ARGB BAR_DEF_GRADIENT = 0xff00ff00
private constant integer BAR_WIDTH = 200 // Width in chars
private constant real BAR_SIZE = 5. // size of each char.
private constant real BAR_XOFFSET = -100. // x offset of the bar from the units position
private constant real BAR_YOFFSET = 0. // y offset
private constant real BAR_ZOFFSET = 128. // this is the height this bar is floating at
private constant real BAR_RECOVER = 0.5 // this is used when a Bar was decaying and its Amount was increased before it finished decaying
private constant real BAR_STAY = 5. // after Rage.Amount becomes 0, wait this many seconds before destroying it.
private constant real BAR_FADE_OUT_TIME = 5.
constant real MAX_RAGE = 50. // maximum amount of rage
constant real DECAY_TICK = 0.03125 // Rage decays every this many seconds
endglobals
// Dont change the following line
//! textmacro SetUpGradients
// dont change anything before the first parenthesis
call s.Bar.AddGradient(100, 0xffcc0000) // i recommend keeping at least this one; you can still change its color
call s.Bar.AddGradient( 90, 0xffb51600)
call s.Bar.AddGradient( 80, 0xff9e2d00)
call s.Bar.AddGradient( 70, 0xff884400)
call s.Bar.AddGradient( 60, 0xff715a00)
call s.Bar.AddGradient( 50, 0xff5a7100)
call s.Bar.AddGradient( 40, 0xff448800)
call s.Bar.AddGradient( 30, 0xff2d9e00)
call s.Bar.AddGradient( 20, 0xff16b500)
call s.Bar.AddGradient( 10, 0xff00cc00)
// ignore the following line
//! endtextmacro
//
globals
private force tmpf
private unit array Units
private integer Count=0
private timer T
endglobals
private struct Rage_base
private TTGradBar Bar
private unit u
private real value
private real derage
private boolean UseDecay
private boolean bardecay
private real stay
static method create takes unit u returns Rage_base
local Rage_base s=Rage_base.allocate()
call ForceAddPlayer(tmpf, GetOwningPlayer(u))
set s.u=u
// Create the bar
set s.Bar=TTGradBar.create(BAR_BASE_STRING, BAR_WIDTH, BAR_SIZE, 0, 0, BAR_ZOFFSET)
call s.Bar.ChangeVisibility(tmpf)
call s.Bar.SetBackground(ARGB.create(BAR_ALPHA, BAR_BG_RED, BAR_BG_GREEN, BAR_BG_BLUE))
call s.Bar.SetForeground(BAR_DEF_GRADIENT)
call ForceClear(tmpf)
//! runtextmacro SetUpGradients()
call s.Bar.LockToUnit(u, BAR_XOFFSET, BAR_YOFFSET, BAR_ZOFFSET)
return s
endmethod
static method DecayCallback takes nothing returns nothing
local integer i=0
local Rage_base s
loop
exitwhen i>=Count
set s=Rage[Units[i]]
if s.UseDecay then
set s.Amount=s.Amount-(s.Decay*DECAY_TICK)
elseif s.bardecay then
set s.stay=s.stay+DECAY_TICK
if s.bardecay and s.stay>=BAR_STAY then
call s.destroy()
endif
endif
set i=i+1
endloop
endmethod
method operator Amount takes nothing returns real
return .value
endmethod
method operator Amount= takes real r returns nothing
if r>MAX_RAGE then
set r=MAX_RAGE
set .bardecay=false
elseif r<=0 then
set r=0
set .UseDecay=false
set .bardecay=true
else
set .bardecay=false
endif
set .value=r
set .Bar.Value=100*(.value/MAX_RAGE)
endmethod
method operator Decay takes nothing returns real
return .derage
endmethod
method operator Decay= takes real r returns nothing
if r<=0 then
set .UseDecay=false
set r=0
else
set .UseDecay=true
endif
set .derage=r
endmethod
method onDestroy takes nothing returns nothing
call .Bar.FadeOut(BAR_FADE_OUT_TIME, true, 0,0)
set .value=0
set .derage=0
set .UseDecay=false
set .bardecay=false
set .stay=0
call Rage.release(.u)
endmethod
endstruct
struct Rage // based off of PUI_PROPERTY struct; credits to cohadar
private static unit array pui_unit
private static Rage_base array pui_data
//-----------------------------------------------------------------------
// Returns default value when first time used
//-----------------------------------------------------------------------
static method operator [] takes unit whichUnit returns Rage_base
local integer pui = GetUnitIndex(whichUnit)
if .pui_unit[pui] != whichUnit then
set .pui_unit[pui] = whichUnit
set .pui_data[pui] = Rage_base.create(whichUnit)
set Units[Count]=whichUnit
if Count==0 then
call TimerStart(T, DECAY_TICK, true, function Rage_base.DecayCallback)
endif
set Count=Count+1
endif
return .pui_data[pui]
endmethod
static method OnDeathActions takes nothing returns nothing
local integer pui=GetUnitIndex(GetTriggerUnit())
if .pui_data[pui]!=0 then
call .pui_data[pui].destroy()
endif
endmethod
static method release takes unit u returns nothing
local integer pui=GetUnitIndex(u)
local integer i=0
loop
exitwhen i>=Count
if Units[i]==u and .pui_data[pui]!=0 then
set Count=Count-1
set Units[i]=Units[Count]
set Units[Count]=null
if Count>=0 then
call PauseTimer(T)
endif
endif
set i=i+1
endloop
set .pui_data[pui]=0
set .pui_unit[pui]=null
endmethod
endstruct
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerAddAction(t, function Rage.OnDeathActions)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
set tmpf=CreateForce()
set T=CreateTimer()
endfunction
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library Testsingle initializer Init uses TTBARS, RAGE // meh, not really a beauty.
globals
private trigger Trig
private timer tim
private group tmp
private TTGradBar s
private unit H = null
endglobals
private function ReduceVal takes nothing returns nothing
set s.Value=s.Value-5
if s.Value<=0 then
call s.destroy()
set H=null
call PauseTimer(tim)
endif
endfunction
private function DamagedActions takes nothing returns nothing
local unit t=GetTriggerUnit()
local unit u=GetEventDamageSource()
local real d=GetEventDamage()
if GetUnitAbilityLevel(t, 'Bssd')>0 then // 'Bssd' is slow posion buff applied
call UnitRemoveAbility(t, 'Bssd')
set Rage[u].Amount=Rage[u].Amount+3
set Rage[u].Decay=1
else
set Rage[t].Amount=Rage[t].Amount+(0.02*d)
endif
endfunction
private function DispCredits takes nothing returns nothing
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, "Credits:")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - Ammorth (found a bug)")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - Anitarf (suggestions)")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - Ddyq (helped testing)")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - Dynasti (motivated me)")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - Vexorian (created JassHelper, TimerUtils and ARGB)")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - PitzerMike (publishes JassNewGenPack)")
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0,0,10, " - Pipedream (created Grimoire)")
endfunction
private function Actions takes nothing returns nothing
local real d
local real a
local unit u
if H==null then
// Create the Bar: Base Char|Number or Chars|Size| X| Y| Z |
set s=TTGradBar.create("||", 140, 5, 0, 0, 60) // 5 seems to be a good size
call s.SetBackground(0xFF808080)
call s.SetForeground(0xFF00FF00)
// value color
call s.AddGradient(50, 0xffffff00)
call s.AddGradient(25, 0xffff0000) // Order doesnt matter
// call s.SetForeground(0xFF00FF00) achieves the same result as the line below.
//call s.AddGradient(100, 0xff00ff00) // [I recommend always adding a gradient with value 100.] -- Not anymore, doesnt matter
set s.Value=100 // this uses percentages. So dont use values above 100 or below zero
call TimerStart(tim, 1., true, function ReduceVal)
set H=CreateUnit(Player(0), 'h000', 0,0,0)
call UnitApplyTimedLife(H, 'BTLF', 20)
call s.LockToUnit(H, -76, 0, 98)
call TriggerRegisterUnitEvent(Trig, H, EVENT_UNIT_DAMAGED)
set d=bj_PI/10
set a = d
loop
exitwhen a>2*bj_PI
set u=CreateUnit(Player(1), 'hfoo', Cos(a)*512, Sin(a)*512, 0)
call PauseUnit(u, true)
call TriggerRegisterUnitEvent(Trig, u, EVENT_UNIT_DAMAGED)
call UnitApplyTimedLife(u, 'BTLF', 20)
set a=a+d
endloop
set u=null
call DispCredits()
endif
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerAddAction(t, function Actions)
call TriggerRegisterPlayerChatEvent(t, Player(0), "-test", true)
set t=CreateTrigger()
call TriggerAddAction(t, function DispCredits)
call TriggerRegisterTimerEvent(t, 60, true)
set Trig=CreateTrigger()
call TriggerAddAction(Trig, function DamagedActions)
set tim=CreateTimer()
endfunction
endlibrary