//TESH.scrollpos=0
//TESH.alwaysfold=0
function B2S takes boolean b returns string
if (b) then
return "true"
endif
return "false"
endfunction
Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope BasicExample initializer onInit
private function GameStart takes nothing returns nothing
local ProgressBar bar = ProgressBar.create()
set bar.zOffset = 150
set bar.color = PLAYER_COLOR_RED
set bar.targetUnit = CreateUnit(Player(0), 'hfoo', 0, 0, 0)
call bar.setPercent(30)
call ReleaseTimer(GetExpiredTimer())
endfunction
private function onInit takes nothing returns nothing
call TimerStart(NewTimer(), 0, false, function GameStart)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope ExampleLoop initializer onInit
globals
private ProgressBar pbar
private unit u
endglobals
private function doreset takes nothing returns nothing
local integer random = GetRandomInt(20, 100)
call BJDebugMsg(I2S(random) + "%")
set pbar.color = GetPlayerColor(Player(GetRandomInt(0, 12)))
call pbar.setPercentage(random, 1)
endfunction
private function onInit takes nothing returns nothing
set u = CreateUnit(Player(0), 'hfoo', 0, 0, 0)
set pbar = ProgressBar.create()
set pbar.xOffset = -15
set pbar.zOffset = 200
set pbar.size = 1
set pbar.color = GetPlayerColor(Player(GetRandomInt(0, 12)))
set pbar.targetUnit = u
call TimerStart(CreateTimer(), 2.5, true, function doreset)
endfunction
endscope
//TESH.scrollpos=58
//TESH.alwaysfold=0
scope HealthBar initializer onInit
private struct unitdata
ProgressBar hp
ProgressBar mp
unit u
timer t
endstruct
native UnitAlive takes unit id returns boolean
private function update takes nothing returns nothing
local timer t = GetExpiredTimer()
local unitdata d = GetTimerData(t)
local real life = GetUnitState(d.u, UNIT_STATE_LIFE)+0.405
local real percent
set percent = (life / GetUnitState(d.u, UNIT_STATE_MAX_LIFE) * 100.0)
if (not UnitAlive(d.u)) then
call ReleaseTimer(d.t)
call d.hp.setPercentage(0, 1)
call d.mp.setPercentage(0, 1)
call d.mp.destroy()
call d.hp.destroy()
call d.destroy()
return
elseif (percent <= 30) then
set d.hp.color = PLAYER_COLOR_RED
elseif (percent <= 50) then
set d.hp.color = PLAYER_COLOR_ORANGE
elseif (percent <= 60) then
set d.hp.color = PLAYER_COLOR_YELLOW
elseif (percent > 60) then
set d.hp.color = PLAYER_COLOR_GREEN
endif
call d.hp.setPercentage(percent, 1)
set life = GetUnitState(d.u, UNIT_STATE_MAX_MANA)
if (life > 0) then
set percent = GetUnitState(d.u, UNIT_STATE_MANA) / life * 100.0
call d.mp.setPercentage(percent, 1)
endif
endfunction
private function onEnum takes nothing returns boolean
local unit u = GetFilterUnit()
local unitdata d = unitdata.create()
local ProgressBar bar
local ProgressBar mana
set bar = ProgressBar.createEx('hpbr')
set bar.xOffset = -14.5
set bar.zOffset = 135
set bar.size = .7
set bar.color = PLAYER_COLOR_GREEN
set bar.targetUnit = u
call bar.setPercentage(100, 1)
set d.hp = bar
set d.t = NewTimerEx(d)
set d.u = u
if ( GetUnitState(d.u, UNIT_STATE_MAX_MANA) > 0 ) then
set mana = ProgressBar.createEx('mpbr')
set mana.xOffset = -14.5
set mana.zOffset = 110
set mana.size = .7
set mana.color = PLAYER_COLOR_BLUE
set mana.targetUnit = u
call mana.setPercentage(100, 1)
set d.mp = mana
endif
call TimerStart(d.t, 0.25, true, function update)
set u = null
return false
endfunction
private function gamestart takes nothing returns nothing
local group g = CreateGroup()
call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, Filter(function onEnum))
call DestroyGroup(g)
set g = null
call DestroyTimer(GetExpiredTimer())
endfunction
private function onInit takes nothing returns nothing
call EnablePreSelect(false, false) // hides default HP bars
call TimerStart(CreateTimer(), 0, false, function gamestart)
endfunction
endscope
//TESH.scrollpos=185
//TESH.alwaysfold=0
library ProgressBars requires TimerUtils optional BoundSentinel
/**************************************************************
*
* ProgressBars v2.0.1 by TriggerHappy
*
* This library allows you to easily create and modify progress bars.
* It works by creating a dummy unit with a special model and changing
* the animation speed to increase or reduce the bar speed. It is more than
* just a wrapper as it recycles each progress bar, meaning it will avoid
* costly CreateUnit calls whenever possible which also leak.
*
* Options:
* x - set X coordinate
* y - set Y coordinate
* xOffset - offset of the target unit, if any.
* yOffset - offset of the target unit, if any.
* zOffset - how high the bar is from the ground.
* color - allows you to tint the bar or add transparency
* targetUnit - pick which unit the bar should hover over
* size - set model scale
*
* Usage:
* local ProgressBar bar = ProgressBar.create()
* set bar.zOffset = 150
* set bar.color = PLAYER_COLOR_RED
* set bar.targetUnit = CreateUnit(Player(0), 'hfoo', 0, 0, 0)
* call bar.setPercentage(30)
*
* Installation:
* 1. Copy the dummy unit over to your map
* 2. Change the DUMMY constant to fit the Raw code of the dummy.
* 3. Copy this and all required libraries over to your map.
*
* Thanks to JesusHipster for the Progress Bar V2 model
* and to Vexorian for TimerUtils
*
**************************************************************/
globals
private constant integer DUMMY = 'pbar'
private constant player DUMMY_OWNER = Player(PLAYER_NEUTRAL_PASSIVE)
private constant real TIMER_PERIOD = 0.03 // the timer period used with .targetUnit
endglobals
struct ProgressBar
unit bar
unit target
real xOffset = 0
real yOffset = 0
timer timer
timer timer2
private boolean t_enabled = false
private real endVal
private real curVal=0
private real pspeed=0
private boolean reverse
private boolean done
readonly static unit array dummy
readonly static integer lastDummyIndex = -1
method operator x= takes real x returns nothing
call SetUnitX(this.bar, x)
endmethod
method operator x takes nothing returns real
return GetUnitX(this.bar)
endmethod
method operator y= takes real y returns nothing
call SetUnitY(this.bar, y)
endmethod
method operator y takes nothing returns real
return GetUnitY(this.bar)
endmethod
method operator zOffset= takes real offset returns nothing
call SetUnitFlyHeight(this.bar, offset, 0)
endmethod
method operator zOffset takes nothing returns real
return GetUnitFlyHeight(this.bar)
endmethod
method operator size= takes real size returns nothing
call SetUnitScale(this.bar, size, size, size)
endmethod
method operator color= takes playercolor color returns nothing
call SetUnitColor(this.bar, color)
endmethod
method show takes boolean flag returns nothing
call UnitRemoveAbility(this.bar, 'Aloc')
call ShowUnit(this.bar, flag)
call UnitAddAbility(this.bar, 'Aloc')
endmethod
method reset takes nothing returns nothing
call SetUnitAnimationByIndex(this.bar, 1)
endmethod
method RGB takes integer red, integer green, integer blue, integer alpha returns nothing
call SetUnitVertexColor(this.bar, red, green, blue, alpha)
endmethod
method destroy takes nothing returns nothing
set lastDummyIndex = lastDummyIndex + 1
set dummy[lastDummyIndex] = this.bar
call SetUnitAnimationByIndex(this.bar, 0)
call SetUnitTimeScale(this.bar, 1)
set this.bar = null
set this.target = null
set this.t_enabled = false
set this.endVal = 0
set this.curVal = 0
if (this.timer != null) then
call ReleaseTimer(this.timer)
endif
if (this.timer2 != null) then
call ReleaseTimer(this.timer2)
endif
endmethod
private static method updatePercentage takes nothing returns nothing
local timer expired = GetExpiredTimer()
local thistype this = GetTimerData(expired)
if (this.reverse) then
if (this.curVal > this.endVal) then
set this.curVal = (this.curVal - (this.pspeed))
call SetUnitTimeScale(this.bar, -this.pspeed)
elseif (this.curVal <= this.endVal) then
call SetUnitTimeScale(this.bar, 0)
set this.curVal = this.endVal
call PauseTimer(this.timer2)
set this.done=true
endif
else
if (this.curVal < this.endVal) then
set this.curVal = (this.curVal + (this.pspeed))
call SetUnitTimeScale(this.bar, this.pspeed)
elseif (this.curVal >= this.endVal) then
call SetUnitTimeScale(this.bar, 0)
set this.curVal = this.endVal
call PauseTimer(this.timer2)
set this.done=true
endif
endif
endmethod
private static method updatePosition takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
if (this.target != null) then
call SetUnitX(this.bar, GetUnitX(this.target) + xOffset)
call SetUnitY(this.bar, GetUnitY(this.target) + yOffset)
else
call ReleaseTimer(GetExpiredTimer())
endif
endmethod
private static method getDummy takes nothing returns unit
if (lastDummyIndex <= -1) then
return CreateUnit(DUMMY_OWNER, DUMMY, 0, 0, 270)
endif
call SetUnitAnimationByIndex(dummy[lastDummyIndex], 1)
set lastDummyIndex = lastDummyIndex - 1
return dummy[lastDummyIndex + 1]
endmethod
static method release takes integer count returns nothing
if (count > thistype.lastDummyIndex) then
set count = thistype.lastDummyIndex
endif
loop
exitwhen count <= 0
call RemoveUnit(dummy[count])
set dummy[count] = null
set count = count - 1
endloop
set thistype.lastDummyIndex = -1
endmethod
static method create takes integer unitId returns thistype
local thistype this = thistype.allocate()
set this.bar = thistype.getDummy()
set this.done = true
call SetUnitAnimationByIndex(this.bar, 1)
call SetUnitTimeScale(this.bar, 0)
return this
endmethod
method setPercentage takes real percent, real speed returns nothing
set this.endVal = R2I(percent)
set this.pspeed = speed
set this.reverse = (curVal > endVal)
if (this.done) then
if (this.timer2 == null) then
set this.timer2 = NewTimerEx(this)
endif
call TimerStart(this.timer2, 0.01, true, function thistype.updatePercentage)
set this.done=false
endif
endmethod
method operator targetUnit= takes unit u returns nothing
set this.target = u
if (u != null) then
if (this.timer == null) then
set this.timer = NewTimerEx(this)
endif
call TimerStart(this.timer, TIMER_PERIOD, true, function thistype.updatePosition)
call SetUnitX(this.bar, GetUnitX(this.target) - xOffset)
call SetUnitY(this.bar, GetUnitY(this.target) - yOffset)
set this.t_enabled = true
else
if (this.timer != null) then
call ReleaseTimer(this.timer)
endif
set this.t_enabled = false
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=91
//TESH.alwaysfold=0
library ProgressBars requires TimerUtils optional BoundSentinel
/**************************************************************
*
* ProgressBars v2.0.1 by TriggerHappy
*
* This library allows you to easily create and modify progress bars.
* It works by creating a dummy unit with a special model and changing
* the animation speed to increase or reduce the bar speed. It is more than
* just a wrapper as it recycles each progress bar, meaning it will avoid
* costly CreateUnit calls whenever possible which also leak.
*
* Options:
* x - set X coordinate
* y - set Y coordinate
* xOffset - offset of the target unit, if any.
* yOffset - offset of the target unit, if any.
* zOffset - how high the bar is from the ground.
* color - allows you to tint the bar or add transparency
* targetUnit - pick which unit the bar should hover over
* size - set model scale
*
* Usage:
* local ProgressBar bar = ProgressBar.create()
* set bar.zOffset = 150
* set bar.color = PLAYER_COLOR_RED
* set bar.targetUnit = CreateUnit(Player(0), 'hfoo', 0, 0, 0)
* call bar.setPercentage(30)
*
* Installation:
* 1. Copy the dummy unit over to your map
* 2. Change the DUMMY constant to fit the Raw code of the dummy.
* 3. Copy this and all required libraries over to your map.
*
* Thanks to JesusHipster for the Progress Bar models
* and to Vexorian for TimerUtils & BoundSentinel
*
**************************************************************/
globals
private constant integer PROGRESS_BAR_DUMMY = 'pbar' // the default one
private constant player PROGRESS_BAR_OWNER = Player(PLAYER_NEUTRAL_PASSIVE) // owner of the dummy
private constant real UPDATE_POSITION_PERIOD = 0.03 // the timer period used with .targetUnit
endglobals
struct ProgressBar
unit bar
unit target
real xOffset = 0
real yOffset = 0
timer timer
timer timer2
private boolean t_enabled = false
private real endVal
private real curVal=0
private real pspeed=0
private boolean reverse
private boolean done
private boolean recycle
readonly static unit array dummy
readonly static integer lastDummyIndex = -1
method operator x= takes real x returns nothing
call SetUnitX(this.bar, x)
endmethod
method operator x takes nothing returns real
return GetUnitX(this.bar)
endmethod
method operator y= takes real y returns nothing
call SetUnitY(this.bar, y)
endmethod
method operator y takes nothing returns real
return GetUnitY(this.bar)
endmethod
method operator zOffset= takes real offset returns nothing
call SetUnitFlyHeight(this.bar, offset, 0)
endmethod
method operator zOffset takes nothing returns real
return GetUnitFlyHeight(this.bar)
endmethod
method operator size= takes real size returns nothing
call SetUnitScale(this.bar, size, size, size)
endmethod
method operator color= takes playercolor color returns nothing
call SetUnitColor(this.bar, color)
endmethod
method show takes boolean flag returns nothing
call UnitRemoveAbility(this.bar, 'Aloc')
call ShowUnit(this.bar, flag)
call UnitAddAbility(this.bar, 'Aloc')
endmethod
method reset takes nothing returns nothing
call SetUnitAnimationByIndex(this.bar, 1)
endmethod
method RGB takes integer red, integer green, integer blue, integer alpha returns nothing
call SetUnitVertexColor(this.bar, red, green, blue, alpha)
endmethod
method destroy takes nothing returns nothing
if (recycle) then
set lastDummyIndex = lastDummyIndex + 1
set dummy[lastDummyIndex] = this.bar
call SetUnitAnimationByIndex(this.bar, 0)
call SetUnitTimeScale(this.bar, 1)
endif
set this.bar = null
set this.target = null
set this.t_enabled = false
set this.endVal = 0
set this.curVal = 0
if (this.timer != null) then
call ReleaseTimer(this.timer)
set this.timer = null
endif
if (this.timer2 != null) then
call ReleaseTimer(this.timer2)
set this.timer2 = null
endif
endmethod
private static method updatePercentage takes nothing returns nothing
local timer expired = GetExpiredTimer()
local thistype this = GetTimerData(expired)
if (this.reverse) then
if (this.curVal > this.endVal) then
call SetUnitTimeScale(this.bar, -this.pspeed)
set this.curVal = (this.curVal - (this.pspeed))
elseif (this.curVal <= this.endVal) then
call PauseTimer(this.timer2)
call SetUnitTimeScale(this.bar, 0)
set this.curVal = this.endVal
set this.done = true
endif
else
if (this.curVal < this.endVal) then
call SetUnitTimeScale(this.bar, this.pspeed)
set this.curVal = (this.curVal + (this.pspeed))
elseif (this.curVal >= this.endVal) then
call PauseTimer(this.timer2)
call SetUnitTimeScale(this.bar, 0)
set this.curVal = this.endVal
set this.done = true
endif
endif
endmethod
private static method updatePosition takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
if (this.target != null) then
call SetUnitX(this.bar, GetUnitX(this.target) + xOffset)
call SetUnitY(this.bar, GetUnitY(this.target) + yOffset)
else
call ReleaseTimer(GetExpiredTimer())
endif
endmethod
private static method getDummy takes nothing returns unit
if (lastDummyIndex <= -1) then
set bj_lastCreatedUnit = CreateUnit(PROGRESS_BAR_OWNER, PROGRESS_BAR_DUMMY, 0, 0, 270)
call PauseUnit(bj_lastCreatedUnit, true)
return bj_lastCreatedUnit
endif
call SetUnitAnimationByIndex(dummy[lastDummyIndex], 1)
set lastDummyIndex = lastDummyIndex - 1
return dummy[lastDummyIndex + 1]
endmethod
static method release takes integer count returns nothing
if (count > thistype.lastDummyIndex) then
set count = thistype.lastDummyIndex
endif
loop
exitwhen count <= 0
call RemoveUnit(dummy[count])
set dummy[count] = null
set count = count - 1
endloop
set thistype.lastDummyIndex = -1
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set this.bar = thistype.getDummy()
set this.done = true
set this.recycle = true
call SetUnitAnimationByIndex(this.bar, 1)
call SetUnitTimeScale(this.bar, 0)
return this
endmethod
static method createEx takes integer unitId returns thistype
local thistype this = thistype.allocate()
set this.bar = CreateUnit(PROGRESS_BAR_OWNER, unitId, 0, 0, 0)
set this.done = true
set this.recycle = false
call SetUnitAnimationByIndex(this.bar, 1)
call SetUnitTimeScale(this.bar, 0)
return this
endmethod
method setPercentage takes real percent, real speed returns nothing
set this.endVal = R2I(percent)
set this.pspeed = speed
set this.reverse = (curVal > endVal)
if (this.done) then
if (this.timer2 == null) then
set this.timer2 = NewTimerEx(this)
endif
call TimerStart(this.timer2, 0.01, true, function thistype.updatePercentage)
set this.done=false
endif
endmethod
method operator targetUnit= takes unit u returns nothing
set this.target = u
if (u != null) then
if (this.timer == null) then
set this.timer = NewTimerEx(this)
endif
call TimerStart(this.timer, UPDATE_POSITION_PERIOD, true, function thistype.updatePosition)
call SetUnitX(this.bar, GetUnitX(this.target) - xOffset)
call SetUnitY(this.bar, GetUnitY(this.target) - yOffset)
set this.t_enabled = true
else
if (this.timer != null) then
call ReleaseTimer(this.timer)
endif
set this.t_enabled = false
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=170
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+) 2.0
//* ----------
//*
//* 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.wc3c.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* set t=NewTimerEx(x) : Get a timer (alternative to CreateTimer), call
//* Initialize timer data as x, instead of 0.
//*
//* 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.
//*
//* Multi-flavor:
//* Set USE_HASH_TABLE to true if you don't want to complicate your life.
//*
//* If you like speed and giberish try learning about the other flavors.
//*
//********************************************************************
//================================================================
globals
//How to tweak timer utils:
// USE_HASH_TABLE = true (new blue)
// * SAFEST
// * SLOWEST (though hash tables are kind of fast)
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true (orange)
// * kinda safe (except there is a limit in the number of timers)
// * ALMOST FAST
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
// * THE FASTEST (though is only faster than the previous method
// after using the optimizer on the map)
// * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
// work)
//
private constant boolean USE_HASH_TABLE = true
private constant boolean USE_FLEXIBLE_OFFSET = false
private constant integer OFFSET = 0x100000
private integer VOFFSET = OFFSET
//Timers to preload at map init:
private constant integer QUANTITY = 256
//Changing this to something big will allow you to keep recycling
// timers even when there are already AN INCREDIBLE AMOUNT of timers in
// the stack. But it will make things far slower so that's probably a bad idea...
private constant integer ARRAY_SIZE = 8190
endglobals
//==================================================================================================
globals
private integer array data[ARRAY_SIZE]
private hashtable ht
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
static if(USE_HASH_TABLE) then
// new blue
call SaveInteger(ht,0,GetHandleId(t), value)
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-VOFFSET]=value
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-OFFSET]=value
endif
endfunction
function GetTimerData takes timer t returns integer
static if(USE_HASH_TABLE) then
// new blue
return LoadInteger(ht,0,GetHandleId(t) )
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-VOFFSET]
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-OFFSET]
endif
endfunction
//==========================================================================================
globals
private timer array tT[ARRAY_SIZE]
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
private boolean didinit = false
endglobals
private keyword init
//==========================================================================================
// I needed to decide between duplicating code ignoring the "Once and only once" rule
// and using the ugly textmacros. I guess textmacros won.
//
//! textmacro TIMERUTIS_PRIVATE_NewTimerCommon takes VALUE
// On second thought, no.
//! endtextmacro
function NewTimerEx takes integer value returns timer
if (tN==0) then
if (not didinit) then
//This extra if shouldn't represent a major performance drawback
//because QUANTITY rule is not supposed to be broken every day.
call init.evaluate()
set tN = tN - 1
else
//If this happens then the QUANTITY rule has already been broken, try to fix the
// issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
set tT[0]=CreateTimer()
static if( not USE_HASH_TABLE) then
debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
static if( USE_FLEXIBLE_OFFSET) then
if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
else
if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
endif
endif
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],value)
return tT[tN]
endfunction
function NewTimer takes nothing returns timer
return NewTimerEx(0)
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==ARRAY_SIZE) 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
local integer i=0
local integer o=-1
local boolean oops = false
if ( didinit ) then
return
else
set didinit = true
endif
static if( USE_HASH_TABLE ) then
set ht = InitHashtable()
loop
exitwhen(i==QUANTITY)
set tT[i]=CreateTimer()
call SetTimerData(tT[i], HELD)
set i=i+1
endloop
set tN = QUANTITY
else
loop
set i=0
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set VOFFSET = GetHandleId(tT[i])
static if(USE_FLEXIBLE_OFFSET) then
set o=VOFFSET
else
set o=OFFSET
endif
endif
if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
exitwhen true
endif
if (GetHandleId(tT[i])-o>=0) then
set i=i+1
endif
endloop
set tN = i
exitwhen(tN == QUANTITY)
set oops = true
exitwhen not USE_FLEXIBLE_OFFSET
debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")
endloop
if(oops) then
static if ( USE_FLEXIBLE_OFFSET) then
debug call BJDebugMsg("The problem has been fixed.")
//If this message doesn't appear then there is so much
//handle id fragmentation that it was impossible to preload
//so many timers and the thread crashed! Therefore this
//debug message is useful.
elseif(DEBUG_MODE) then
call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
endif
endif
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library BoundSentinel initializer init
//*************************************************
//* BoundSentinel
//* -------------
//* Don't leave your units unsupervised, naughty
//* them may try to get out of the map bounds and
//* crash your game.
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//*************************************************
//==================================================
globals
// High enough so the unit is no longer visible, low enough so the
// game doesn't crash...
//
// I think you need 0.0 or soemthing negative prior to patch 1.22
//
private constant real EXTRA = 500.0
endglobals
//=========================================================================================
globals
private real maxx
private real maxy
private real minx
private real miny
endglobals
//=======================================================================
private function dis takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
endfunction
private function init takes nothing returns nothing
local trigger t=CreateTrigger()
local region r=CreateRegion()
local rect rc
set minx=GetCameraBoundMinX() - EXTRA
set miny=GetCameraBoundMinY() - EXTRA
set maxx=GetCameraBoundMaxX() + EXTRA
set maxy=GetCameraBoundMaxY() + EXTRA
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddAction(t, function dis)
//this is not necessary but I'll do it anyway:
set t=null
set r=null
set rc=null
endfunction
endlibrary