Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
library_once TimerUtils
//*********************************************************************
//* TimerUtils (Blue flavor)
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3campaigns.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Blue Flavor: Slower than the red flavor, it got a 408000 handle id
//* limit, which means that if more than 408000 handle ids
//* are used in your map, TimerUtils might fail, this
//* value is quite big and it is much bigger than the
//* timer limit in Red flavor.
//*
//********************************************************************
//================================================================
globals
private constant integer MAX_HANDLE_ID_COUNT = 408000
// values lower than 8191: very fast, but very unsafe.
// values bigger than 8191: not that fast, the bigger the number is the slower the function gets
// Most maps don't really need a value bigger than 50000 here, but if you are unsure, leave it
// as the rather inflated value of 408000
endglobals
//=================================================================================================
private function H2I takes handle h returns integer
return h
return 0
endfunction
//==================================================================================================
globals
private integer array data[MAX_HANDLE_ID_COUNT]
private constant integer MIN_HANDLE_ID=0x100000
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
debug call BJDebugMsg("SetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
debug endif
set data[H2I(t)-MIN_HANDLE_ID]=value
endfunction
function GetTimerData takes timer t returns integer
debug if(H2I(t)-MIN_HANDLE_ID>=MAX_HANDLE_ID_COUNT) then
debug call BJDebugMsg("GetTimerData: Handle id too big, increase the max handle id count or use gamecache instead")
debug endif
return data[H2I(t)-MIN_HANDLE_ID]
endfunction
//==========================================================================================
globals
private timer array tT
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
endglobals
//==========================================================================================
function NewTimer takes nothing returns timer
if (tN==0) then
set tT[0]=CreateTimer()
else
set tN=tN-1
endif
call SetTimerData(tT[tN],0)
return tT[tN]
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==8191) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//=====================================================================================
//=====================================================================================
//==============================Teleporting=Shot=v1.3==================================
//=====================================================================================
//=====================================================================================
//==================================By=xD,Schurke======================================
//=====================================================================================
//=====================================================================================
scope teleportingshot initializer teleportInt
globals
private integer DUMMY = 'h000' //dummy id: change to your map specific dummy raw code
private integer SPELL_RAW = 'A000' //the spell rawcode: change to your map specific spell raw code
private integer DUMMY_SPELL_RAW = 'A001' //the dummy spell rawcode: change to your map specific dummy spell raw code
private integer DUMMY_SPELL_DEBUFF = 'B000' //the dummy spell debuff: change to your map specific dummy spell debuff raw code
private integer TIMED_LIFE_RAW = 'BTLF' //don't change (timed life raw code)
//the diffrent effect strings
private constant string SPELL_SFX = "Abilities\\Spells\\Undead\\DeathPact\\DeathPactTarget.mdl" //the effect of the wave
private constant string SPELL_SFX_TWO = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTo.mdl" //the effect, which is created at the casting point
private constant string SPELL_SFX_THREE = "Abilities\\Spells\\Human\\MassTeleport\\MassTeleportTarget.mdl" //the teleporting effect
//below are some diffrent values
private constant real Range = 950. //the max range of the spell, change to increase/decrease the range
private constant real Interval = 0.1 //the timer interval DON'T CHANGE
private constant real TELEPORT_INTERVAL = 1. //the interval after which time the units are teleported
private constant real WAVE_SPEED = 45. //decrease/increase for a lower/higher speed
private constant real CASTER_STOP = 90. //must always be a multiplicator of WAVE_SPEED
private constant real DAMAGE = 50
//the order strings
private constant string curse = "curse" //dummy spell order string
private constant string stop = "stop" //stop string for caster, because spell is based on channel
endglobals
//function for the damage calculation
private function damage takes integer lvl returns real
return I2R(lvl)*DAMAGE
endfunction
private struct teleportstruct
unit caster //stores the caster
group g = CreateGroup() //stores the units for teleporting issues and only one time damage
timer t //timer for executing the method effectmethod
real curdis = 0 //distance, increases each 0.05 seconds by 20
real x1 = 0 //x coordinate of the caster
real y1 = 0 //y coordinate of the caster
real x2 = 0 //x coordinate of the target point ability being cast (for getting the angle)
real y2 = 0 //y coordinate of the target point ability being cast (for getting the angle)
real angle = 0 //angle: for the direction of the spell
effect sfx //the effect which is created at the casters point
static method teleport takes nothing returns nothing
local teleportstruct Dat = GetTimerData(GetExpiredTimer())
local unit u
//part where the units are teleported
loop
set u = FirstOfGroup(Dat.g)
exitwhen u == null
if GetUnitState(u,UNIT_STATE_LIFE) > 0 then
call DestroyEffect(AddSpecialEffect(SPELL_SFX_THREE,GetUnitX(u),GetUnitY(u)))
call SetUnitPosition(u,Dat.x1,Dat.y1)
call UnitRemoveAbility(u,DUMMY_SPELL_DEBUFF)
call GroupRemoveUnit(Dat.g,u)
else
call GroupRemoveUnit(Dat.g,u)
endif
endloop
call teleportstruct.destroy(Dat)
set u = null
endmethod
static method effectmethod takes nothing returns nothing
local teleportstruct Dat = GetTimerData(GetExpiredTimer()) //gets the struct with the TimerUtiles function GetTimerData
local group g = CreateGroup() //Group for damaging and later teleporting issues
local unit u //group unit
local real x //x for wave effect
local real y //y for wave effect
local unit dummy //dummy variable
set Dat.curdis = Dat.curdis + WAVE_SPEED //increases the current distance for the next two lines nessesary
set x = Dat.x1 + Dat.curdis * Cos(Dat.angle * bj_DEGTORAD)
set y = Dat.y1 + Dat.curdis * Sin(Dat.angle * bj_DEGTORAD)
call DestroyEffect(AddSpecialEffect(SPELL_SFX,x,y)) //creates the effect and destroys it
call GroupEnumUnitsInRange(g,x,y,150,null) //picks all units in a range of 150 of x and y (for damaging etc.) following loop for picking units
loop
set u = FirstOfGroup(g)
exitwhen u == null
if IsUnitEnemy(u,GetOwningPlayer(Dat.caster)) and IsUnitType(u,UNIT_TYPE_STRUCTURE) != true and GetUnitState(u,UNIT_STATE_LIFE) > 0 and IsUnitInGroup(u,Dat.g) != true then //checks diffrent aspects for damaging target etc.
call UnitDamageTarget(Dat.caster,u,damage(GetUnitAbilityLevel(Dat.caster,SPELL_RAW)),false,true,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS) //damages the current unit u
//dummy part for adding debuff to unit u
set dummy = CreateUnit(GetOwningPlayer(Dat.caster),DUMMY,GetUnitX(u),GetUnitY(u),0)
call UnitAddAbility(dummy,DUMMY_SPELL_RAW)
call IssueTargetOrder(dummy,curse,u)
call UnitApplyTimedLife(dummy,TIMED_LIFE_RAW,1)
//=======================================
call GroupAddUnit(Dat.g,u) //adds the unit u to the group g in the struct teleportstruct
call GroupRemoveUnit(g,u) //removes current unit u from group g
else
call GroupRemoveUnit(g,u) //removes current unit u from group g
endif
endloop
call DestroyGroup(g) //destroys group g for preventing leaks
if Dat.curdis == CASTER_STOP then //after a short time (0.25sec) the caster stops casting (because spell is based on channel)
call IssueImmediateOrder(Dat.caster,stop)
endif
//if the current distance (curdis) reachs (in this case 800) the method onDestroy is called
if Dat.curdis >= Range then
call PauseTimer(Dat.t)
call SetTimerData(Dat.t,Dat)
call TimerStart(Dat.t,TELEPORT_INTERVAL,false,function teleportstruct.teleport)
endif
//nullify the local vars
set g = null
set u = null
set dummy = null
endmethod
//part for creating the struct and setting values to the vars
static method create takes unit u, real x, real y returns teleportstruct
local teleportstruct Dat = teleportstruct.allocate()
set Dat.caster = u
set Dat.x1 = GetUnitX(u)
set Dat.y1 = GetUnitY(u)
set Dat.x2 = x
set Dat.y2 = y
set Dat.angle = bj_RADTODEG * Atan2(Dat.y2 - Dat.y1, Dat.x2 - Dat.x1)
set Dat.sfx = AddSpecialEffect(SPELL_SFX_TWO,GetUnitX(u),GetUnitY(u))
set Dat.t = NewTimer()
call SetTimerData(Dat.t,Dat)
call TimerStart(Dat.t,Interval,true,function teleportstruct.effectmethod)
return Dat
endmethod
//method which nullifys all struct variables and teleports the units in the struct group var g to the casting point
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t) //a TimerUtiles function similar to DestroyTimer()
set .t = null
set .caster = null
call DestroyGroup(.g)
set .g = null
call DestroyEffect(.sfx)
set .sfx = null
endmethod
endstruct
//returns every time false, so that we don't need an action function
private function teleportCond takes nothing returns boolean
local teleportstruct Dat
if GetSpellAbilityId() == SPELL_RAW then
set Dat = teleportstruct.create(GetTriggerUnit(),GetLocationX(GetSpellTargetLoc()),GetLocationY(GetSpellTargetLoc())) //gives the needed values over to the struct and creates it
endif
return false
endfunction
//initialization function with preloading part
private function teleportInt takes nothing returns nothing
local trigger int = CreateTrigger()
local unit u
local integer index = 0
loop
call TriggerRegisterPlayerUnitEvent(int, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(int,Condition(function teleportCond))
//Preloading
set u = CreateUnit(Player(14),DUMMY,999999,999999,0)
call UnitAddAbility(u,DUMMY_SPELL_RAW)
call RemoveUnit(u)
call Preload(SPELL_SFX)
call Preload(SPELL_SFX_TWO)
call Preload(SPELL_SFX_THREE)
set int = null
set u = null
endfunction
endscope