//TESH.scrollpos=-1
//TESH.alwaysfold=0
//
Name | Type | is_array | initial_value |
//TESH.scrollpos=-1
//TESH.alwaysfold=0
// extends imagebars to support gradients for compatibility to TTBARS
// you can add Gradients using the following method:
// method addGradient takes real threshold, ARGB color returns nothing
//
// keep in mind that threshold now is a value from 0 to 1
// if you additionally want to fade this bar, import ImageFadeBars and use imagefadebar instead of imagegradbar
library ImageGradBars requires ImageBars, ARGB
globals
private constant integer DEFAULT_FOREGROUND_COLOR = 0xFF002040
private constant integer MAX_GRADIENTS = 10 // Maximum number of gradients you can add
endglobals
struct imagegradbar
private delegate imagebar IB
private ARGB FGColor
private ARGB array GradientColor[MAX_GRADIENTS]
private real array GradientValue[MAX_GRADIENTS]
private integer GradCnt
static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
local thistype s=.allocate()
set s.IB=imagebar.create(bgimage, fgimage, sizex, sizey, x, y, z)
set s.GradCnt=0
set s.FGColor=ARGB(DEFAULT_FOREGROUND_COLOR)
return s
endmethod
method addGradient takes real threshold, ARGB color returns nothing
if .GradCnt>=MAX_GRADIENTS then
debug call BJDebugMsg("ImageGradBar: Cannot add any more gradients to imagegradbar "+I2S(this)+"!")
return
endif
if threshold>1. then
set threshold=1.
elseif threshold<0. then
set threshold=0.
endif
set .GradientValue[.GradCnt]=threshold
set .GradientColor[.GradCnt]=color
set .GradCnt=.GradCnt+1
endmethod
method operator percentFill= 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>1. then
set newval=1.
elseif newval<0. then
set newval=0.
endif
set k=2 // some value above 1 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 .IB.setForegroundColor(.GradientColor[j])
else
call .IB.setForegroundColor(.FGColor)
endif
set .IB.percentFill=newval
endmethod
method setForegroundColor takes ARGB color returns nothing
set .FGColor=color
set .percentFill=.percentFill
endmethod
method setForegroundAlpha takes integer new returns nothing
local ARGB c=.IB.getForegroundColor()
set c.alpha=new
call .IB.setForegroundColor(c)
endmethod
method onDestroy takes nothing returns nothing
call .IB.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
// Basically extends imagegradbars and adds the following methods:
// method fade takes integer fromalpha, integer toalpha, real overtime, boolean destroy returns nothing
// method fadeOut takes real time returns nothing
//
// fadeOut destroys the instance automatically, fade only does if destroy equals true
// Note that for the best results your alpha channels should be synced.
library_once ImageFadeBars requires ImageBars, ImageGradBars
globals
private constant real TICK = 1./32
endglobals
struct imagefadebar
private delegate imagegradbar IB
private integer target
private real current
private real delta
private boolean dodestroy
private boolean fading
private integer i
private static thistype array Structs
private static integer Count=0
private static timer T=CreateTimer()
private static method KeepInBounds takes integer value, integer lowerbound, integer upperbound returns integer
if value>upperbound then
set value=upperbound
elseif value<lowerbound then
set value=lowerbound
endif
return value
endmethod
private method onDestroy takes nothing returns nothing
call IB.destroy()
if .fading then
set .Count=.Count-1
set .Structs[.i]=.Structs[.Count]
set .Structs[.i].i=.i
if .Count==0 then
call PauseTimer(.T)
endif
endif
endmethod
private static method Callback takes nothing returns nothing
local thistype s
local integer i=.Count-1
local ARGB c
loop
exitwhen i<0
set s=.Structs[i]
set s.current=s.current+s.delta
// change the alpha of all channels of the bar to fromalpha
// background first
set c=s.IB.getBackgroundColor()
set c.alpha=R2I(s.current+.5)
call s.IB.setBackgroundColor(c)
// then mask
set c=s.IB.getMaskColor()
set c.alpha=R2I(s.current+.5)
call s.IB.setMaskColor(c)
// then foreground
call s.IB.setForegroundAlpha(R2I(s.current+.5))
if (s.delta>=0 and s.current>=s.target) or (s.delta<0 and s.current<=s.target) then
set s.fading=false
// remove the instance from the list of actively fading instances
set .Count=.Count-1
set .Structs[s.i]=.Structs[.Count]
set .Structs[s.i].i=s.i
if .Count==0 then
call PauseTimer(.T)
endif
// do the users last wish for this instance
if s.dodestroy then
call s.destroy()
endif
endif
set i=i-1
endloop
endmethod
static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
local thistype s=.allocate()
set s.IB=imagegradbar.create(bgimage, fgimage, sizex, sizey, x, y, z)
return s
endmethod
method fade takes integer fromalpha, integer toalpha, real overtime, boolean destroy returns nothing
local ARGB c
if overtime<=0 then
call .destroy()
endif
set .current=.KeepInBounds(fromalpha, 0x00, 0xFF)
set .target=.KeepInBounds(toalpha, 0x00, 0xFF)
set .delta=(.target-.current)*TICK/overtime
set .dodestroy=destroy
// change the alpha of all channels of the bar to fromalpha
// background first
set c=.IB.getBackgroundColor()
set c.alpha=fromalpha
call .IB.setBackgroundColor(c)
// then mask
set c=.IB.getMaskColor()
set c.alpha=fromalpha
call .IB.setMaskColor(c)
// then foreground
call .IB.setForegroundAlpha(R2I(.current+.5))
// make sure we dont add it twice to the list of fading bars
if not .fading then
set .Structs[.Count]=this
set .i=.Count
if .Count==0 then
call TimerStart(.T, TICK, true, function thistype.Callback)
endif
set .Count=.Count+1
set .fading=true
endif
endmethod
method fadeOut takes real time returns nothing
call .fade(0xFF, 0x00, time, true)
endmethod
method setBackgroundColor takes ARGB color returns nothing
if not .fading then
call .IB.setBackgroundColor(color)
endif
endmethod
method setMaskColor takes ARGB color returns nothing
if not .fading then
call .IB.setMaskColor(color)
endif
endmethod
method setForegroundColor takes ARGB color returns nothing
if not .fading then
call .IB.setForegroundColor(color)
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
// Basically extends imagebars and adds the following methods:
// method fade takes integer fromalpha, integer toalpha, real overtime, boolean destroy returns nothing
// method fadeOut takes real time returns nothing
//
// fadeOut destroys the instance automatically, fade only does if destroy equals true
// Note that for the best results your alpha channels should be synced.
library_once ImageFadeBars requires ImageBars
globals
private constant real TICK = 1./32
endglobals
struct imagefadebar
private delegate imagebar IB
private integer target
private real current
private real delta
private boolean dodestroy
private boolean fading
private integer i
private static thistype array Structs
private static integer Count=0
private static timer T=CreateTimer()
private static method KeepInBounds takes integer value, integer lowerbound, integer upperbound returns integer
if value>upperbound then
set value=upperbound
elseif value<lowerbound then
set value=lowerbound
endif
return value
endmethod
private method onDestroy takes nothing returns nothing
call IB.destroy()
if .fading then
set .Count=.Count-1
set .Structs[.i]=.Structs[.Count]
set .Structs[.i].i=.i
if .Count==0 then
call PauseTimer(.T)
endif
endif
endmethod
private static method Callback takes nothing returns nothing
local thistype s
local integer i=.Count-1
local ARGB c
loop
exitwhen i<0
set s=.Structs[i]
set s.current=s.current+s.delta
// change the alpha of all channels of the bar to fromalpha
// background first
set c=s.IB.getBackgroundColor()
set c.alpha=R2I(s.current+.5)
call s.IB.setBackgroundColor(c)
// then mask
set c=s.IB.getMaskColor()
set c.alpha=R2I(s.current+.5)
call s.IB.setMaskColor(c)
// then foreground
set c=s.IB.getForegroundColor()
set c.alpha=R2I(s.current+.5)
call s.IB.setForegroundColor(c)
if s.current>=s.target then
set s.fading=false
// remove the instance from the list of actively fading instances
set .Count=.Count-1
set .Structs[s.i]=.Structs[.Count]
set .Structs[s.i].i=s.i
if .Count==0 then
call PauseTimer(.T)
endif
// do the users last wish for this instance
if s.dodestroy then
call s.destroy()
endif
endif
set i=i-1
endloop
endmethod
static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
local thistype s=.allocate()
set s.IB=imagebar.create(bgimage, fgimage, sizex, sizey, x, y, z)
return s
endmethod
method fade takes integer fromalpha, integer toalpha, real overtime, boolean destroy returns nothing
local ARGB c
if overtime<=0 then
call .destroy()
endif
set .current=.KeepInBounds(fromalpha, 0x00, 0xFF)
set .target=.KeepInBounds(toalpha, 0x00, 0xFF)
set .delta=(.target-.current)*TICK/overtime
set .dodestroy=destroy
// change the alpha of all channels of the bar to fromalpha
// background first
set c=.IB.getBackgroundColor()
set c.alpha=fromalpha
call .IB.setBackgroundColor(c)
// then mask
set c=.IB.getMaskColor()
set c.alpha=fromalpha
call .IB.setMaskColor(c)
// then foreground
set c=s.IB.getForegroundColor()
set c.alpha=fromalpha
call s.IB.setForegroundColor(c)
// make sure we dont add it twice to the list of fading bars
if not .fading then
set .Structs[.Count]=this
set .i=.Count
if .Count==0 then
call TimerStart(.T, TICK, true, function thistype.Callback)
endif
set .Count=.Count+1
set .fading=true
endif
endmethod
method fadeOut takes real time returns nothing
call .fade(.IB.getForegroundColor(), 0, time, true)
endmethod
method setBackgroundColor takes ARGB color returns nothing
if not .fading then
call .IB.setBackgroundColor(color)
endif
endmethod
method setMaskColor takes ARGB color returns nothing
if not .fading then
call .IB.setMaskColor(color)
endif
endmethod
method setForegroundColor takes ARGB color returns nothing
if not .fading then
call .IB.setForegroundColor(color)
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library CastingBar requires ImageFadeBars, ARGB
// Zwiebelchen's Casting Bar System
// redone.
// Requires NewGen, such as Warcraft III Patch 1.24b
globals
private constant string BAR_BG_IMAGE = "Blank128.blp"
private constant string BAR_FG_IMAGE = "Blank128.blp"
private constant real BAR_WIDTH = 128
private constant real BAR_HEIGHT = 24
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
imagefadebar 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)
// 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.percentFill=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()
// string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
set s.bar=imagefadebar.create(BAR_BG_IMAGE, BAR_FG_IMAGE, BAR_WIDTH, BAR_HEIGHT, GetUnitX(caster)+CASTING_BAR_X_OFFSET,GetUnitY(caster)+CASTING_BAR_Y_OFFSET,GetUnitFlyHeight(caster)+CASTING_BAR_Z_OFFSET)
set s.bar.show=IsPlayerInForce(GetLocalPlayer(), disp)
call s.bar.lockToUnit(caster, CASTING_BAR_X_OFFSET, CASTING_BAR_Y_OFFSET, CASTING_BAR_Z_OFFSET)
if channel then
call s.bar.setBackgroundColor(ARGB(BACKGROUND_COLOR_CHANNEL))
call s.bar.setForegroundColor(ARGB(COLOR_CHANNEL))
else
call s.bar.setBackgroundColor(ARGB(BACKGROUND_COLOR))
call s.bar.setForegroundColor(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 AutoIndex, ImageFadeBars, ARGB
globals
private constant integer BAR_BG_RED = 0x20 // Background Red of the bar
private constant integer BAR_BG_GREEN = 0x20 // Background Green of the bar
private constant integer BAR_BG_BLUE = 0x20 // Background Blue of the bar
private constant integer BAR_ALPHA = 0xFF // Alpha of the bar
private constant string BAR_BG_IMAGE = "Blank128.blp" //
private constant string BAR_FG_IMAGE = "Blank128.blp" //
private constant string BAR_MASK_IMAGE = "war3mapimported\\ExperienceMask2.tga"
private constant integer BAR_MASK_COLOR = 0xFFFFFFFF
private ARGB BAR_DEF_GRADIENT = 0xff00ff00
private constant real BAR_WIDTH = 256 // Width in chars
private constant real BAR_HEIGHT = 32 // size of each char.
private constant real BAR_XOFFSET = -128. // 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 = 1./32 // 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(1.0, 0xffcc0000) // i recommend keeping at least this one; you can still change its color
call s.Bar.addGradient(0.9, 0xffb51600)
call s.Bar.addGradient(0.8, 0xff9e2d00)
call s.Bar.addGradient(0.7, 0xff884400)
call s.Bar.addGradient(0.6, 0xff715a00)
call s.Bar.addGradient(0.5, 0xff5a7100)
call s.Bar.addGradient(0.4, 0xff448800)
call s.Bar.addGradient(0.3, 0xff2d9e00)
call s.Bar.addGradient(0.2, 0xff16b500)
call s.Bar.addGradient(0.1, 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 imagefadebar 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=imagefadebar.create(BAR_BG_IMAGE, BAR_FG_IMAGE, BAR_WIDTH, BAR_HEIGHT, 0, 0, 0)
set s.Bar.show=IsPlayerInForce(GetLocalPlayer(), tmpf)
call s.Bar.setBackgroundColor(ARGB.create(BAR_ALPHA, BAR_BG_RED, BAR_BG_GREEN, BAR_BG_BLUE))
call s.Bar.setForegroundColor(BAR_DEF_GRADIENT)
call s.Bar.addMask(BAR_MASK_IMAGE, ARGB(BAR_MASK_COLOR), BAR_WIDTH+2, BAR_HEIGHT+2, -1,-1)
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.percentFill=(.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)
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 = GetUnitId(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=GetUnitId(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=GetUnitId(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 Test initializer Init requires ImageBars, ARGB, RAGE
globals
private constant real TICK = 1./32
private integer MODE
private real TIME=5. // seconds
private imagebar ib
private unit U
endglobals
private function Callback takes nothing returns nothing
local real new
if MODE==0 then
set new=ib.percentFill+(1./TIME*TICK)
if new>1 then
set MODE=1
call ib.setOrientation(true, true)
set ib.percentFill=0
set Rage[U].Amount=37.5
set Rage[U].Decay=50/20.
else
set ib.percentFill=new
endif
elseif MODE==1 then
set new=ib.percentFill+(1./TIME*TICK)
if new>1 then
set MODE=2
call ib.setOrientation(false, false)
set ib.percentFill=0
call ib.setForegroundSize(32, 256)
call ib.setForegroundImage("war3mapimported\\ExperienceFG2.tga")
call ib.setBackgroundSize(32, 256)
call ib.setMaskSize(34,258)
call ib.setMaskImage("war3mapimported\\ExperienceMask3.tga")
call ib.setOffset(0, -128, 0)
else
set ib.percentFill=new
endif
elseif MODE==2 then
set new=ib.percentFill+(1./TIME*TICK)
if new>1 then
set MODE=3
call ib.setOrientation(false, true)
set ib.percentFill=0
else
set ib.percentFill=new
endif
elseif MODE==3 then
set new=ib.percentFill+(1./TIME*TICK)
if new>1 then
call PauseTimer(GetExpiredTimer())
call ib.destroy()
else
set ib.percentFill=new
endif
endif
endfunction
private function Init takes nothing returns nothing
local unit u=CreateUnit(Player(0), 'hfoo', 0,0,0)
set ib=imagebar.create("Blank128.blp", "war3mapimported\\ExperienceFG.tga", 256, 32, 0,0,0)
call ib.setForegroundColor(0xFFFFFFFF)
call ib.setBackgroundColor(0xFF000000)
call ib.addMask("war3mapimported\\ExperienceMask2.tga", 0xFFFFFFFF, 258,34,-1,-1)
call ib.lockToUnit(u, -128, 0, 0)
set ib.wrap=true
call SetCameraPosition(0,0)
set MODE=0
call TimerStart(CreateTimer(), TICK, true, function Callback)
set U=u
set u=null
endfunction
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
// *************************************************************
// * ImageBars -- Version 1.1.3
// * by Deaod
// *************************************************************
// *
// * CREDITS:
// * - Anitarf and Rising_Dusk (Help, Suggestions)
// * - Vexorian (JassHelper, ARGB)
// * - MindWorX and PitzerMike (JassNewGenPack)
// * - Pipedream (Grimoire)
// * - SFilip (TESH)
// *
// * - grim001 (AutoIndex)
// * - cohadar (some snippets from PUI i used)
// * - zwiebelchen (original CastingBar library)
// *
// * HOW TO IMPORT:
// * * C'n'P the code into your map
// * * If you haven't done that already, import ARGB into your map
// * * Import the images you want to use for the bars
// *
// * DESCRIPTION:
// *
// * I'll use this approach for this library, since documenting
// * the whole API in detail would be a pain in the ass for
// * both you and me.
// *
// * You can create a new imagebar using the following function:
// * static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
// * Note that sizex and sizey are the initial dimensions for
// * both, back- and foreground, and that the initial offset
// * of the foreground is 0 in both directions (X and Y).
// * Also note that as of Version 1.1.0 all z heights are offsets
// * from the height of the ground at the origin of the bar.
// *
// * But what good is a bar when you cant fill it? Nothing,
// * so here's how you actually fill the bar:
// * By changing the percentFill instance member. Valid values
// * range from 0 to 1.
// *
// * By default the bar is horizontal and fills from left to right.
// * This can be changed using the following method:
// * method setOrientation takes boolean horizontal, boolean righttoleft returns nothing
// * Note that righttoleft becomes uptodown if horizontal is true.
// *
// * ImageBars consist of up to three layers. A foreground,
// * a background and optionally a mask.
// * The background is rendered below the foreground, and the
// * mask in turn is rendered above the foreground.
// * The position of the image is the lower left corner
// * of the BACKGROUND. The foreground and the mask can be
// * offset from that position individually.
// *
// * Foreground and background are activated by default. You
// * can add a mask by calling the instance method addMask.
// * method addMask takes string maskimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
// * You can adjust the mask using the following methods:
// * method setMaskOffset takes real offx, real offy returns nothing
// * method setMaskSize takes real sizex, real sizey returns nothing
// * method setMaskImage takes string maskimage returns nothing
// * method setMaskColor takes ARGB color returns nothing
// * Additionally, you can use addMask to combine these methods.
// * Should you ever decide not to use a mask at runtime anymore,
// * you can remove the mask using the following method:
// * method removeMask takes nothing returns nothing
// * You can get the color of the mask using the following method:
// * method getMaskColor takes nothing returns ARGB
// *
// * You can adjust the foreground using the following methods:
// * method adjustForeground takes string fgimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
// * method setForegroundOffset takes real offx, real offy returns nothing
// * method setForegroundSize takes real sizex, real sizey returns nothing
// * method setForegroundImage takes string fgimage returns nothing
// * method setForegroundColor takes ARGB color returns nothing
// * You can get the color of the foreground using the following method:
// * method getForegroundColor takes nothing returns ARGB
// *
// * You can adjust the background using the following methods:
// * method adjustBackground takes string bgimage, ARGB color, real sizex, real sizey returns nothing
// * method setBackgroundSize takes real sizex, real sizey returns nothing
// * method setBackgroundImage takes string bgimage returns nothing
// * method setBackgroundColor takes ARGB color returns nothing
// * You can get the color of the background using the following method:
// * method getBackgroundColor takes nothing returns ARGB
// *
// * You can change the position of the imagebar using the
// * following method:
// * method setPosition takes real x, real y, real z returns nothing
// * Additionally, there are the variables x, y and z, which
// * can be changed individually.
// *
// * If you want the bar to follow a unit, use the method
// * lockToUnit.
// * method lockToUnit takes unit which, real offx, real offy, real offz returns nothing
// * which is the unit you want to lock the bar to; offx, offy and
// * offz are the offset in the respective direction from the
// * origin of the unit.
// * You can adjust the offset from the unit by using the
// * following method:
// * method setOffset takes real offx, real offy, real offz returns nothing
// * If you want to unlock the bar, you can either pass "null"
// * as the unit parameter to lockToUnit, or you can use the
// * following method:
// * method unlock takes nothing returns nothing
// * Should you want to access the unit the bars locked to, use
// * the following method:
// * method getUnitLockedTo takes nothing returns unit
// * NOTE: While being locked to a unit, you cant change the
// * position of the bar freely.
// * Also note, that changing the offset is only possible when the
// * bar is locked to a unit.
// *
// * You can show and hide the imagebar at will by changing
// * the "show" member. true shows the imagebar, false hides
// * it.
// *
// * You can make imagebars wrap to the terrain by changing
// * the "wrap" member. true wraps the imagebar to the ground,
// * false doesnt.
// * Note that while being wrapped to the ground, changing the
// * Z position of the imagebar wont have any effect.
// *
// * You can destroy an imagebar using the following method:
// * method destroy takes nothing returns nothing
// *
// *************************************************************
library ImageBars uses ARGB, ImageUtils
globals
private constant real TICK = 1./40 // frequency of syncing bars with position of units theyre locked to
private constant integer DEFAULT_BACKGROUND_COLOR = 0xFFFFFFFF
private constant integer DEFAULT_FOREGROUND_COLOR = 0xFF002040
private constant integer BACKGROUND_IMAGE_TYPE = IMAGE_TYPE_INDICATOR // 2 // lowest layer
private constant integer FOREGROUND_IMAGE_TYPE = IMAGE_TYPE_OCCLUSION_MASK // 3 // middle layer
private constant integer MASK_IMAGE_TYPE = IMAGE_TYPE_SELECTION // 1 // top layer
endglobals
struct imagebar
private imagex FG
private imagex BG
// position of the bar
private real X
private real Y
private real Z
// Colors
private ARGB BGColor
private ARGB FGColor
// OffX/Y is the offset when locked to a unit
// FGOffX/Y is always active
private real OffX
private real OffY
private real OffZ
private real FGOffX
private real FGOffY
// SizeX/Y is the size of the background
// FGSizeX/Y is the maximum size of the foreground.
private real SizeX
private real SizeY
private real FGSizeX
private real FGSizeY
// Mask
private boolean Mask=false
private imagex MI // mask image
private ARGB MaskColor
private real MaskSizeX
private real MaskSizeY
private real MaskOffX
private real MaskOffY
private real Value=0.
private boolean Show=true
private boolean Wrap=false
private boolean Locked=false
private unit Which=null
private boolean Horizontal=true
private boolean RightToLeft=false // UpToDown, if Horizontal is false
private integer i
private static thistype array Structs
private static integer Count=0
private static timer T=CreateTimer()
private static location LocZ=Location(0,0)
// private methods
private static method GetPointZ takes real x, real y returns real
call MoveLocation(.LocZ, x, y)
return GetLocationZ(.LocZ)
endmethod
private static method GetUnitZ takes unit u returns real
return .GetPointZ(GetUnitX(u), GetUnitY(u))+GetUnitFlyHeight(u)
endmethod
private method GetZ takes nothing returns real
if .Locked then
return .GetUnitZ(.Which)+.OffZ
else
return .GetPointZ(.X, .Y)+.Z
endif
endmethod
private method MapForeground takes string fgimage returns nothing
call .FG.destroy()
if .Horizontal then
if .RightToLeft then
set .FG=imagex.create(fgimage, .Value*.FGSizeX, .FGSizeY, .X+.FGOffX+.OffX+(1-.Value)*.FGSizeX, .Y+.FGOffY+.OffY, .GetZ(), .Show)
else
set .FG=imagex.create(fgimage, .Value*.FGSizeX, .FGSizeY, .X+.FGOffX+.OffX, .Y+.FGOffY+.OffY, .GetZ(), .Show)
endif
else
if .RightToLeft then
set .FG=imagex.create(fgimage, .FGSizeX, .Value*.FGSizeY, .X+.FGOffX+.OffX, .Y+.FGOffY+.OffY+(1-.Value)*.FGSizeY, .GetZ(), .Show)
else
set .FG=imagex.create(fgimage, .FGSizeX, .Value*.FGSizeY, .X+.FGOffX+.OffX, .Y+.FGOffY+.OffY, .GetZ(), .Show)
endif
endif
set .FG.type=FOREGROUND_IMAGE_TYPE
set .FG.color=.FGColor
endmethod
private static method Callback takes nothing returns nothing
local integer i=.Count-1
local thistype s
local real dx
local real dy
local real x
local real y
local real z
loop
exitwhen i<0
set s=.Structs[i]
set x=GetUnitX(s.Which)
set y=GetUnitY(s.Which)
set dx=x-s.X
set dy=y-s.Y
set s.X=x
set s.Y=y
set z=.GetUnitZ(s.Which)+s.OffZ
call s.BG.setPosition(s.BG.x+dx, s.BG.y+dy, z)
if s.Mask then
call s.MI.setPosition(s.MI.x+dx, s.MI.y+dy, z)
endif
call s.FG.setPosition(s.FG.x+dx, s.FG.y+dy, z)
set i=i-1
endloop
endmethod
// Foreground related methods
method adjustForeground takes string fgimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
set .FGOffX=-offx
set .FGOffY=-offy
set .FGSizeX=sizex
set .FGSizeY=sizey
set .FGColor=color
call .MapForeground(fgimage)
endmethod
method setForegroundOffset takes real offx, real offy returns nothing
local real dx=-.FGOffX-offx
local real dy=-.FGOffY-offy
set .FGOffX=-offx
set .FGOffY=-offy
call .FG.setPosition(.FG.x+dx, .FG.y+dy, .GetZ())
endmethod
method setForegroundSize takes real sizex, real sizey returns nothing
set .FGSizeX=sizex
set .FGSizeY=sizey
call .MapForeground(.FG.path)
endmethod
method setForegroundImage takes string fgimage returns nothing
set .FG.path=fgimage
endmethod
method getForegroundColor takes nothing returns ARGB
return .FGColor
endmethod
method setForegroundColor takes ARGB color returns nothing
set .FGColor=color
set .FG.color=color
endmethod
// Background related methods
method adjustBackground takes string bgimage, ARGB color, real sizex, real sizey returns nothing
set .SizeX=sizex
set .SizeY=sizey
set .BGColor=color
call .BG.destroy()
set .BG=imagex.create(bgimage, sizex, sizey, .X+OffX, .Y+.OffY, .GetZ(), .Show)
set .BG.type=BACKGROUND_IMAGE_TYPE
set .BG.color=color
endmethod
method setBackgroundSize takes real sizex, real sizey returns nothing
set .SizeX=sizex
set .SizeY=sizey
call .BG.setSize(sizex, sizey)
endmethod
method setBackgroundImage takes string bgimage returns nothing
set .BG.path=bgimage
endmethod
method getBackgroundColor takes nothing returns ARGB
return .BGColor
endmethod
method setBackgroundColor takes ARGB color returns nothing
set .BGColor=color
set .BG.color=color
endmethod
// Mask related methods
method addMask takes string maskimage, ARGB color, real sizex, real sizey, real offx, real offy returns nothing
if .Mask then
call .MI.destroy()
endif
set .MI=imagex.create(maskimage, sizex, sizey, .X+.OffX+offx, .Y+.OffY+offy, .GetZ(), .Show)
set .MI.type=MASK_IMAGE_TYPE
set .MI.color=color
set .MaskColor=color
set .MaskSizeX=sizex
set .MaskSizeY=sizey
set .MaskOffX=offx
set .MaskOffY=offy
set .Mask=true
endmethod
method removeMask takes nothing returns nothing
if .Mask then
call .MI.destroy()
set .Mask=false
endif
endmethod
method setMaskImage takes string maskimage returns nothing
if .Mask then
set .MI.path=maskimage
endif
endmethod
method getMaskColor takes nothing returns ARGB
return .MaskColor
endmethod
method setMaskColor takes ARGB color returns nothing
if .Mask then
set .MaskColor=color
set .MI.color=color
endif
endmethod
method setMaskSize takes real sizex, real sizey returns nothing
if .Mask then
set .MaskSizeX=sizex
set .MaskSizeY=sizey
call .MI.setSize(sizex, sizey)
endif
endmethod
method setMaskOffset takes real offx, real offy returns nothing
local real dx=offx-.MaskOffX
local real dy=offy-.MaskOffY
if .Mask then
set .MaskOffX=offx
set .MaskOffY=offy
call .MI.setPosition(.MI.x+dx, .MI.y+dy, .GetZ())
endif
endmethod
// General methods
static method create takes string bgimage, string fgimage, real sizex, real sizey, real x, real y, real z returns thistype
local thistype s=.allocate()
set s.BG=imagex.create(bgimage, sizex, sizey, x, y, .GetPointZ(x,y)+z, true)
set s.FG=imagex.create(fgimage, 1, sizey, x, y, .GetPointZ(x,y)+z, true)
set s.X=x
set s.Y=y
set s.Z=z
set s.BGColor=ARGB(DEFAULT_BACKGROUND_COLOR)
set s.FGColor=ARGB(DEFAULT_FOREGROUND_COLOR)
set s.SizeX=sizex
set s.SizeY=sizey
set s.FGSizeX=sizex
set s.FGSizeY=sizey
return s
endmethod
method operator percentFill takes nothing returns real
return .Value
endmethod
method operator percentFill= takes real new returns nothing
set .Value=new
if .Value>1. then
set .Value=1.
elseif .Value<0. then
set .Value=0.
endif
call .MapForeground(.FG.path)
endmethod
method setOrientation takes boolean horizontal, boolean righttoleft returns nothing
set .Horizontal=horizontal
set .RightToLeft=righttoleft
call .MapForeground(.FG.path)
endmethod
method operator x takes nothing returns real
return .X
endmethod
method operator y takes nothing returns real
return .Y
endmethod
method operator z takes nothing returns real
return .Z
endmethod
method operator x= takes real new returns nothing
local real dx=new-.X
if not .Locked then
set .X=new
set .BG.x=.BG.x+dx
set .FG.x=.FG.x+dx
if .Mask then
set .MI.x=.MI.x+dx
endif
endif
endmethod
method operator y= takes real new returns nothing
local real dy=new-.Y
if not .Locked then
set .Y=new
set .BG.y=.BG.y+dy
set .FG.y=.FG.y+dy
if .Mask then
set .MI.y=.MI.y+dy
endif
endif
endmethod
method operator z= takes real new returns nothing
local real dz=new-.Z
if not .Locked then
set .Z=new
set .BG.z=.BG.z+dz
set .FG.z=.FG.z+dz
if .Mask then
set .MI.z=.MI.z+dz
endif
endif
endmethod
method setPosition takes real x, real y, real z returns nothing
local real dx=x-.X
local real dy=y-.Y
local real nz
if not .Locked then
set .X=x
set .Y=y
set .Z=z
set nz=.GetPointZ(.BG.x+dx, .BG.y+dy)+.Z
call .BG.setPosition(.BG.x+dx, .BG.y+dy, nz)
if .Mask then
call .MI.setPosition(.MI.x+dx, .MI.y+dy, nz)
endif
call .FG.setPosition(.FG.x+dx, .FG.y+dy, nz)
endif
endmethod
method unlock takes nothing returns nothing
if .Locked then
set .Which=null
set .Locked=false
call .BG.setPosition(.BG.x-.OffX, .BG.y-.OffY, .GetPointZ(.BG.x-.OffX, .BG.y-.OffY)+.Z)
if .Mask then
call .MI.setPosition(.MI.x-.OffX, .MI.y-.OffY, .GetPointZ(.MI.x-.OffX, .MI.y-.OffY)+.Z)
endif
call .MapForeground(.FG.path)
set .OffX=0
set .OffY=0
set .Count=.Count-1
set .Structs[.i]=.Structs[.Count]
set .Structs[.i].i=.i
if .Count==0 then
call PauseTimer(.T)
endif
endif
endmethod
method lockToUnit takes unit which, real offx, real offy, real offz returns nothing
if which==null then
call .unlock()
elseif .Locked then
set .Which=which
set .OffZ=offz
call .BG.setPosition(.BG.x+(offx-.OffX), .BG.y+(offy-.OffY), .GetZ())
if .Mask then
call .MI.setPosition(.MI.x+(offx-.OffX), .MI.y+(offy-.OffY), .GetZ())
endif
call .MapForeground(.FG.path)
set .OffX=offx
set .OffY=offy
else
set .Locked=true
set .Which=which
set .OffX=offx
set .OffY=offy
set .OffZ=offz
call .BG.setPosition(.BG.x+offx, .BG.y+offy, .GetZ())
if .Mask then
call .MI.setPosition(.MI.x+offx, .MI.y+offy, .GetZ())
endif
call .MapForeground(.FG.path)
set .Structs[.Count]=this
set .i=.Count
if .Count==0 then
call TimerStart(.T, TICK, true, function thistype.Callback)
endif
set .Count=.Count+1
endif
endmethod
method getUnitLockedTo takes nothing returns unit
return .Which
endmethod
method setOffset takes real offx, real offy, real offz returns nothing
local real dx
local real dy
if .Locked then
set dx=offx-.OffX
set dy=offy-.OffY
set .OffX=offx
set .OffY=offy
set .OffZ=offz
call .BG.setPosition(.BG.x+dx, .BG.y+dy, .GetUnitZ(.Which)+.OffZ)
if .Mask then
call .MI.setPosition(.MI.x+dx, .MI.y+dy, .GetUnitZ(.Which)+.OffZ)
endif
call .MapForeground(.FG.path)
endif
endmethod
method operator show takes nothing returns boolean
return .Show
endmethod
method operator show= takes boolean new returns nothing
set .Show=new
set .BG.show=new
if .Mask then
set .MI.show=new
endif
set .FG.show=new
endmethod
method operator wrap takes nothing returns boolean
return .Wrap
endmethod
method operator wrap= takes boolean new returns nothing
set .Wrap=new
set .BG.wrap=new
if .Mask then
set .MI.wrap=new
endif
set .FG.wrap=new
endmethod
method onDestroy takes nothing returns nothing
if .Locked then
call .unlock()
endif
if .Mask then
call .MI.destroy()
endif
call .BG.destroy()
call .FG.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library AutoIndex
//===========================================================================
// Information:
//==============
//
// AutoIndex is a very simple script to utilize. Just call GetUnitId(unit) to
// get get the unique value assigned to a particular unit. AutoIndex differs from
// other unit indexing libraries because it automatically assigns an ID to each
// unit as it enters the map, and automatically frees that ID as the unit leaves
// the map. This gives you several advantages as the user:
//
// 1.) The GetUnitId function inlines directly to a GetUnitUserData call (or a
// LoadInteger call if UseUnitUserData is disabled.)
// 2.) You don't need to manually free IDs as units leave the map.
// 3.) Detecting removing units to free their indexes is O(1), and less costly
// performance-wise than a timer scanning the map for removed units.
//
// If you turn on debug mode, AutoIndex will become slower, but it will show
// you a variety of helpful error messages. It can detect the following problems:
// -Passing a null unit to GetUnitId
// -Passing a removed or decayed unit to GetUnitId
// -Code outside of AutoIndex has overwritten a unit's UserData value.
// -GetUnitId was used on a filtered unit (a unit you don't want indexed).
//
// AutoIndex also provides events upon indexing or deindexing units. This
// effectively allows you to notice when units enter or leave the game, and
// handle the creation or destruction of attached data or other things.
//
//===========================================================================
// How to install AutoIndex:
//===========================
//
// 1.) Copy and paste this script into your map.
// 2.) Save it to allow the ObjectMerger macro to generate the "Leave Detect"
// ability for you. Close and re-open the map. After that, disable the macro
// to prevent the save delay.
//
//===========================================================================
// How to use AutoIndex:
//=======================
//
// So you can get a unique integer for each unit, but how do you use that to
// attach data to a unit? GetUnitId will always return a number in the range of
// 1-8190. This means it can be used as an array index, as demonstrated below:
//
// globals
// integer array IntegerData
// real array RealData
// SomeStruct array SomeStructData
// englobals
//
// function Example takes nothing returns nothing
// local unit u = CreateUnit(...)
// local integer id = GetUnitId(u)
// //You now have a unique index for the unit, so you can
// //attach or retrieve data about the unit using arrays.
// set IntegerData[id] = 5
// set RealData[id] = 25.0
// set SomeStructData[id] = SomeStruct.create()
// //If you have access to the same unit in another function, you can
// //retrieve the data by using GetUnitId() and reading the arrays.
// endfunction
//
// The UnitFilter function in the config section is provided so that you can
// make AutoIndex completely ignore any unit-types that don't want to be indexed.
// You may want to ignore dummy casters or system-private units, especially ones
// that use UnitUserData internally. You don't need to worry about xe dummy units,
// as those are automatically filtered.
//
//===========================================================================
// How to use OnUnitIndexed / OnUnitDeindexed:
//=============================================
//
// AutoIndex will fire the OnUnitIndexed event when a unit enters the map,
// and the OnUnitDeindexed event when a unit leaves the map. Functions used
// as events must take a unit and return nothing. An example is given below:
//
// function UnitEntersMap takes unit u returns nothing
// call BJDebugMsg(GetUnitName(u)+" was indexed with the ID "+I2S(GetUnitId(u)))
// endfunction
//
// function UnitLeavesMap takes unit u returns nothing
// call BJDebugMsg(GetUnitName(u)+" was deindexed with the ID "+I2S(GetUnitId(u)))
// endfunction
//
// function Init takes nothing returns nothing
// call OnUnitIndexed(UnitEntersMap)
// call OnUnitDeindexed(UnitLeavesMap)
// endfunction
//
// As you can see, it works perfectly fine to call GetUnitId() on a unit
// during either of these events.
//
// If you call OnUnitIndexed during map initialization, every existing
// unit will be considered as entering the map. This saves you from needing
// to manually enumerate preplaced units (or units created by initialization
// code that ran before OnUnitIndexed was called).
//
// OnUnitDeindexed runs while a unit still exists, which means you can
// still do things such as destroy special effects attached to the unit.
// The unit will cease to exist immediately after the event is over.
//
//===========================================================================
// AutoIndex API:
//================
//
// GetUnitId(unit) -> integer
// This function returns a unique ID in the range of 1-8190 for the
// specified unit. Use it to attach data to the unit. This function
// inlines directly to GetUnitUserData or LoadInteger if debug mode
// is disabled. If debug mode is enabled, it can display error mess-
// ages when passed a null, decayed or filtered unit.
//
// IsUnitIndexed(unit) -> boolean
// This function returns a boolean indicating whether the specified
// unit is indexed or not. A unit would not be indexed if you ignored
// it using the UnitFilter function, or if it is a xe dummy unit.
//
// OnUnitIndexed(IndexFunc)
// This function accepts an IndexFunc, which must take a unit and
// return nothing. The IndexFunc will be fired instantly whenever
// a unit enters the map. You may use GetUnitId on the unit. When
// you call this function during map initialization, every existing
// unit will be considered as entering the map.
//
// OnUnitDeindexed(IndexFunc)
// Same as above, but runs whenever a unit is leaving the map. When
// this event runs, the unit still exists, but it will cease to exist
// as soon as the event ends. You may use GetUnitId on the unit.
//
//===========================================================================
// Configuration:
//================
//! external ObjectMerger w3a Adef lvdt anam "Leave Detect" aart "" arac 0
//Save your map with this Object Merger call enabled, then close and reopen your
//map. Disable it by removing the exclamation to remove the delay while saving.
globals
private constant integer LeaveDetectAbilityID = 'lvdt'
//This rawcode must match the parameter after "Adef" in the
//ObjectMergermacro above. You can change both if you want.
private constant boolean UseUnitUserData = true
//If this is set to true, UnitUserData will be used. You should only set
//this to false if something else in your map already uses UnitUserData.
//A hashtable will be used instead, but it is about 60% slower.
endglobals
public function UnitFilter takes nothing returns boolean
return true
endfunction
//Any units you filter out in this function will not be indexed.
//Use GetFilterUnit() to refer to the filtered unit. You do not
//need to filter out xe dummy units; they are already filtered.
//===========================================================================
// User functions:
//=================
function GetUnitId takes unit u returns integer
static if DEBUG_MODE then
return AutoIndex.getIndexDebug(u)
else
return AutoIndex.getIndex(u)
endif
endfunction
function IsUnitIndexed takes unit u returns boolean
return AutoIndex.isUnitIndexed(u)
endfunction
function interface IndexFunc takes unit u returns nothing
function OnUnitIndexed takes IndexFunc func returns nothing
call AutoIndex.onUnitIndexed(func)
endfunction
function OnUnitDeindexed takes IndexFunc func returns nothing
call AutoIndex.onUnitDeindexed(func)
endfunction
//===========================================================================
hook RemoveUnit AutoIndex.hook_RemoveUnit
hook ReplaceUnitBJ AutoIndex.hook_ReplaceUnitBJ
debug hook SetUnitUserData AutoIndex.hook_SetUnitUserData
struct AutoIndex
private static trigger enter = CreateTrigger()
private static trigger status = CreateTrigger()
private static trigger creepdeath = CreateTrigger()
private static group preplaced = CreateGroup()
private static timer allowdecay = CreateTimer()
private static hashtable ht
private static boolean array dead
private static boolean array summoned
private static boolean array animated
private static boolean array nodecay
private static boolean array removing
private static IndexFunc array indexfuncs
private static integer indexfuncs_n = -1
private static IndexFunc array deindexfuncs
private static integer deindexfuncs_n = -1
private static IndexFunc indexfunc
private static unit array allowdecayunit
private static integer allowdecay_n = -1
private static boolean duringinit = true
private static boolean array altered
private static unit array idunit
//===========================================================================
static method getIndex takes unit u returns integer
static if UseUnitUserData then
return GetUnitUserData(u)
else
return LoadInteger(ht, 0, GetHandleId(u))
endif
endmethod
//Resolves to an inlinable one-liner after the static if.
static method getIndexDebug takes unit u returns integer
local integer index = getIndex(u)
if u == null then
call BJDebugMsg("AutoIndex error: Null unit passed to GetUnitId.")
elseif GetUnitTypeId(u) == 0 then
call BJDebugMsg("AutoIndex error: Removed or decayed unit passed to GetUnitId.")
elseif idunit[index] != u then
call BJDebugMsg("AutoIndex error: "+GetUnitName(u)+" is a filtered unit.")
endif
return index
endmethod
//If debug mode is enabled, use the getIndex method that shows errors.
static method setIndex takes unit u, integer index returns nothing
static if UseUnitUserData then
call SetUnitUserData(u, index)
else
call SaveInteger(ht, 0, GetHandleId(u), index)
endif
endmethod
//Resolves to an inlinable one-liner after the static if.
//===========================================================================
static method isUnitAnimateDead takes unit u returns boolean
return animated[getIndex(u)]
endmethod
//Don't use this; use IsUnitAnimateDead from StatusEvents instead.
static method isUnitIndexed takes unit u returns boolean
return u != null and idunit[getIndex(u)] == u
endmethod
//===========================================================================
private static method onUnitIndexed_sub takes nothing returns nothing
call indexfunc.evaluate(GetEnumUnit())
endmethod
//During initialization, evaluate the indexfunc for every preplaced unit.
static method onUnitIndexed takes IndexFunc func returns nothing
set indexfuncs_n = indexfuncs_n + 1
set indexfuncs[indexfuncs_n] = func
if duringinit then
set indexfunc = func
call ForGroup(preplaced, function AutoIndex.onUnitIndexed_sub)
endif
endmethod
static method onUnitDeindexed takes IndexFunc func returns nothing
set deindexfuncs_n = deindexfuncs_n + 1
set deindexfuncs[deindexfuncs_n] = func
endmethod
//===========================================================================
private static method hook_RemoveUnit takes unit whichUnit returns nothing
set removing[getIndex(whichUnit)] = true
endmethod
private static method hook_ReplaceUnitBJ takes unit whichUnit, integer newUnitId, integer unitStateMethod returns nothing
set removing[getIndex(whichUnit)] = true
endmethod
//Intercepts whenever RemoveUnit or ReplaceUnitBJ is called and sets a flag.
private static method hook_SetUnitUserData takes unit whichUnit, integer data returns nothing
static if UseUnitUserData then
if IsUnitIndexed(whichUnit) then
if getIndex(whichUnit) == data then
call BJDebugMsg("AutoIndex error: Code outside AutoIndex attempted to alter "+GetUnitName(whichUnit)+"'s index.")
else
call BJDebugMsg("AutoIndex error: Code outside AutoIndex altered "+GetUnitName(whichUnit)+"'s index.")
if idunit[data] != null then
call BJDebugMsg("AutoIndex error: "+GetUnitName(whichUnit)+" and "+GetUnitName(idunit[data])+" now have the same index.")
endif
set altered[data] = true
endif
endif
endif
endmethod
//In debug mode, intercepts whenever SetUnitUserData is used on an indexed unit.
//Displays an error message if outside code tries to alter a unit's index.
//===========================================================================
private static method allowDecay takes nothing returns nothing
local integer n = allowdecay_n
loop
exitwhen n < 0
set nodecay[getIndex(allowdecayunit[n])] = false
set allowdecayunit[n] = null
set n = n - 1
endloop
set allowdecay_n = -1
endmethod
//Iterate through all the units in the stack and allow them to decay again.
private static method detectStatus takes nothing returns boolean
local unit u = GetTriggerUnit()
local integer index = getIndex(u)
local integer n
if idunit[index] == u then //Ignore non-indexed units.
if not IsUnitType(u, UNIT_TYPE_DEAD) then
if dead[index] then //The unit was dead, but now it's alive.
set dead[index] = false //The unit has been resurrected.
//! runtextmacro optional RunStatusEvent("Resurrect")
//If StatusEvents is in the map, run the resurrection events.
if IsUnitType(u, UNIT_TYPE_SUMMONED) and not summoned[index] then
set summoned[index] = true //If the unit gained the summoned flag,
set animated[index] = true //it's been raised with Animate Dead.
//! runtextmacro optional RunStatusEvent("AnimateDead")
//If StatusEvents is in the map, run the Animate Dead events.
endif
endif
else
if not removing[index] and not dead[index] and not animated[index] then
set dead[index] = true //The unit was alive, but now it's dead.
set nodecay[index] = true //A dead unit can't decay for at least 0. seconds.
set allowdecay_n = allowdecay_n + 1 //Add the unit to a stack. After the timer
set allowdecayunit[allowdecay_n] = u //expires, allow the unit to decay again.
call TimerStart(allowdecay, 0., false, function AutoIndex.allowDecay)
//! runtextmacro optional RunStatusEvent("Death")
//If StatusEvents is in the map, run the Death events.
//! runtextmacro optional TransportUnload()
//If TransportEvents is in the map, remove the dead unit from whatever transport it's in.
elseif removing[index] or (dead[index] and not nodecay[index]) or (not dead[index] and animated[index]) then
//If .nodecay was false and the unit is dead and was previously dead, the unit decayed.
//If .animated was true and the unit is dead, the unit died and exploded.
//If .removing was true, the unit is being removed or replaced.
//! runtextmacro optional TransportUnload()
//If TransportEvents is in the map, remove the leaving unit from whatever transport it's in.
set n = deindexfuncs_n
loop //Run the OnUnitDeindexed events.
exitwhen n < 0
call deindexfuncs[n].evaluate(u)
set n = n - 1
endloop
//! runtextmacro optional TransportClean()
//If TransportEvents is in the map, and the leaving unit is a
//transport, clean the transport- related data from the unit.
call AutoIndex(index).destroy() //Free the index by destroying the AutoIndex struct.
set idunit[index] = null //Null this unit reference to prevent a leak.
endif
endif
endif
set u = null
return false
endmethod
private static method isUndefendOrder takes nothing returns boolean
//! runtextmacro optional TransportUnloadCheck()
//If TransportEvents is in the map, check whether a unit is unloading.
return GetIssuedOrderId() == 852056
endmethod
//===========================================================================
private static method unitEntersMap takes unit u returns nothing
local integer index
local integer n = 0
if getIndex(u) != 0 then //If a unit already has an ID, don't assign a new one.
return //This only happens if a unit leaves the entire map area.
endif
set index = create()
call setIndex(u, index) //Assign an index to the entering unit.
call UnitAddAbility(u, LeaveDetectAbilityID) //Add the leave detect ability to the entering unit.
call UnitMakeAbilityPermanent(u, true, LeaveDetectAbilityID) //Prevent it from disappearing on morph.
set dead[index] = IsUnitType(u, UNIT_TYPE_DEAD) //Reset all of the flags for the entering
set summoned[index] = IsUnitType(u, UNIT_TYPE_SUMMONED) //unit. These flags are necessary to detect
set animated[index] = false //when the unit leaves the map.
set nodecay[index] = false
set removing[index] = false
debug set altered[index] = false //In debug mode, this flag tracks wheter a unit's index was altered.
set idunit[index] = u //Attach the unit that is supposed to have this index to the index.
loop //Run the OnUnitIndexed events.
exitwhen n > indexfuncs_n
call indexfuncs[n].evaluate(u)
set n = n + 1
endloop
endmethod
private static method initPreplacedUnit takes nothing returns nothing
static if LIBRARY_xebasic then
if GetUnitTypeId(GetEnumUnit()) == XE_DUMMY_UNITID then
return //Don't index xe dummy units, and don't add
endif //them to the group of preplaced units.
endif
call GroupAddUnit(preplaced, GetEnumUnit()) //Assemble a group of all the preplaced units.
call unitEntersMap(GetEnumUnit()) //Initialize each preplaced unit.
return
endmethod
private static method initEnteringUnit takes nothing returns boolean
static if LIBRARY_xebasic then
if GetUnitTypeId(GetFilterUnit()) == XE_DUMMY_UNITID then
return false //Don't index xe dummy units, and don't add
endif //them to the group of preplaced units.
endif
if duringinit then
call GroupAddUnit(preplaced, GetFilterUnit())
//Add units that are created during initialization to the preplaced units group.
//This ensures that all units are noticed by OnUnitIndexed during initialization.
endif
call unitEntersMap(GetFilterUnit()) //Initialize each unit that enters the map.
return false
endmethod
//===========================================================================
private static method afterInit takes nothing returns nothing
set duringinit = false //Initialization is over; set a flag.
call DestroyTimer(GetExpiredTimer()) //Destroy the timer.
call GroupClear(preplaced) //The preplaced units group is
call DestroyGroup(preplaced) //no longer needed, so clean it.
set preplaced = null
endmethod
private static method onInit takes nothing returns nothing
local region maparea = CreateRegion()
local rect bounds = GetWorldBounds()
local group g = CreateGroup()
local integer i = 15
static if not UseUnitUserData then
set ht = InitHashtable() //Only create a hashtable if it will be used.
endif
loop
exitwhen i < 0
call SetPlayerAbilityAvailable(Player(i), LeaveDetectAbilityID, false)
//Make the LeaveDetect ability unavailable so that it doesn't show up on the command card of every unit.
call TriggerRegisterPlayerUnitEvent(status, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, function UnitFilter)
//Register the "EVENT_PLAYER_UNIT_ISSUED_ORDER" event to notice Undefend orders. Ignore filtered units.
call GroupEnumUnitsOfPlayer(g, Player(i), Condition(function UnitFilter))
call ForGroup(g, function AutoIndex.initPreplacedUnit)
//Enum every non-filtered unit on the map during initialization and assign it a unique
//index. By using GroupEnumUnitsOfPlayer, even units with Locust can be detected.
set i = i - 1
endloop
call TriggerAddCondition(status, And(function AutoIndex.isUndefendOrder, function AutoIndex.detectStatus))
//The detectStatus method will fire every time a non-filtered unit recieves an undefend order.
//And() is used here to avoid using a trigger action, which starts a new thread and is slower.
call TriggerRegisterPlayerUnitEvent(creepdeath, Player(12), EVENT_PLAYER_UNIT_DEATH, function UnitFilter)
call TriggerAddCondition(creepdeath, function AutoIndex.detectStatus)
//The detectStatus method must also fire when a neutral hostile creep dies, in case it was
//sleeping. Sleeping creeps don't fire undefend orders on non-damaging deaths.
call RegionAddRect(maparea, bounds) //GetWorldBounds() contains the entire map area, including the shaded boundry areas.
call TriggerRegisterEnterRegion(enter, maparea, And(function UnitFilter, function AutoIndex.initEnteringUnit))
//Only the filter function of an EnterRegion trigger runs instantly when a unit is created.
//Using And() lets both the UnitFilter and indexing function run when a unit enters the map.
call TimerStart(CreateTimer(), 0., false, function AutoIndex.afterInit)
//After any time elapses, perform after-initialization actions.
call GroupClear(g)
call DestroyGroup(g)
call RemoveRect(bounds)
set g = null
set bounds = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library ARGB initializer init
//******************************************************************************
//*
//* ARGB 1.2
//* ====
//* 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).
//*
//* structs that have a recolor method that takes red,green,blue and alpha as 0.255
//* integers can implement the ARGBrecolor module to gain an ability to quickly
//* recolor using an ARGB object.
//*
//********************************************************************************
//=================================================================================
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
// not really part of the exported stuff, I may remove it in the future, so please don't call this textmacro
//! textmacro ARGB_PLAYER_COLOR_2_ARGB
if(pc==PLAYER_COLOR_RED) then
return 0xFFFF0303
elseif(pc==PLAYER_COLOR_BLUE) then
return 0xFF0042FF
elseif(pc==PLAYER_COLOR_CYAN) then
return 0xFF1CE6B9
elseif(pc==PLAYER_COLOR_PURPLE) then
return 0xFF540081
elseif(pc==PLAYER_COLOR_YELLOW) then
return 0xFFFFFC01
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
//! endtextmacro
static method fromPlayerColor takes playercolor pc returns ARGB
//! runtextmacro ARGB_PLAYER_COLOR_2_ARGB()
endmethod
static method fromPlayer takes player p returns ARGB
local playercolor pc=GetPlayerColor(p)
//! runtextmacro ARGB_PLAYER_COLOR_2_ARGB()
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 alpha= takes integer na returns ARGB
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
return ARGB(b + g*0x100 + r*0x10000 + na*0x1000000)
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 red= takes integer nr returns ARGB
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
return ARGB(b + g*0x100 + nr*0x10000 + a*0x1000000)
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 green= takes integer ng returns ARGB
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
return ARGB(b + ng*0x100 + r*0x10000 + a*0x1000000)
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
method operator blue= takes integer nb returns ARGB
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
return ARGB(nb + g*0x100 + r*0x10000 + a*0x1000000)
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
module ARGBrecolor
method ARGBrecolor takes ARGB color 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 this.recolor(r, g , b, a)
endmethod
endmodule
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
// *************************************************************
// * ImageUtils
// * by Deaod
// *************************************************************
// *
// * CREDITS:
// * - Vexorian (JassHelper, ARGB)
// * - MindWorX and PitzerMike (JassNewGenPack)
// * - Pipedream (Grimoire)
// * - SFilip (TESH)
// *
// * HOW TO IMPORT:
// * * C'n'P the code into your map
// * * If you haven't done that already, import ARGB into your map
// *
// * HOW TO USE:
// * * this library provides you with wrappers for CreateImage and DestroyImage (NewImage and ReleaseImage respectively).
// * Those are necessary to work around creating invalid images. They also catch attempts to destroy images created by WC3 itself
// * (although thats rather conditional, you need to use NewImage and ReleaseImage correctly for it to work).
// * CreateImageEx also exists (for backwards compatibility), but is deprecated.
// *
// * This library also comes with an object oriented wrapper for images, heres how to use those:
// *
// * * declare a variable of type imagex
// *
// * * use imagex.create(string path, real sizeX, real sizeY, real posX, real posY, real posZ, boolean show) to create a new image
// * - path is the path to the imagefile that you want to display
// * - sizeX and sizeY are the dimensions of the image displayed in standard WC3 units of length
// * - posX, posY and posZ specifiy the position where the image is created.
// * Note that this point is the lower left corner of the image.
// *
// * * you can change the path of the image youre displaying by setting the path member of an instance of the imagex struct.
// * Example: set yourimage.path="Path\\To\\The\\Image.blp"
// *
// * * you can change the size of the image by setting the sizeX and sizeY member of an instance of the imagex struct.
// * Example: set yourimage.sizeX=64.
// * set yourimage.sizeY=64.
// * Theres also a method combining those two: yourimage.setSize(real sizex, real sizey)
// * Example: call yourimage.setSize(64., 64.)
// * Sizes work like describen in the create method.
// *
// * * you can change the position of the image by setting the X, Y and Z members of an instance of the imagex struct.
// * Example: set yourimage.X=128.
// * set yourimage.Y=128.
// * set yourimage.Z=0.
// * Theres also a method combining those three: yourimage.setPosition(real x, real y, real z)
// * Example: call yourimage.setPosition(128.,128.,0.)
// * The point specified is the lower left corner of the image.
// *
// * * you can access the individual values of the red, green, blue and alpha channels of the current color of the image
// * with the red, green, blue and alpha members of an instance of the imagex struct.
// * Example: set red = yourimage.red
// * set green = yourimage.green
// * set blue = yourimage.blue
// * set alpha = yourimage.alpha
// * I planned adding a way to change the value of the individual color channels,
// * but unfortunately i cant due to a limitation in JassHelper.
// *
// * * you can change the color of the image by setting the color member of an instance of the imagex struct.
// * Example: set yourimage.color=ARGB(0xFF808080)
// * Refer to ARGBs manual for more information on what is a valid ARGB instance.
// *
// * * you can decide whether to display the image or not by setting the show member of an instance of the imagex struct.
// * Example: set yourimage.show=true
// * true displays the image, false hides it.
// *
// * * you can make the image wrap to the ground by setting the wrap member of an instance of the imagex struct.
// * Example: set yourimage.wrap=true
// * true makes the image wrap to the ground, but makes the image ignore its Z position.
// * false allows you to change the Z position of the image freely.
// * Defaults to false for new instances.
// *
// * * you can change the type of an image by setting the type member of an instance of the imagex struct.
// * Example: set yourimage.type=IMAGE_TYPE_INDICATOR
// * A list of all known image types can be found below.
// * Note that not every image type known works, and that image types influence
// * the order in which images are stacked on top of each other.
// *
// * NOTE: although i have only shown examples for changing the value of members,
// * its also possible to read them, unless stated otherwise.
// *
// * * to destroy an image use yourimage.destroy()
// *
// *************************************************************
library ImageUtils requires ARGB
globals
private constant integer MAX_IMAGES = 8190
// Doesnt get rendered
// using this type in CreateImage returns an invalid image (id of -1)
constant integer IMAGE_TYPE_SHADOW = 0
// Gets drawn above fog of war
constant integer IMAGE_TYPE_SELECTION = 1
// Gets drawn above fog of war
constant integer IMAGE_TYPE_INDICATOR = 2
// Gets drawn above fog of war
constant integer IMAGE_TYPE_OCCLUSION_MASK = 3
// Gets tinted based on time of day ingame.
// Gets drawn below fog of war
constant integer IMAGE_TYPE_UBERSPLAT = 4
// Doesnt get rendered
constant integer IMAGE_TYPE_TOPMOST = 5
private constant integer DEFAULT_IMAGE_TYPE = IMAGE_TYPE_INDICATOR
private ARGB DEFAULT_COLOR = 0xFFFFFFFF
private constant integer INVALID_IMAGE_ID = -1 // go complain about that at Blizzard,
// i have nothing to do with that
endglobals
globals
private boolean array ImageValid[MAX_IMAGES]
endglobals
function NewImage takes string path, real sizex, real sizey, real sizez, real posx, real posy, real posz, real offx, real offy, real offz, integer imagetype returns image
local image i=CreateImage(path, sizex, sizey, sizez, posx, posy, posz, offx, offy, offz, imagetype)
local integer id=GetHandleId(i)
if id<0 then
debug call BJDebugMsg("NewImage: Invalid imagepath!")
return null
elseif id>=MAX_IMAGES then
debug call BJDebugMsg("NewImage: Exceeded Maximum Images!")
return i
endif
set ImageValid[id]=true
return i
endfunction
function CreateImageEx takes string path, real sizex, real sizey, real sizez, real posx, real posy, real posz, real offx, real offy, real offz, integer imagetype returns image
debug call BJDebugMsg("CreateImageEx: Use NewImage instead, CreateImageEx is deprecated!")
return NewImage(path, sizex, sizey, sizez, posx, posy, posz, offx, offy, offz, imagetype)
endfunction
function ReleaseImage takes image i returns nothing
local integer id=GetHandleId(i)
if id>=MAX_IMAGES then
call DestroyImage(i)
elseif id>0 and ImageValid[id] then
call DestroyImage(i)
set ImageValid[id]=false
debug elseif id>0 then
debug call BJDebugMsg("ReleaseImage: Double free of image "+I2S(id)+".")
debug else
debug call BJDebugMsg("ReleaseImage: Trying to free invalid image.")
endif
endfunction
struct imagex[MAX_IMAGES]
private image img
private string Path
private real SizeX
private real SizeY
private real X
private real Y
private real Z
private ARGB Color
private boolean Show
private boolean Wrap
private integer Type
// Get Methods
method operator path takes nothing returns string
return .Path
endmethod
method operator sizeX takes nothing returns real
return .SizeX
endmethod
method operator sizeY takes nothing returns real
return .SizeY
endmethod
method operator x takes nothing returns real
return .X
endmethod
method operator y takes nothing returns real
return .Y
endmethod
method operator z takes nothing returns real
return .Z
endmethod
method operator red takes nothing returns integer
return .Color.red
endmethod
method operator green takes nothing returns integer
return .Color.green
endmethod
method operator blue takes nothing returns integer
return .Color.blue
endmethod
method operator alpha takes nothing returns integer
return .Color.alpha
endmethod
method operator color takes nothing returns ARGB
return .Color
endmethod
method operator show takes nothing returns boolean
return .Show
endmethod
method operator wrap takes nothing returns boolean
return not .Wrap
endmethod
method operator type takes nothing returns integer
return .Type
endmethod
// Private Proxies
private method NewPosition takes nothing returns nothing
call SetImagePosition(.img, .x, .y, 0)
endmethod
private method NewZPos takes real z returns nothing
call SetImageConstantHeight(.img, .wrap, z)
endmethod
private method Recolor takes nothing returns nothing
call SetImageColor(.img, .red, .green, .blue, .alpha)
endmethod
private method Recreate takes nothing returns nothing
if .img!=null then
call ReleaseImage(.img) // never destroy null images, if you dont want hell unleashed
endif
set .img=NewImage(.path, .sizeX, .sizeY, 0, .x, .y, 0, 0, 0, 0, .type)
call .NewZPos(.z)
call .Recolor()
call SetImageRenderAlways(.img, .show)
endmethod
// Set Methods
// Set the image's filepath
method operator path= takes string path returns nothing
set .Path=path
call .Recreate()
endmethod
// Set the size of the image
method operator sizeX= takes real sizex returns nothing
set .SizeX=sizex
call .Recreate()
endmethod
method operator sizeY= takes real sizey returns nothing
set .SizeY=sizey
call .Recreate()
endmethod
method setSize takes real sizex, real sizey returns nothing
set .SizeX=sizex
set .SizeY=sizey
call .Recreate()
endmethod
// Set the position of the image
method operator x= takes real x returns nothing
set .X=x
call .NewPosition()
endmethod
method operator y= takes real y returns nothing
set .Y=y
call .NewPosition()
endmethod
method operator z= takes real z returns nothing
set .Z=z
call .NewZPos(z)
endmethod
method setPosition takes real x, real y, real z returns nothing
set .X=x
set .Y=y
set .Z=z
call .NewPosition()
call .NewZPos(z)
endmethod
// Set the color of the image // due to a limtation in JassHelper, only the operator color= works
/*method operator red= takes integer red returns nothing
set .Color.red=red
call .Recolor()
endmethod
method operator green= takes integer green returns nothing
set .Color.green=green
call .Recolor()
endmethod
method operator blue= takes integer blue returns nothing
set .Color.blue=blue
call .Recolor()
endmethod
method operator alpha= takes integer alpha returns nothing
set .Color.alpha=alpha
call .Recolor()
endmethod*/
method operator color= takes ARGB new returns nothing
set .Color=new
call .Recolor()
endmethod
// Do you want to display the image?
method operator show= takes boolean show returns nothing
set .Show=show
call SetImageRenderAlways(.img, .show)
endmethod
method operator wrap= takes boolean wrap returns nothing
set .Wrap=not wrap
call .NewZPos(.z)
endmethod
// On which layer should the image be rendered?
method operator type= takes integer imageType returns nothing
set .Type=imageType
call SetImageType(.img, imageType)
endmethod
// constructor and destructor
static method create takes string path, real sizeX, real sizeY, real posX, real posY, real posZ, boolean show returns thistype
local thistype s=.allocate()
set s.Path=path
set s.SizeX=sizeX
set s.SizeY=sizeY
set s.X=posX
set s.Y=posY
set s.Z=posZ
set s.Show=show
set s.Wrap=false
set s.Type=DEFAULT_IMAGE_TYPE
set s.Color=DEFAULT_COLOR
call s.Recreate()
return s
endmethod
method onDestroy takes nothing returns nothing
if .img!=null then
call ReleaseImage(.img)
endif
set .img=null
endmethod
private static method onInit takes nothing returns nothing
if GetHandleId(CreateImage("ReplaceableTextures\\CommandButtons\\BTNSlowOn.blp", 0, 0, 0, 0, 0, 0, 0, 0, 0, 1)) != null then
debug call BJDebugMsg("ImageUtils: image(null) already allocated, there might be errors")
endif
endmethod
endstruct
endlibrary