Name | Type | is_array | initial_value |
Hero | unit | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Revive initializer init
private function Conditions takes nothing returns nothing
local unit u = GetTriggerUnit()
local player p = GetOwningPlayer(u)
if GetUnitTypeId(u) == 'H000' then
call TriggerSleepAction(5.)
call ReviveHero(u, GetPlayerStartLocationX(p), GetPlayerStartLocationY(p), true)
endif
set u = null
endfunction
//===========================================================================
private function init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction( t, function Conditions )
set t = null
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope PeriodicAttack initializer init
globals
private group G = CreateGroup()
private constant integer UnitID = 'nban'
private constant integer N = 12
endglobals
private function GetUnits takes nothing returns boolean
return true
endfunction
private function Loop takes nothing returns nothing
local location l = GetPlayerStartLocationLoc(Player(11))
set G = CreateNUnitsAtLoc(N, UnitID, Player(11), l, 0.)
call GroupPointOrder(G, "attack", GetPlayerStartLocationX(Player(1)), GetPlayerStartLocationY(Player(1)))
call GroupClear(G)
call RemoveLocation(l)
set l = null
endfunction
private function init takes nothing returns nothing
call TimerStart(CreateTimer(), 15., true, function Loop)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope SetMinGold initializer init
globals
private constant real Gold = 120.
private constant real Factor = 2.
endglobals
private function Actions takes nothing returns nothing
call SetPlayerStateBJ( Player(1), PLAYER_STATE_RESOURCE_GOLD, R2I(Factor * Gold) )
endfunction
//===========================================================================
private function init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterPlayerStateEvent( t, Player(1), PLAYER_STATE_RESOURCE_GOLD, LESS_THAN, Gold )
call TriggerAddAction( t, function Actions )
set t = null
endfunction
endscope
//TESH.scrollpos=0
//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=77
//TESH.alwaysfold=0
//***************************************************************************************************************
//* *
//* Death Carrier (vJASSified). *
//* By Moyack. *
//* V.2.0. *
//* *
//***************************************************************************************************************
// Made for the spell contest No 13 (for the bad luck maybe??)
// Requires TimerUtils (http://www.wc3c.net/showthread.php?t=101322) by Vexorian.
library DeathCarrier initializer init requires TimerUtils
// Configuration part...
globals
private constant integer SpellID = 'A000' // Sets the ability Rawcode
private constant real TIMEOUT = 0.5 // Sets the timer frequency
private constant attacktype ATTACK = ATTACK_TYPE_SIEGE // Sets the type of attack that deals the spell
private constant damagetype DAMAGE = DAMAGE_TYPE_NORMAL // Sets the type of damage that deals the spell
endglobals
private constant function Damage takes integer lvl returns real
return 100. + 70. * (lvl - 1)
endfunction
private constant function AOE takes integer lvl returns real
return 500. // I left it in this way so it can be configurable to a variable area
endfunction
private constant function Jumps takes integer lvl returns integer
return 5 // sets the number of times the maks jumps on units before explode
endfunction
// end configuration part...
private function GetEnemies takes nothing returns boolean
return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.405 and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(bj_groupRandomCurrentPick))
endfunction
private struct data
group g
unit c
integer counter = 0
private method onDestroy takes nothing returns nothing
call GroupClear(.g)
set .c = null
endmethod
private static method PickRandomUnit takes nothing returns nothing
set bj_groupRandomConsidered = bj_groupRandomConsidered + 1
if GetWidgetLife(GetEnumUnit()) > 0.405 and GetRandomInt(1,bj_groupRandomConsidered) == 1 then
set bj_groupRandomCurrentPick = GetEnumUnit()
endif
endmethod
static method effect takes nothing returns nothing
local data d = thistype( GetTimerData(GetExpiredTimer()) )
local real x
local real y
set bj_groupRandomConsidered = 0
set bj_groupRandomCurrentPick = null
call ForGroup(d.g, function thistype.PickRandomUnit)
if bj_groupRandomCurrentPick == null then
call d.destroy()
call ReleaseTimer(GetExpiredTimer())
return
endif
call DestroyEffect(AddSpellEffectTargetById(SpellID, EFFECT_TYPE_SPECIAL, bj_groupRandomCurrentPick, "overhead"))
set d.counter = d.counter + 1
if d.counter > Jumps(GetUnitAbilityLevel(d.c, SpellID)) then
set x = GetUnitX(bj_groupRandomCurrentPick)
set y = GetUnitY(bj_groupRandomCurrentPick)
call DestroyEffect(AddSpecialEffect(GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 1), x, y))
// at this point, d.g is not needed, so I'll use to do the final task :P
set bj_groupRandomCurrentPick = d.c
call GroupEnumUnitsInRange(d.g, x, y, 0.5 * AOE(GetUnitAbilityLevel(d.c, SpellID)), Condition(function GetEnemies))
loop
set bj_groupRandomCurrentPick = FirstOfGroup(d.g)
exitwhen bj_groupRandomCurrentPick == null
call UnitDamageTarget(d.c, bj_groupRandomCurrentPick, Damage(GetUnitAbilityLevel(d.c, SpellID)), true, true, ATTACK, DAMAGE, WEAPON_TYPE_ROCK_HEAVY_BASH)
call DestroyEffect(AddSpecialEffectTarget(GetAbilityEffectById(SpellID, EFFECT_TYPE_SPECIAL, 2), bj_groupRandomCurrentPick, "chest"))
call GroupRemoveUnit(d.g, bj_groupRandomCurrentPick)
endloop
call d.destroy()
call ReleaseTimer(GetExpiredTimer())
else
call UnitDamageTarget(d.c, bj_groupRandomCurrentPick, GetRandomReal(0, Damage(GetUnitAbilityLevel(d.c, SpellID))), true, false, ATTACK, DAMAGE, WEAPON_TYPE_ROCK_HEAVY_BASH)
endif
endmethod
static method Start takes unit c, real x, real y returns nothing
local data d = data.allocate()
local timer t = NewTimer()
if d.g == null then
set d.g = CreateGroup()
endif
set d.c = c
set bj_groupRandomCurrentPick = c
call GroupEnumUnitsInRange(d.g, x, y, AOE(GetUnitAbilityLevel(c, SpellID)), Condition(function GetEnemies))
call SetTimerData(t, integer(d))
call TimerStart(t, TIMEOUT, true, function data.effect)
set t = null
endmethod
endstruct
private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == SpellID then
call data.Start(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
endif
return false
endfunction
//===========================================================================
private function init takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function Conditions ) )
set t = null
endfunction
endlibrary