//TESH.scrollpos=0
//TESH.alwaysfold=0
native UnitAlive takes unit id returns boolean
Name | Type | is_array | initial_value |
HERO | unit | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DemoMapTemplate initializer Init needs TimerUtils, GroupUtils
//*==========================================================================
//* Demo Map Template v1.01
//* by: emjlr3
//*
//* Should you want to port my triggers to your own terrain/map, keep reading.
//* Otherwise, feel free to ignore this trigger.
//*
//* Simply copy and paste the contents of this trigger to your Demo Map, or copy the trigger itself.
//* Your choice. Either way works.
//* This library requires the following libraries:
//* TimerUtils by Vexorian (http://www.wc3c.net/showthread.php?t=101322)
//* GroupUtils by Rising_Dusk (http://www.wc3c.net/showthread.php?t=104464)
//*
//* Configure the following options (just as you would have in the individual triggers in this map).
//* Save, test and enjoy!
//*==========================================================================
// ==CONFIGURABLE GLOBALS:
globals
// Creep Revival
// Minimum time in seconds before creeps will respawn
private constant real CTIME = 30.
// Effect created on creeps when revived, set to "" for no effect
private constant string CSFX = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
// Revive creeps only when enemies aren't nearby? 700 range
private constant boolean CHECK = true
// Creeps can drop items on death? 33% chance, @ creep level
private constant boolean ITEMS = true
// Creeps gradually increase in level? 25% chance
private constant boolean LEVEL = true
// Clean up old, unpicked items?
private constant boolean CLEAN = true
// Hero Restore
// Allow hero restore?
private constant boolean RESTORE = true
// Effect created on restored units, set to "" for no effect
private constant string HSFX = "Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl"
// Number of times Restore must be used before GodMode is enabled, set to 0 for infinite
private constant integer COUNT = 5
// Hero Revival
// Time in seconds to wait before reviving the hero
private constant real RTIME = 5.
// Initialization
// Text to display when the map starts
private constant string TEXT = "Press 'Esc.' to refresh your hero."
// Time in seconds to display TEXT
private constant real TTEXT = 30.
// Sphere
// Do time of day dependant sphere updates?
private constant boolean SPHERE = true
// Day sphere ability
private constant integer DAY = 'A000'
// Night sphere ability
private constant integer NIGHT = 'A001'
// Tree Respawn
// Do tree respawn?
private constant boolean TREE = true
// Time in seconds before trees will respawn
private constant real TTIME = 45.
// Weather
// Do custom weather effects?
private constant boolean WEATHER = true
// Time in seconds between random weather effects
private constant real WTIME = 35.
// System Required - NO TOUCHING!
// Hero Restore
private group g=CreateGroup()
private unit u=null
private integer c=0
// Hero Revival
private real x=GetStartLocationX(0)
private real y=GetStartLocationY(0)
// Initialization
unit HERO=null
hashtable HT=InitHashtable()
// Tree Respawn
private trigger treetrig=null
// Weather
private integer array effects
private integer count=0
private weathereffect we
endglobals
// ==CONFIGURABLE FUNCTIONS:
// Initialization
// Global variable name of the hero used for testing
private function GetHero takes nothing returns unit
return gg_unit_Hblm_0000
endfunction
// Weather
// Setup random weather data
private function SetUpWeather takes nothing returns nothing
// Effect rawcodes, these should start at 1
set effects[1]='RAhr'
set effects[2]='RAlr'
set effects[3]='FDwh'
set effects[4]='FDwl'
set effects[5]='WOlw'
set effects[6]='RLlr'
// The total number of random weather effects
set count=6
endfunction
// ==NO TOUCHING PAST THIS POINT!!!
native UnitAlive takes unit id returns boolean
// Creep Revival
private function FiltCreep takes nothing returns boolean
return IsUnitType(GetFilterUnit(),UNIT_TYPE_SUMMONED)==false
endfunction
private function EnemyOfCreeps takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),Player(12)) and UnitAlive(GetFilterUnit()) then
set bj_forceCountPlayers=bj_forceCountPlayers+1
endif
return false
endfunction
private function ReviveCreep takes nothing returns nothing
local unit u=GetTriggerUnit()
local integer id=GetHandleId(u)
local integer lvl=GetUnitLevel(u)+GetRandomInt(0,1)*GetRandomInt(0,1) // 25%
local location l=LoadLocationHandle(HT,id,0)
local real r=LoadReal(HT,id,0)
local group g
local item it=null
// spawn items
static if ITEMS then
if GetRandomReal(0.,1.)<=.33 then // 33%
set it=CreateItem(ChooseRandomItemEx(ITEM_TYPE_PERMANENT,GetUnitLevel(u)),GetUnitX(u),GetUnitY(u))
endif
endif
call FlushChildHashtable(HT,id)
call TriggerSleepAction(CTIME)
// respawn creep once enemies aren't about
static if CHECK then
set g=NewGroup()
loop
set bj_forceCountPlayers=0
call GroupEnumUnitsInRangeOfLoc(g,l,700.,Condition(function EnemyOfCreeps))
exitwhen bj_forceCountPlayers==0
call TriggerSleepAction(0.) // as fast as possible absent of timer use
endloop
call ReleaseGroup(g)
endif
// spawn creep
static if LEVEL then
if lvl>GetUnitLevel(u) then
set u=CreateUnitAtLoc(Player(12),ChooseRandomCreep(IMinBJ(lvl,10)),l,r)
else
set u=CreateUnitAtLoc(Player(12),GetUnitTypeId(u),l,r)
endif
else
set u=CreateUnitAtLoc(Player(12),GetUnitTypeId(u),l,r)
endif
call DestroyEffect(AddSpecialEffectTarget(CSFX,u,"origin"))
set id=GetHandleId(u)
call SaveLocationHandle(HT,id,0,l)
call SaveReal(HT,id,0,r)
// clean item
static if CLEAN then
if it!=null then
if not IsItemOwned(it) then
call SetWidgetLife(it,0.)
endif
set it=null
endif
endif
set l=null
set u=null
endfunction
private function RegisterCreep takes nothing returns boolean
local unit u=GetFilterUnit()
local integer id=GetHandleId(u)
call SaveLocationHandle(HT,id,0,GetUnitLoc(u))
call SaveReal(HT,id,0,GetUnitFacing(u))
set u=null
return false
endfunction
// Hero Restore
private function RestoreHealth takes nothing returns nothing
call ReleaseTimer(GetExpiredTimer())
if UnitAlive(HERO) then
call SetWidgetLife(HERO,99999.)
call UnitRemoveBuffs(HERO,false,true)
endif
endfunction
private function RestoreMana takes nothing returns nothing
call ReleaseTimer(GetExpiredTimer())
call SetUnitState(HERO,UNIT_STATE_MANA,99999.)
endfunction
private function GodMode takes nothing returns boolean
if GetTriggerEventId()==EVENT_UNIT_DAMAGED then
if GetEventDamage()>.1 then
call TimerStart(NewTimer(),0.,false,function RestoreHealth)
endif
elseif GetTriggerEventId()==EVENT_UNIT_SPELL_EFFECT then
call TimerStart(NewTimer(),0.,false,function RestoreMana)
else
call UnitResetCooldown(HERO)
endif
return false
endfunction
private function RestoreHeroChild takes nothing returns boolean
if UnitAlive(GetFilterUnit()) then
set u=GetFilterUnit()
call SetWidgetLife(u,99999.)
call SetUnitState(u,UNIT_STATE_MANA,99999.)
call UnitResetCooldown(u)
call UnitRemoveBuffs(u,false,true)
call DestroyEffect(AddSpecialEffectTarget(HSFX,u,"origin"))
endif
return false
endfunction
private function RestoreHero takes nothing returns nothing
local trigger t
call GroupEnumUnitsOfPlayer(g,Player(0),Condition(function RestoreHeroChild))
set c=c+1
if c==COUNT then
call DisplayTimedTextToPlayer(Player(0),0.,0.,bj_TEXT_DELAY_SECRET," ")
call DisplayTimedTextToPlayer(Player(0),0.,0.,bj_TEXT_DELAY_SECRET,"|c0000FF00GOD MODE|r")
call StartSound(bj_questSecretSound)
set t=CreateTrigger()
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_DAMAGED)
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_SPELL_ENDCAST)
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function GodMode))
endif
endfunction
// Hero Revival
private function HeroReviveChild takes nothing returns nothing
local integer id=GetHandleId(GetExpiredTimer())
call ReviveHero(HERO,x,y,true)
call ClearSelection()
call SelectUnit(HERO,true)
call SetCameraPosition(x,y)
call DestroyTimerDialog(LoadTimerDialogHandle(HT,id,0))
call ReleaseTimer(GetExpiredTimer())
call FlushChildHashtable(HT,id)
endfunction
private function HeroRevive takes nothing returns nothing
local timer t=NewTimer()
local timerdialog td=CreateTimerDialog(t)
call TimerStart(t,RTIME,false,function HeroReviveChild)
call TimerDialogDisplay(td,true)
call TimerDialogSetTitle(td,GetHeroProperName(HERO))
call SaveTimerDialogHandle(HT,GetHandleId(t),0,td)
set t=null
set td=null
endfunction
private function InitHeroRevive takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_DEATH)
call TriggerAddAction(t,function HeroRevive)
call ReleaseTimer(GetExpiredTimer())
endfunction
// Sphere
private function ChangeSphere takes nothing returns nothing
if GetFloatGameState(GAME_STATE_TIME_OF_DAY)==6. then
call UnitRemoveAbility(HERO,NIGHT)
call UnitAddAbility(HERO,DAY)
else
call UnitRemoveAbility(HERO,DAY)
call UnitAddAbility(HERO,NIGHT)
endif
endfunction
private function InitSphere takes nothing returns nothing
call ReleaseTimer(GetExpiredTimer())
if GetFloatGameState(GAME_STATE_TIME_OF_DAY)>=6. and GetFloatGameState(GAME_STATE_TIME_OF_DAY)<18. then
call UnitAddAbility(HERO,DAY)
else
call UnitAddAbility(HERO,NIGHT)
endif
endfunction
// Tree Respawn
private function RespawnTree takes nothing returns nothing
call TriggerSleepAction(TTIME)
call DestructableRestoreLife(GetTriggerDestructable(),GetDestructableMaxLife(GetTriggerDestructable()),true)
endfunction
private function RegisterTree takes nothing returns boolean
call TriggerRegisterDeathEvent(treetrig,GetFilterDestructable())
return false
endfunction
// Weather
private function CreateWeather takes nothing returns nothing
local integer i=GetRandomInt(0,count)
call EnableWeatherEffect(we,false)
call RemoveWeatherEffect(we)
if i>0 then
set we=AddWeatherEffect(GetWorldBounds(),effects[i])
call EnableWeatherEffect(we,true)
endif
endfunction
// ==================================================================
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
local group g=NewGroup()
local integer i=1
// Creep Revival
call TriggerRegisterPlayerUnitEvent(t,Player(12),EVENT_PLAYER_UNIT_DEATH,null)
call TriggerAddCondition(t,Condition(function FiltCreep))
call TriggerAddAction(t,function ReviveCreep)
call GroupEnumUnitsOfPlayer(g,Player(12),Condition(function RegisterCreep))
call ReleaseGroup(g)
call Preload(CSFX)
// Hero Restore
static if RESTORE then
set t=CreateTrigger()
call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(t,function RestoreHero)
call Preload(HSFX)
endif
// Hero Revival
call TimerStart(NewTimer(),0.,false,function InitHeroRevive)
// Initialization
call FogEnable(false)
call SuspendTimeOfDay(false)
call SetSkyModel("Environment\\Sky\\Sky\\SkyLight.mdl")
call DisplayTimedTextToPlayer(Player(0),0.,0.,TTEXT,TEXT)
call DisplayTimedTextToPlayer(Player(0),0.,0.,TTEXT,"|c0000FF00Demo Map Template by emjlr3.|r")
set HERO=GetHero()
set udg_HERO=HERO
call SelectUnit(HERO,true)
call QueueUnitAnimation(HERO,"stand")
// Sphere
static if SPHERE then
set t=CreateTrigger()
call TriggerRegisterGameStateEvent(t,GAME_STATE_TIME_OF_DAY,EQUAL,6.)
call TriggerRegisterGameStateEvent(t,GAME_STATE_TIME_OF_DAY,EQUAL,18.)
call TriggerAddAction(t,function ChangeSphere)
call TimerStart(NewTimer(),0.,false,function InitSphere)
set bj_lastCreatedUnit=CreateUnit(Player(15),'hfoo',0.,0.,0.)
call ShowUnit(bj_lastCreatedUnit,false)
call UnitAddAbility(bj_lastCreatedUnit,DAY)
call UnitAddAbility(bj_lastCreatedUnit,NIGHT)
call UnitApplyTimedLife(bj_lastCreatedUnit,'BTLF',.001)
endif
// Tree Respawn
static if TREE then
set treetrig=CreateTrigger()
call EnumDestructablesInRect(GetWorldBounds(),Condition(function RegisterTree),null)
call TriggerAddAction(treetrig,function RespawnTree)
endif
// Weather
static if WEATHER then
call SetUpWeather()
loop
exitwhen i>count
set we=AddWeatherEffect(GetWorldBounds(),effects[i])
call RemoveWeatherEffect(we)
set i=i+1
endloop
call TimerStart(CreateTimer(),WTIME,true,function CreateWeather)
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope CreepRevival initializer Init
globals
// Configurables:
// Minimum time in seconds before creeps will respawn
private constant real TIME = 30.
// Effect created on creeps when revived, set to "" for no effect
private constant string SFX = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl"
// Revive creeps only when enemies aren't nearby? 600 range
private constant boolean CHECK = true
// Creeps can drop items on death? 33% chance, @ creep level
private constant boolean ITEMS = true
// Creeps gradually increase in level? 25% chance
private constant boolean LEVEL = true
// Clean up old, unpicked items?
private constant boolean CLEAN = true
endglobals
private function Filt takes nothing returns boolean
return IsUnitType(GetFilterUnit(),UNIT_TYPE_SUMMONED)==false
endfunction
private function EnemyOfCreeps takes nothing returns boolean
if IsUnitEnemy(GetFilterUnit(),Player(12)) and UnitAlive(GetFilterUnit()) then
set bj_forceCountPlayers=bj_forceCountPlayers+1
endif
return false
endfunction
private function Revive takes nothing returns nothing
local unit u=GetTriggerUnit()
local integer id=GetHandleId(u)
local integer lvl=GetUnitLevel(u)+GetRandomInt(0,1)*GetRandomInt(0,1) // 25%
local location l=LoadLocationHandle(HT,id,0)
local real r=LoadReal(HT,id,0)
local group g
local item it=null
// spawn items
static if ITEMS then
if GetRandomReal(0.,1.)<=.33 then // 33%
set it=CreateItem(ChooseRandomItemEx(ITEM_TYPE_PERMANENT,GetUnitLevel(u)),GetUnitX(u),GetUnitY(u))
endif
endif
call FlushChildHashtable(HT,id)
call TriggerSleepAction(TIME)
// respawn creep once enemies aren't about
static if CHECK then
set g=NewGroup()
loop
set bj_forceCountPlayers=0
call GroupEnumUnitsInRangeOfLoc(g,l,600.,Condition(function EnemyOfCreeps))
exitwhen bj_forceCountPlayers==0
call TriggerSleepAction(0.) // as fast as possible absent of timer use
endloop
call ReleaseGroup(g)
endif
// spawn creep
static if LEVEL then
if lvl>GetUnitLevel(u) then
set u=CreateUnitAtLoc(Player(12),ChooseRandomCreep(IMinBJ(lvl,10)),l,r)
else
set u=CreateUnitAtLoc(Player(12),GetUnitTypeId(u),l,r)
endif
else
set u=CreateUnitAtLoc(Player(12),GetUnitTypeId(u),l,r)
endif
call DestroyEffect(AddSpecialEffectTarget(SFX,u,"origin"))
set id=GetHandleId(u)
call SaveLocationHandle(HT,id,0,l)
call SaveReal(HT,id,0,r)
// clean item
static if CLEAN then
if it!=null then
if not IsItemOwned(it) then
call SetWidgetLife(it,0.)
endif
set it=null
endif
endif
set l=null
set u=null
endfunction
private function Register takes nothing returns boolean
local unit u=GetFilterUnit()
local integer id=GetHandleId(u)
call SaveLocationHandle(HT,id,0,GetUnitLoc(u))
call SaveReal(HT,id,0,GetUnitFacing(u))
set u=null
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
local group g=NewGroup()
call TriggerRegisterPlayerUnitEvent(t,Player(12),EVENT_PLAYER_UNIT_DEATH,null)
call TriggerAddCondition(t,Condition(function Filt))
call TriggerAddAction(t,function Revive)
call GroupEnumUnitsOfPlayer(g,Player(12),Condition(function Register))
call ReleaseGroup(g)
call Preload(SFX)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope HeroRestore initializer Init
globals
// Configurables:
// Effect created on restored units, set to "" for no effect
private constant string SFX = "Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl"
// Number of times Restore must be used before GodMode is enabled, set to 0 for infinite
private constant integer COUNT = 5
// Required
private group g=CreateGroup()
private unit u=null
private integer c=0
endglobals
private function RestoreHealth takes nothing returns nothing
call ReleaseTimer(GetExpiredTimer())
if UnitAlive(HERO) then
call SetWidgetLife(HERO,99999.)
call UnitRemoveBuffs(HERO,false,true)
endif
endfunction
private function RestoreMana takes nothing returns nothing
call ReleaseTimer(GetExpiredTimer())
call SetUnitState(HERO,UNIT_STATE_MANA,99999.)
endfunction
private function GodMode takes nothing returns boolean
if GetTriggerEventId()==EVENT_UNIT_DAMAGED then
if GetEventDamage()>.1 then
call TimerStart(NewTimer(),0.,false,function RestoreHealth)
endif
elseif GetTriggerEventId()==EVENT_UNIT_SPELL_EFFECT then
call TimerStart(NewTimer(),0.,false,function RestoreMana)
else
call UnitResetCooldown(HERO)
endif
return false
endfunction
private function RestoreChild takes nothing returns boolean
if UnitAlive(GetFilterUnit()) then
set u=GetFilterUnit()
call SetWidgetLife(u,99999.)
call SetUnitState(u,UNIT_STATE_MANA,99999.)
call UnitResetCooldown(u)
call UnitRemoveBuffs(u,false,true)
call DestroyEffect(AddSpecialEffectTarget(SFX,u,"origin"))
endif
return false
endfunction
private function Restore takes nothing returns nothing
local trigger t
call GroupEnumUnitsOfPlayer(g,Player(0),Condition(function RestoreChild))
set c=c+1
if c==COUNT then
call DisplayTimedTextToPlayer(Player(0),0.,0.,bj_TEXT_DELAY_SECRET," ")
call DisplayTimedTextToPlayer(Player(0),0.,0.,bj_TEXT_DELAY_SECRET,"|c0000FF00GOD MODE|r")
call StartSound(bj_questSecretSound)
set t=CreateTrigger()
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_DAMAGED)
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_SPELL_ENDCAST)
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function GodMode))
endif
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
call TriggerAddAction(t,function Restore)
call Preload(SFX)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope HeroRevival initializer Init
globals
// Configurables:
// Time in seconds to wait before reviving the hero
private constant real TIME = 5.
// Required
private real x=GetStartLocationX(0)
private real y=GetStartLocationY(0)
endglobals
private function ReviveChild takes nothing returns nothing
local integer id=GetHandleId(GetExpiredTimer())
call ReviveHero(HERO,x,y,true)
call ClearSelection()
call SelectUnit(HERO,true)
call SetCameraPosition(x,y)
call DestroyTimerDialog(LoadTimerDialogHandle(HT,id,0))
call ReleaseTimer(GetExpiredTimer())
call FlushChildHashtable(HT,id)
endfunction
private function Revive takes nothing returns nothing
local timer t=NewTimer()
local timerdialog td=CreateTimerDialog(t)
call TimerStart(t,TIME,false,function ReviveChild)
call TimerDialogDisplay(td,true)
call TimerDialogSetTitle(td,GetHeroProperName(HERO))
call SaveTimerDialogHandle(HT,GetHandleId(t),0,td)
set t=null
set td=null
endfunction
private function InitChild takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterUnitEvent(t,HERO,EVENT_UNIT_DEATH)
call TriggerAddAction(t,function Revive)
call ReleaseTimer(GetExpiredTimer())
endfunction
private function Init takes nothing returns nothing
call TimerStart(NewTimer(),0.,false,function InitChild)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Initialization initializer Init
globals
// Configurables:
// Text to display when the map starts
private constant string TEXT = "Press 'Esc.' to refresh your hero."
// Time in seconds to display TEXT
private constant real TTEXT = 30.
// Required
unit HERO=null
hashtable HT=InitHashtable()
endglobals
// Global variable name of the hero used for testing
private function Hero takes nothing returns unit
return gg_unit_Hblm_0000
endfunction
private function Init takes nothing returns nothing
call FogEnable(false)
call SuspendTimeOfDay(false)
call SetSkyModel("Environment\\Sky\\Sky\\SkyLight.mdl")
call DisplayTimedTextToPlayer(Player(0),0.,0.,TTEXT,TEXT)
call DisplayTimedTextToPlayer(Player(0),0.,0.,TTEXT,"|c0000FF00Demo Map Template by emjlr3.|r")
set HERO=Hero()
set udg_HERO=HERO
call SelectUnit(HERO,true)
call QueueUnitAnimation(HERO,"stand")
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Sphere initializer Init
globals
// Configurables:
// Day sphere ability
private constant integer DAY = 'A000'
// Night sphere ability
private constant integer NIGHT = 'A001'
endglobals
private function ChangeSphere takes nothing returns nothing
if GetFloatGameState(GAME_STATE_TIME_OF_DAY)==6. then
call UnitRemoveAbility(HERO,NIGHT)
call UnitAddAbility(HERO,DAY)
else
call UnitRemoveAbility(HERO,DAY)
call UnitAddAbility(HERO,NIGHT)
endif
endfunction
private function InitChild takes nothing returns nothing
call ReleaseTimer(GetExpiredTimer())
if GetFloatGameState(GAME_STATE_TIME_OF_DAY)>=6. and GetFloatGameState(GAME_STATE_TIME_OF_DAY)<18. then
call UnitAddAbility(HERO,DAY)
else
call UnitAddAbility(HERO,NIGHT)
endif
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
call TriggerRegisterGameStateEvent(t,GAME_STATE_TIME_OF_DAY,EQUAL,6.)
call TriggerRegisterGameStateEvent(t,GAME_STATE_TIME_OF_DAY,EQUAL,18.)
call TriggerAddAction(t,function ChangeSphere)
call TimerStart(NewTimer(),0.,false,function InitChild)
set bj_lastCreatedUnit=CreateUnit(Player(15),'hfoo',0.,0.,0.)
call ShowUnit(bj_lastCreatedUnit,false)
call UnitAddAbility(bj_lastCreatedUnit,DAY)
call UnitAddAbility(bj_lastCreatedUnit,NIGHT)
call UnitApplyTimedLife(bj_lastCreatedUnit,'BTLF',.001)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope TreeRespawn initializer Init
globals
// Configurables:
// Time in seconds before trees will respawn
private constant real TIME = 45.
// Required
private trigger t=CreateTrigger()
endglobals
private function Respawn takes nothing returns nothing
call TriggerSleepAction(TIME)
call DestructableRestoreLife(GetTriggerDestructable(),GetDestructableMaxLife(GetTriggerDestructable()),true)
endfunction
private function Register takes nothing returns boolean
call TriggerRegisterDeathEvent(t,GetFilterDestructable())
return false
endfunction
private function Init takes nothing returns nothing
call EnumDestructablesInRect(GetWorldBounds(),Condition(function Register),null)
call TriggerAddAction(t,function Respawn)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Weather initializer Init
globals
// Configurables:
// Time in seconds between random weather effects
private constant real TIME = 35.
// Required
private integer array effects
private integer count=0
private weathereffect we
endglobals
// Setup random weather data
private function SetUp takes nothing returns nothing
// Effect rawcodes, these should start at 1
set effects[1]='RAhr'
set effects[2]='RAlr'
set effects[3]='FDwh'
set effects[4]='FDwl'
set effects[5]='WOlw'
set effects[6]='RLlr'
// The total number of random weather effects
set count=6
endfunction
private function CreateWeather takes nothing returns nothing
local integer i=GetRandomInt(0,count)
call EnableWeatherEffect(we,false)
call RemoveWeatherEffect(we)
if i>0 then
set we=AddWeatherEffect(GetWorldBounds(),effects[i])
call EnableWeatherEffect(we,true)
endif
endfunction
private function Init takes nothing returns nothing
local integer i=1
call SetUp()
loop
exitwhen i>count
set we=AddWeatherEffect(GetWorldBounds(),effects[i])
call RemoveWeatherEffect(we)
set i=i+1
endloop
call TimerStart(CreateTimer(),TIME,true,function CreateWeather)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GroupUtils initializer Init requires optional xebasic
//******************************************************************************
//* BY: Rising_Dusk
//*
//* This library is a combination of several features relevant to groups. First
//* and foremost, it contains a group stack that you can access dynamic groups
//* from. It also provides means to refresh groups and clear any shadow
//* references within them. The included boolexprs are there for backwards
//* compatibility with maps that happen to use them. Since the 1.24c patch,
//* null boolexprs used in GroupEnumUnits* calls no longer leak, so there is no
//* performance gain to using the BOOLEXPR_TRUE constant.
//*
//* Instead of creating/destroying groups, we have moved on to recycling them.
//* NewGroup pulls a group from the stack and ReleaseGroup adds it back. Always
//* remember to call ReleaseGroup on a group when you are done using it. If you
//* fail to do so enough times, the stack will overflow and no longer work.
//*
//* GroupRefresh cleans a group of any shadow references which may be clogging
//* its hashtable. If you remove a unit from the game who is a member of a unit
//* group, it will 'effectively' remove the unit from the group, but leave a
//* shadow in its place. Calling GroupRefresh on a group will clean up any
//* shadow references that may exist within it. It is only worth doing this on
//* groups that you plan to have around for awhile.
//*
//* Constants that can be used from the library:
//* [group] ENUM_GROUP As you might expect, this group is good for
//* when you need a group just for enumeration.
//* [boolexpr] BOOLEXPR_TRUE This is a true boolexpr, which is important
//* because a 'null' boolexpr in enumeration
//* calls results in a leak. Use this instead.
//* [boolexpr] BOOLEXPR_FALSE This exists mostly for completeness.
//*
//* This library also includes a simple implementation of a group enumeration
//* call that factors collision of units in a given area of effect. This is
//* particularly useful because GroupEnumUnitsInRange doesn't factor collision.
//*
//* In your map, you can just replace all instances of GroupEnumUnitsInRange
//* with GroupEnumUnitsInArea with identical arguments and your spells will
//* consider all units colliding with the area of effect. After calling this
//* function as you would normally call GroupEnumUnitsInRange, you are free to
//* do anything with the group that you would normally do.
//*
//* If you don't use xebasic in your map, you may edit the MAX_COLLISION_SIZE
//* variable below and the library will use that as the added radius to check.
//* If you use xebasic, however, the script will automatically use xe's
//* collision size variable.
//*
//* You are also able to use GroupUnitsInArea. This function returns all units
//* within the area, no matter what they are, which can be convenient for those
//* instances where you actually want that.
//*
//* Example usage:
//* local group MyGroup = NewGroup()
//* call GroupRefresh(MyGroup)
//* call ReleaseGroup(MyGroup)
//* call GroupEnumUnitsInArea(ENUM_GROUP, x, y, 350., BOOLEXPR_TRUE)
//* call GroupUnitsInArea(ENUM_GROUP, x, y, 350.)
//*
globals
//If you don't have xebasic in your map, this value will be used instead.
//This value corresponds to the max collision size of a unit in your map.
private constant real MAX_COLLISION_SIZE = 150.00
//If you are insane and don't care about any of the protection involved in
//this library, but want this script to be really fast, set this to true.
private constant boolean LESS_SAFETY = false
endglobals
globals
//* Constants that are available to the user
group ENUM_GROUP = CreateGroup()
boolexpr BOOLEXPR_TRUE = null
boolexpr BOOLEXPR_FALSE = null
endglobals
globals
//* Hashtable for debug purposes
private hashtable ht = InitHashtable()
//* Temporary references for GroupRefresh
private boolean Flag = false
private group Refr = null
//* Arrays and counter for the group stack
private group array Groups
private integer Count = 0
//* Variables for use with the GroupUnitsInArea function
private real X = 0.
private real Y = 0.
private real R = 0.
private hashtable H = InitHashtable()
endglobals
private function HookDestroyGroup takes group g returns nothing
if g == ENUM_GROUP then
call BJDebugMsg(SCOPE_PREFIX+"Warning: ENUM_GROUP destroyed")
endif
endfunction
debug hook DestroyGroup HookDestroyGroup
private function AddEx takes nothing returns nothing
if Flag then
call GroupClear(Refr)
set Flag = false
endif
call GroupAddUnit(Refr, GetEnumUnit())
endfunction
function GroupRefresh takes group g returns nothing
set Flag = true
set Refr = g
call ForGroup(Refr, function AddEx)
if Flag then
call GroupClear(g)
endif
endfunction
function NewGroup takes nothing returns group
if Count == 0 then
set Groups[0] = CreateGroup()
else
set Count = Count - 1
endif
static if not LESS_SAFETY then
call SaveInteger(ht, 0, GetHandleId(Groups[Count]), 1)
endif
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer id = GetHandleId(g)
static if LESS_SAFETY then
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Null groups cannot be released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
endif
else
if g == null then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Null groups cannot be released")
return false
elseif not HaveSavedInteger(ht, 0, id) then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Group not part of stack")
return false
elseif LoadInteger(ht, 0, id) == 2 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Groups cannot be multiply released")
return false
elseif Count == 8191 then
debug call BJDebugMsg(SCOPE_PREFIX+"Error: Max groups achieved, destroying group")
call DestroyGroup(g)
return false
endif
call SaveInteger(ht, 0, id, 2)
endif
call GroupClear(g)
set Groups[Count] = g
set Count = Count + 1
return true
endfunction
private function Filter takes nothing returns boolean
return IsUnitInRangeXY(GetFilterUnit(), X, Y, R)
endfunction
private function HookDestroyBoolExpr takes boolexpr b returns nothing
local integer bid = GetHandleId(b)
if HaveSavedHandle(H, 0, bid) then
//Clear the saved boolexpr
call DestroyBoolExpr(LoadBooleanExprHandle(H, 0, bid))
call RemoveSavedHandle(H, 0, bid)
endif
endfunction
hook DestroyBoolExpr HookDestroyBoolExpr
private constant function GetRadius takes real radius returns real
static if LIBRARY_xebasic then
return radius+XE_MAX_COLLISION_SIZE
else
return radius+MAX_COLLISION_SIZE
endif
endfunction
function GroupEnumUnitsInArea takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing
local real prevX = X
local real prevY = Y
local real prevR = R
local integer bid = 0
//Set variables to new values
set X = x
set Y = y
set R = radius
if filter == null then
//Adjusts for null boolexprs passed to the function
set filter = Condition(function Filter)
else
//Check for a saved boolexpr
set bid = GetHandleId(filter)
if HaveSavedHandle(H, 0, bid) then
//Set the filter to use to the saved one
set filter = LoadBooleanExprHandle(H, 0, bid)
else
//Create a new And() boolexpr for this filter
set filter = And(Condition(function Filter), filter)
call SaveBooleanExprHandle(H, 0, bid, filter)
endif
endif
//Enumerate, if they want to use the boolexpr, this lets them
call GroupEnumUnitsInRange(whichGroup, x, y, GetRadius(radius), filter)
//Give back original settings so nested enumerations work
set X = prevX
set Y = prevY
set R = prevR
endfunction
function GroupUnitsInArea takes group whichGroup, real x, real y, real radius returns nothing
local real prevX = X
local real prevY = Y
local real prevR = R
//Set variables to new values
set X = x
set Y = y
set R = radius
//Enumerate
call GroupEnumUnitsInRange(whichGroup, x, y, GetRadius(radius), Condition(function Filter))
//Give back original settings so nested enumerations work
set X = prevX
set Y = prevY
set R = prevR
endfunction
private function True takes nothing returns boolean
return true
endfunction
private function False takes nothing returns boolean
return false
endfunction
private function Init takes nothing returns nothing
set BOOLEXPR_TRUE = Condition(function True)
set BOOLEXPR_FALSE = Condition(function False)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+)
//* ----------
//*
//* 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)
//* 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 OFFSET manually for it to
// work)
//
private constant boolean USE_HASH_TABLE = false
private constant boolean USE_FLEXIBLE_OFFSET = true
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.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
// 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")
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")
set tT[0]=CreateTimer()
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
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==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
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