Name | Type | is_array | initial_value |
CL_castpt | location | No | |
CL_real | real | No | |
CL_tarpt | location | No | |
CL_tempeff | effect | No | |
CL_temprect | rect | No | |
CL_tmppt | location | No | |
CL_tmppt2 | location | No | |
CL_tmppt3 | location | No | |
do_not_copy_me | location | No |
//TESH.scrollpos=6
//TESH.alwaysfold=0
//==Chaoslaser v2==
//~Uses TimerUtils (blue flavor)
//~Needs jngp
//Credits go to HINDYhat for teaching me jass and correcting my spell a couple of times ^^
//2oo9 by Squiggy
scope CLv2 initializer SpellInit
globals
private constant integer SPELLID = 'A000' //First, I set the constants to the two abilites
private constant integer SPELLID2 = 'A001'
private constant integer DmgFactor = 30 //Here you can preset the amount of damage which is going to be dealt (level*DmgFactor)
private constant real distance = 100 //Here, you can change the distance in which the beamdummies are created
private constant string effpath = "Abilities\\Spells\\Undead\\DarkRitual\\DarkRitualTarget.mdl" //And here, you can change the cast effect
endglobals
globals
private player p
endglobals
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == SPELLID //The usual condition
endfunction
private struct growth //The struct 'growth' holds every needed data for the growth of the dummy and the
unit dummy //stuff that goes after
real size
real grow
real posX
real posY
real facing
real distance
integer abilv
real distaddX
real distaddY
endstruct
private function Grp takes nothing returns boolean //Group filter to your left
return IsUnitEnemy(GetFilterUnit(), p)
endfunction
//Everything after the dummy is created goes here
private function grow takes nothing returns nothing
local integer INDEX //First, we define and set the needed locals
local unit u
local unit gru
local group g
local growth gt = growth(GetTimerData(GetExpiredTimer())) //Now we get the data from the expired timer
set gt.size = gt.size + .1 //We increase the dummysize by 10%
call BJDebugMsg(R2S(gt.size))
call SetUnitScale(gt.dummy, gt.size, gt.size, gt.size)
if gt.size > 10 then //Now if the dummysize reaches 10, it's time to create the 'laserbeam'
set g = CreateGroup()
call ReleaseTimer(GetExpiredTimer()) //and to remove the timer
set INDEX = 0
call RemoveUnit(gt.dummy)
set gt.posX = GetUnitX(gt.dummy)
set gt.posY = GetUnitY(gt.dummy)
loop
exitwhen INDEX >= (gt.distance/distance) //Now we create one dummy per 100 warcraft units until the distance it reached
set u = CreateUnit(p, 'n001', gt.posX, gt.posY, gt.facing)
call SetUnitAbilityLevel(u, SPELLID2, gt.abilv)
call UnitApplyTimedLife(u, 'BLTF' , .2)
set INDEX = INDEX+1
set gt.posX = gt.posX + gt.distaddX //And here we move the position of the next created dummy 'forward'
set gt.posY = gt.posY + gt.distaddY
endloop
set INDEX = 0
loop
exitwhen INDEX == 8 // Now we spawn the eight dummies which move outwards from the current position
set u = CreateUnit(p, 'n001', gt.posX, gt.posY, INDEX*45)
call SetUnitAbilityLevel(u, SPELLID2, gt.abilv)
call IssuePointOrder(u, "move", gt.posX+1000.00*Cos((INDEX*45)*bj_DEGTORAD), gt.posY+1000.00*Sin((INDEX*45)*bj_DEGTORAD)) //We order it to move
call SetUnitScale(u, 0.3, 0.3, 0.3) //And now we decrease it's scaling to 0.33
call UnitApplyTimedLife(u, 'BLTF' , 1.2)
set INDEX = INDEX+1
endloop
set u = CreateUnit(p, 'n002', gt.posX, gt.posY, 90) //Last, we need the effect and to deal damage
call SetUnitAbilityLevel(u, SPELLID2, gt.abilv)
call UnitApplyTimedLife(u, 'BLTF' , 1.0)
call GroupEnumUnitsInRange(g, gt.posX, gt.posY, 500, Filter(function Grp))
loop //As we just picked every unit in 200 range from the point where the dummy is spawned
set gru = FirstOfGroup(g) //we deal the damage equal to lvl*30
exitwhen gru == null
call UnitDamageTarget(u, gru, gt.abilv*DmgFactor, false, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
call GroupRemoveUnit(g, gru)
endloop
set u = null //And now we null the necessary variables and clean up leaks
set gt.dummy = null
call DestroyGroup(g)
set g = null
call gt.destroy()
endif
endfunction
private function Actions takes nothing returns nothing //This part of the spell creates the dummy and starts the timer which makes the dummy 'grow'
local unit caster = GetTriggerUnit()
local real dx
local real dy
local location targetpoint = GetSpellTargetLoc()
local timer t = NewTimer() //Here, we create the timer
local growth gt = growth.create()
set p = GetOwningPlayer(caster)
call SetTimerData(t, integer(gt))
set gt.abilv = GetUnitAbilityLevel(caster, SPELLID)
set gt.size = 0.00
set gt.facing = GetUnitFacing(caster)
set gt.dummy = CreateUnit(p, 'n000', GetUnitX(caster)+distance*Cos(gt.facing*bj_DEGTORAD), GetUnitY(caster)+100.00*Sin(gt.facing*bj_DEGTORAD), gt.facing)
call TimerStart(t, 0.04, true, function grow) //Now we start it
set gt.posX = GetUnitX(gt.dummy)
set gt.posY = GetUnitY(gt.dummy)
set dx = GetLocationX(targetpoint)-gt.posX //And now it's time to get the diatance between the caster and the targeted point
set dy = GetLocationY(targetpoint)-gt.posY
set gt.distance = SquareRoot(dx * dx + dy * dy)
set gt.distaddX = distance*Cos(gt.facing*bj_DEGTORAD)
set gt.distaddY = distance*Sin(gt.facing*bj_DEGTORAD)
call SetUnitScale(gt.dummy, gt.size, gt.size, gt.size)
call IssueTargetOrder(gt.dummy, "thunderbolt", caster) //This is done to stun the caster (looks crappy if he can move while casting
call DestroyEffect(AddSpecialEffect(effpath, gt.posX, gt.posY))
call RemoveLocation(targetpoint) //And here we get rid of leaks
set caster = null
endfunction
private function SpellInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t, Condition(function Conditions))
call TriggerAddAction(t, function Actions)
endfunction
endscope
//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