Boomerang v1.02
Import Difficulty: Low
Units Affected: Ground/Air
Target Type: Unit/Point - Enemy, Ground, Terrain
Spell Info:
Toss your handy dandy boomerang toward the targeted location, which promptly returns to you, following an elliptical path. Units unlucky enough to wander nearby are dealt damage and disarmed for a short duration.
Requirements:
UnitAlive native
TimerUtils
GroupUtils
Would also be a good idea to make use of Bound Sentinel
JASS:
scope Boomerang initializer Init
//*********************************************************************
//* Boomerang v1.02
//* by: emjlr3
//* ----------
//*
//* Requirements:
//* *A point target ability, like the "Boomerang" ability found in this map
//* *A dummy unit, like the "Caster Dummy" unit found in this map
//* *UnitAlive native, found in the custom script section of this map
//* *TimerUtils library
//* <a href="http://www.wc3c.net/showthread.php?t=101322" target="_blank" class="link link--external" rel="nofollow noopener">http://www.wc3c.net/showthread.php?t=101322</a>
//* *GroupUtils library
//* <a href="http://www.wc3c.net/showthread.php?t=104464" target="_blank" class="link link--external" rel="nofollow noopener">http://www.wc3c.net/showthread.php?t=104464</a>
//* *A copy of this trigger
//* *Although not required, the BoundSentinel library is recommended
//* <a href="http://www.wc3c.net/showthread.php?t=102576" target="_blank" class="link link--external" rel="nofollow noopener">http://www.wc3c.net/showthread.php?t=102576</a>
//*
//* (requires vJass) More abilities at <a href="http://www.thehelper.net/forums" class="link link--internal">http://www.thehelper.net/forums</a>
//*
//* Credits:
//* *Vexorian for his TimerUils library
//* *Rising_Dusk for his GroupUtils library
//*
//* Important:
//* *SFX strings can be set to "" for no effect.
//* *The boomerang returns to where the hero was, not where it is. Using
//* an ability with a follow through time can help alleviate this problem
//* if you choose not to use the PAUSE option.
//* *Stacking casts of the buff will overwrite the previous cast only
//* when it's buff duration exceeds that left from the previous use.
//* *DISARMABIL and HARVEST need only be changed if you have modified
//* the base ability. If so, copy and paste a new, un-edited version and
//* use it's rawcode for these values.
//*
//********************************************************************
//==CONFIGURATION==\\
globals
private constant attacktype ATTACK = ATTACK_TYPE_MAGIC // Ability damage attacktype
private constant boolean KILLTREES = true // Have boomerang destroy trees in it's path
private constant boolean PAUSE = false // Pause caster until boomerange returns
private constant boolean PRELOAD = true // Preload DISARMABIL and effects, will use MISSILE as dummy unit
private constant boolean REMOVE = true // Remove ABIL during boomerang movement
private constant damagetype DAMAGE = DAMAGE_TYPE_MAGIC // Ability damage damagetype
private constant integer ABIL = 'A005' // Boomerang ability rawcode
private constant integer DISARMABIL = 'Abun' // Cargo Hold (Orc Burrow) ability rawcode
private constant integer HARVEST = 'Ahrl' // Harvest (Ghouls Lumber) ability rawcode
private constant integer MAXHANDLES = 8190 // Map's max handle count, don't change if unsure
private constant integer MISSILE = 'n000' // Boomerang dummy unit rawcode
private constant integer OFFSET = 0x100000 // Map's first handle id, don't change if unsure
private constant real BUFFACC = .15 // Periodic check on afflicted units for buff removal, lower values decrease performance
private constant real HEIGHT = 40. // Boomerang fly height
private constant real RANGE = 175. // Target and tree intersection range
private constant real TIMEOUT = 0.03 // Periodic timer interval, lower values decrease performance
private constant string BOOMSFX = "Abilities\\Weapons\\BloodElfSpellThiefMISSILE\\BloodElfSpellThiefMISSILE.mdl" // Boomerang model
private constant string BOOMSFXAP = "origin" // Attachment point for BOOMSFX on MISSILE
private constant string BUFFSFX = "Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl" // Target buff model
private constant string BUFFSFXAP = "overhead" // Attachment point for BUFFSFX
private constant string TARGETSFX = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" // Boomerang strikes target model
private constant string TARGETSFXAP = "chest" // Attachment point for TARGETSFX
endglobals
private function Damage takes integer level returns real
return 100.*level // Damage dealt when the boomerang strikes a target
endfunction
private function Duration takes integer level returns real
return 1.*level // Buff duration
endfunction
private function Life takes integer level, real distance returns real
return .5+distance/500. // Time it takes the boomerang to finish it's trajectory, distance is the cast distance
endfunction
private function Targets takes unit caster, unit target returns boolean
return true // Custom boomerang targeting boolean function
endfunction
private function Width takes integer level, real distance returns real
return distance/2. // Radius of the boomerang arc, distance is the cast distance
endfunction
//==NO TOUCHING PAST THIS POINT==\\
private keyword data
private keyword disarm
globals
private boolexpr BOOL
private group DISARMGROUP = CreateGroup()
private group GROUP = CreateGroup()
private constant real HALFPI = bj_PI/2.
private rect RECT
private unit TARG
private data TEMPDATA
private unit TREEDUMMY
private data array DATA
private integer DATACOUNT = 0
private timer DATATIMER = CreateTimer()
private disarm array UNITDISARM[MAXHANDLES]
endglobals
private function h2i takes unit u returns integer
return GetHandleId(u)-OFFSET
endfunction
private struct disarm
timer t
unit u
effect sfx
real time=0.
real max
method destroy takes nothing returns nothing
call UnitRemoveAbility(.u,DISARMABIL)
call DestroyEffect(.sfx)
call ReleaseTimer(.t)
call GroupRemoveUnit(DISARMGROUP,.u)
call .deallocate()
endmethod
endstruct
private struct data
group g
unit u
unit boom
effect sfx
player p
real face
real x
real y
real a
real cosa
real sina
real dist
real width
real xd
real yd
real damage
real life
real halfmaxticks
integer i=0
integer lvl
integer maxticks
boolean early=false
method destroy takes nothing returns nothing
local integer i=1
call ReleaseGroup(.g)
static if REMOVE then
call SetPlayerAbilityAvailable(.p,ABIL,true)
endif
static if PAUSE then
call PauseUnit(.u,false)
endif
call DestroyEffect(.sfx)
call RemoveUnit(.boom)
if .early then
loop
exitwhen DATA<i>==this
set i=i+1
endloop
set DATA<i>=DATA[DATACOUNT]
set DATACOUNT=DATACOUNT-1
endif
call .deallocate()
endmethod
endstruct
//=====================================================================
private function KillTrees takes nothing returns boolean
if IssueTargetOrder(TREEDUMMY,"harvest",GetFilterDestructable()) then
call KillDestructable(GetFilterDestructable())
endif
return false
endfunction
private function KillTreesInRange takes real x, real y, real radius returns nothing
call SetRect(RECT,x-radius,y-radius,x+radius,y+radius)
call PauseUnit(TREEDUMMY,false)
call EnumDestructablesInRect(RECT,Condition(function KillTrees),null)
call PauseUnit(TREEDUMMY,true)
endfunction
private function Update takes nothing returns nothing
local disarm d=GetTimerData(GetExpiredTimer())
if not UnitAlive(d.u) or d.time>=d.max then
call d.destroy()
else
set d.time=d.time+BUFFACC
endif
endfunction
private function Filt takes nothing returns boolean
local data d=TEMPDATA
local disarm di
set TARG=GetFilterUnit()
if IsUnitEnemy(TARG,d.p) and UnitAlive(TARG) and not IsUnitInGroup(TARG,d.g) and Targets(d.u,TARG) then
call GroupAddUnit(d.g,TARG)
call DestroyEffect(AddSpecialEffectTarget(TARGETSFX,TARG,TARGETSFXAP))
call UnitDamageTarget(d.u,TARG,d.damage,false,false,ATTACK,DAMAGE,null)
call UnitAddAbility(TARG,DISARMABIL)
call UnitMakeAbilityPermanent(TARG,true,DISARMABIL)
if not IsUnitInGroup(TARG,DISARMGROUP) then
set di=disarm.create()
set di.max=Duration(d.lvl)
set di.t=NewTimer()
set di.u=TARG
set di.sfx=AddSpecialEffectTarget(BUFFSFX,TARG,BUFFSFXAP)
call SetTimerData(di.t,di)
call TimerStart(di.t,BUFFACC,true,function Update)
set UNITDISARM[h2i(TARG)]=di
call GroupAddUnit(DISARMGROUP,TARG)
else
set di=UNITDISARM[h2i(TARG)]
if di.max-di.time<Duration(d.lvl) then
set di.time=0.
set di.max=Duration(d.lvl)
endif
endif
endif
return false
endfunction
private function Effects takes nothing returns nothing
local data d
local integer i=1
local real r
local real ra
local real rb
local real x
local real y
loop
exitwhen i>DATACOUNT
set d=DATA<i>
set r=(1-I2R(d.i)/d.halfmaxticks)*bj_PI
set ra=d.dist/2.*Cos(r)
set rb=d.width/2.*Sin(r)
set x=d.xd+ra*d.cosa-rb*d.sina
set y=d.yd+ra*d.sina+rb*d.cosa
if d.i>=d.maxticks then
static if KILLTREES then
call KillTreesInRange(x,y,RANGE)
endif
call d.destroy()
set DATA<i>=DATA[DATACOUNT]
set DATACOUNT=DATACOUNT-1
set i=i-1
else
static if KILLTREES then
call KillTreesInRange(x,y,RANGE)
endif
set d.i=d.i+1
call SetUnitX(d.boom,x)
call SetUnitY(d.boom,y)
call SetUnitFacing(d.boom,(d.a+r-HALFPI)*bj_RADTODEG)
set TEMPDATA=d
call GroupEnumUnitsInRange(GROUP,x,y,RANGE,BOOL)
endif
set i=i+1
endloop
if DATACOUNT==0 then
call PauseTimer(DATATIMER)
endif
endfunction
private function Actions takes nothing returns nothing
local data d=data.create()
local real dx
local real dy
set d.u=GetTriggerUnit()
set d.p=GetOwningPlayer(d.u)
set d.face=GetUnitFacing(d.u)
set d.x=GetUnitX(d.u)
set d.y=GetUnitY(d.u)
set d.boom=CreateUnit(d.p,CasterId,d.x,d.y,d.face)
set d.sfx=AddSpecialEffectTarget(BOOMSFX,d.boom,BOOMSFXAP)
set dx=GetSpellTargetX()-d.x
set dy=GetSpellTargetY()-d.y
set d.dist=SquareRoot(dx*dx+dy*dy)
set d.a=Atan2(dy,dx)
set d.cosa=Cos(d.a)
set d.sina=Sin(d.a)
set d.xd=d.x+d.dist/2.*Cos(d.a)
set d.yd=d.y+d.dist/2.*Sin(d.a)
set d.lvl=GetUnitAbilityLevel(d.u,ABIL)
set d.damage=Damage(d.lvl)
set d.width=Width(d.lvl,d.dist)
set d.life=Life(d.lvl,d.dist)
set d.maxticks=R2I(d.life/TIMEOUT)
set d.halfmaxticks=d.maxticks/2.
set d.g=NewGroup()
set DATACOUNT=DATACOUNT+1
set DATA[DATACOUNT]=d
if DATACOUNT==1 then
call TimerStart(DATATIMER,TIMEOUT,true,function Effects)
endif
call SetUnitPathing(d.boom,false)
call UnitAddAbility(d.boom,'Aloc')
call SetUnitFlyHeight(d.boom,HEIGHT,0.)
static if REMOVE then
call SetPlayerAbilityAvailable(d.p,ABIL,false)
endif
static if PAUSE then
call PauseUnit(d.u,true)
endif
endfunction
//======================================================================
private function Conditions takes nothing returns boolean
if GetSpellAbilityId()==ABIL then
call Actions()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=0
loop
exitwhen i>bj_MAX_PLAYERS
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
set i=i+1
endloop
call TriggerAddCondition(t,Condition(function Conditions))
set BOOL=Condition(function Filt)
static if PRELOAD then
set TARG=CreateUnit(Player(15),MISSILE,0.,0.,0.)
call UnitAddAbility(TARG,DISARMABIL)
call UnitApplyTimedLife(TARG,'BTLF',.001)
call Preload(BOOMSFX)
call Preload(BUFFSFX)
call Preload(TARGETSFX)
endif
static if KILLTREES then
set RECT=Rect(0.,0.,100.,100.)
set TREEDUMMY = CreateUnit(Player(15),MISSILE,0.,0.,0.)
call ShowUnit(TREEDUMMY,false)
call UnitAddAbility(TREEDUMMY,HARVEST)
call UnitAddAbility(TREEDUMMY,'Aloc')
call PauseUnit(TREEDUMMY,true)
endif
endfunction
endscope</i></i></i></i>
Orbital v1.02
Import Difficulty: Low
Units Affected: Ground/Air
Target Type: Instant
Spell Info:
Summon 4 orbitting masses of molten rock, which slowly circle, awaiting their masters command. They grow in size and power over 12 seconds, however, their massive energy can only be maintained for a short while.
Upon expiration, deals damage to enemies or heals allies surrounding the impact zone.
If their timer expires, they automatically target their summoner.
Requirements:
UnitAlive native
Would also be a good idea to make use of Bound Sentinel
JASS:
scope Orbital initializer Init
//*********************************************************************
//* Orbital v1.02
//* by: emjlr3
//* ----------
//*
//* Requirements:
//* *An instant cast ability, like the "Orbital" ability found in this map
//* *A dummy unit, like the "Caster Dummy" unit found in this map
//* *UnitAlive native, found in the custom script section of this map
//* *A copy of this trigger
//* *Although not required, the BoundSentinel library is recommended
//* <a href="http://www.wc3c.net/showthread.php?t=102576" target="_blank" class="link link--external" rel="nofollow noopener">http://www.wc3c.net/showthread.php?t=102576</a>
//*
//* (requires vJass) More abilities at <a href="http://www.thehelper.net/forums" class="link link--internal">http://www.thehelper.net/forums</a>
//*
//* Credits:
//* *DotA for spell architecture inspiration
//*
//* Important:
//* *SFX strings can be set to "" for no effect.
//* *Instance limit of 8190/OMAX.
//* *One instance per unit. This is, for the most part, rendered
//* safe through clever ability availability manipulation.
//*
//********************************************************************
//==CONFIGURATION==\\
globals
private constant attacktype ATTACK = ATTACK_TYPE_MAGIC // Collision damage attacktype
private constant boolean CLK = true // Rotate clockwise
private constant boolean PRELOAD = true // Preload effects and TARGET ability, will use DUM as dummy unit
private constant damagetype DAMAGE = DAMAGE_TYPE_MAGIC // Collision damage damagetype
private constant integer ABIL = 'A002' // Orbital ability rawcode
private constant integer DUM = 'n000' // Orbital dummy unit rawcode
private constant integer MAXHANDLES = 8190 // Map's max handle count, don't change if unsure
private constant integer OFFSET = 0x100000 // Map's first handle id, don't change if unsure
private constant integer OMAX = 4 // Max number of orbitals
private constant integer TARGET = 'A004' // Target Orbitals ability rawcode
private constant real SPEED = 18. // Speed at which orbitals follow targets, distance/TIMEOUT
private constant real TIMEOUT = .03 // Periodic timer interval
private constant string MDL = "Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl" // Orbital model
private constant string MDLAP = "origin" // Attachment point for MDL
private constant string SFX = "Abilities\\Spells\\Other\\Volcano\\VolcanoMissile.mdl" // Effect on targets following collision
private constant string SND = "Abilities\\Spells\\Other\\SoulBurn\\SoulBurn1.wav" // Sound to play when orbitals reach max strength
endglobals
private function Damage takes integer level, real currtime, real maxtime returns real
// currtime is current elapsed time of spell, maxtime is the total time required for orbitals to reach maximum power
return level*10+level*20*RMinBJ(currtime/maxtime,1.) // Damage/heal effect on applicable targets
endfunction
private function Distance takes integer level returns real
return 200. // Orbitals rotation distance from caster
endfunction
private function Orbitals takes integer level returns integer
return 4 // Number of orbitals
endfunction
private function Range takes integer level, real currtime, real maxtime returns real
// currtime is current elapsed time of spell, maxtime is the total time required for orbitals to reach maximum power
return 200.+100.*RMinBJ(currtime/maxtime,1.) // Collision effects radius
endfunction
private function ReachMax takes integer level returns real
return 12.*.75 // Time required for orbitals to reach maximum strength
endfunction
private function ScaleIncrease takes integer level, real currtime, real maxtime returns real
// currtime is current elapsed time of spell, maxtime is the total time required for orbitals to reach maximum power
return .5+1.*RMinBJ(currtime/maxtime,1.) // Orbital model scale @ time currtime
endfunction
private function StartScale takes integer level returns real
return .5 // Orbital initial model scale
endfunction
private function Targets takes unit caster, unit target returns boolean
return true // Custom orbital targeting boolean function
endfunction
private function Time takes integer level returns real
return 12. // Max timed life of orbitals
endfunction
private function Update takes integer level returns real
return 360.*TIMEOUT // Rate at which orbitals coords around caster change, angle degrees/TIMEOUT
endfunction
//==NO TOUCHING PAST THIS POINT==\\
private keyword data
globals
private boolexpr BOOL
private integer COUNT = 0
private data array DATA[MAXHANDLES]
private data array DATASTACK
private group EXPLODE = CreateGroup()
private group GROUP = CreateGroup()
private constant real MODSPEED = SPEED*SPEED
private constant integer RMAX = OMAX+1
private sound SOUND
private unit TARG
private data TEMPD
private timer TIMER = CreateTimer()
endglobals
private function Filt takes nothing returns boolean
local data d=TEMPD
local unit TARG=GetFilterUnit()
local real r
local real rr
if UnitAlive(TARG) and Targets(d.u,TARG) then
set r=Damage(d.lvl,d.time,d.maxtime)
if IsUnitEnemy(TARG,d.p) then
call UnitDamageTarget(d.u,TARG,r,false,false,ATTACK,DAMAGE,null)
else
call SetWidgetLife(TARG,GetWidgetLife(TARG)+r)
endif
endif
return false
endfunction
private struct data
unit u
unit target
unit array orbital[RMAX]
effect array sfx[RMAX]
player p
integer lvl
integer stack
integer mode=0
integer array gotem[RMAX]
integer count
real time=0.
real maxtime
real update
real array degree[RMAX]
real reachmax
real dist
real startscale
boolean max=false
method destroy takes nothing returns nothing
local integer i=1
loop
exitwhen i>.count
if .gotem<i>!=1 then
set TEMPD=this
call GroupEnumUnitsInRange(EXPLODE,GetUnitX(.orbital<i>),GetUnitY(.orbital<i>),Range(.lvl,.time,.maxtime),BOOL)
call DestroyEffect(AddSpecialEffect(SFX,GetUnitX(.orbital<i>),GetUnitY(.orbital<i>)))
call DestroyEffect(.sfx<i>)
call RemoveUnit(.orbital<i>)
endif
set i=i+1
endloop
set DATASTACK[.stack]=DATASTACK[COUNT]
set COUNT=COUNT-1
call GroupRemoveUnit(GROUP,.u)
call UnitRemoveAbility(.u,TARGET)
call SetPlayerAbilityAvailable(.p,ABIL,true)
call .deallocate()
endmethod
endstruct
private function Effects takes nothing returns nothing
local data d
local integer i=1
local integer c=1
local real x
local real y
local real r
local boolean b=true
loop
exitwhen i>COUNT
set d=DATASTACK<i>
if d.time>d.maxtime and d.mode==0 then
set d.mode=1
set d.target=d.u
call UnitRemoveAbility(d.u,TARGET)
call SetPlayerAbilityAvailable(d.p,ABIL,true)
elseif d.mode==0 then
set x=GetUnitX(d.u)
set y=GetUnitY(d.u)
set r=ScaleIncrease(d.lvl,d.time,d.reachmax)
loop
exitwhen c>d.count
if UnitAlive(d.orbital[c]) and d.orbital[c]!=null then
set d.degree[c]=d.degree[c]+d.update
static if CLK then
call SetUnitFacing(d.orbital[c],d.degree[c]+90.)
else
call SetUnitFacing(d.orbital[c],d.degree[c]-90.)
endif
call SetUnitX(d.orbital[c],x+d.dist*Cos(d.degree[c]*bj_DEGTORAD))
call SetUnitY(d.orbital[c],y+d.dist*Sin(d.degree[c]*bj_DEGTORAD))
call SetUnitScale(d.orbital[c],r,r,r)
endif
set c=c+1
endloop
if d.time>=d.reachmax and not d.max then
if GetLocalPlayer()==d.p then
call StartSound(SOUND)
set d.max=true
endif
endif
set d.time=d.time+TIMEOUT
elseif d.mode==1 then
loop
exitwhen c>d.count
if UnitAlive(d.target) and d.target!=null then
if d.gotem[c]!=1 then
set x=GetUnitX(d.orbital[c])
set y=GetUnitY(d.orbital[c])
if Pow(GetUnitX(d.target)-x,2)+Pow(GetUnitY(d.target)-y,2)<=MODSPEED then
set TEMPD=d
call GroupEnumUnitsInRange(EXPLODE,x,y,Range(d.lvl,d.time,d.maxtime),BOOL)
call DestroyEffect(AddSpecialEffect(SFX,x,y))
call DestroyEffect(d.sfx[c])
call RemoveUnit(d.orbital[c])
set d.gotem[c]=1
else
set b=false
set r=Atan2(GetUnitY(d.target)-y,GetUnitX(d.target)-x)
call SetUnitFacing(d.orbital[c],r*bj_RADTODEG)
call SetUnitX(d.orbital[c],x+SPEED*Cos(r))
call SetUnitY(d.orbital[c],y+SPEED*Sin(r))
endif
endif
else
call d.destroy()
set i=i-1
exitwhen true
endif
set c=c+1
endloop
if b then
call d.destroy()
set i=i-1
exitwhen true
endif
endif
set i=i+1
endloop
if COUNT==0 then
call PauseTimer(TIMER)
endif
endfunction
private function Actions takes nothing returns nothing
local data d=data.create()
local real x
local real xu
local real y
local real yu
local integer i=1
set d.u=GetTriggerUnit()
set d.p=GetOwningPlayer(d.u)
set d.lvl=GetUnitAbilityLevel(d.u,ABIL)
set d.update=Update(d.lvl)
set d.maxtime=Time(d.lvl)
set d.reachmax=ReachMax(d.lvl)
set d.count=Orbitals(d.lvl)
set d.dist=Distance(d.lvl)
set d.startscale=StartScale(d.lvl)
set COUNT=COUNT+1
set d.stack=COUNT
if COUNT==1 then
call TimerStart(TIMER,TIMEOUT,true,function Effects)
endif
set DATASTACK[COUNT]=d
call SetPlayerAbilityAvailable(d.p,ABIL,false)
call UnitAddAbility(d.u,TARGET)
call SetPlayerAbilityAvailable(d.p,TARGET,true)
set xu=GetUnitX(d.u)
set yu=GetUnitY(d.u)
loop
exitwhen i>d.count
set d.degree<i>=360.*i/I2R(d.count)
set x=xu+d.dist*Cos(bj_DEGTORAD*d.degree<i>)
set y=yu+d.dist*Sin(bj_DEGTORAD*d.degree<i>)
static if CLK then
set d.orbital<i>=CreateUnit(d.p,CasterId,x,y,d.degree<i>+90.)
else
set d.orbital<i>=CreateUnit(d.p,CasterId,x,y,d.degree<i>-90.)
endif
call SetUnitPathing(d.orbital<i>,false)
call SetUnitScale(d.orbital<i>,d.startscale,d.startscale,d.startscale)
set d.sfx<i>=AddSpecialEffectTarget(MDL,d.orbital<i>,MDLAP)
set d.gotem<i>=0
set i=i+1
endloop
set DATA[GetHandleId(d.u)-OFFSET]=d
call GroupAddUnit(GROUP,d.u)
endfunction
//======================================================================
private function Conditions takes nothing returns boolean
local data d
if GetSpellAbilityId()==ABIL then
call Actions()
elseif GetSpellAbilityId()==TARGET then
set d=DATA[GetHandleId(GetTriggerUnit())-OFFSET]
set d.target=GetSpellTargetUnit()
set d.mode=1
call UnitRemoveAbility(d.u,TARGET)
call SetPlayerAbilityAvailable(d.p,ABIL,true)
elseif IsUnitInGroup(GetTriggerUnit(),GROUP) and GetTriggerEventId()==EVENT_PLAYER_UNIT_DEATH then
set d=DATA[GetHandleId(GetTriggerUnit())-OFFSET]
call d.destroy()
endif
return false
endfunction
private function Init takes nothing returns nothing
local trigger t=CreateTrigger()
local integer i=0
loop
exitwhen i>bj_MAX_PLAYERS
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_DEATH,null)
set i=i+1
endloop
call TriggerAddCondition(t,Condition(function Conditions))
set BOOL=Condition(function Filt)
set SOUND=CreateSound(SND,false,false,true,10,10,"DefaultEAXON")
call SetSoundDuration(SOUND,1579)
call SetSoundChannel(SOUND,0)
static if PRELOAD then
set TARG=CreateUnit(Player(15),DUM,0.,0.,0.)
call UnitAddAbility(TARG,TARGET)
call UnitApplyTimedLife(TARG,'BTLF',.001)
call Preload(MDL)
call Preload(SFX)
endif
endfunction
endscope</i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i></i>
ChangeLog:
Changelog
Boomerang:
v1.02
*Replaced onDestroy method with destroy method
v1.01
*Reorganized initial struct members storage for efficiency (d.a)
*Removed needless GroupClear() call
v1.00
*Initial Release
Orbital
v1.02
*Replaced onDestroy method with destroy method
*Added custom user targeting function
v1.01
*Changed SetUnitState and GetUnitState to SetWidgetLife and GetWidgetLife
*Updated distance calulation check
*Stored orbital[c] coordinates when d.mode==1 and utilized where applicable
*Properly uses ATTACK and DAMAGE configurables
*Removed needless GroupClear() calls
v1.00
*Initial release
Boomerang:
v1.02
*Replaced onDestroy method with destroy method
v1.01
*Reorganized initial struct members storage for efficiency (d.a)
*Removed needless GroupClear() call
v1.00
*Initial Release
Orbital
v1.02
*Replaced onDestroy method with destroy method
*Added custom user targeting function
v1.01
*Changed SetUnitState and GetUnitState to SetWidgetLife and GetWidgetLife
*Updated distance calulation check
*Stored orbital[c] coordinates when d.mode==1 and utilized where applicable
*Properly uses ATTACK and DAMAGE configurables
*Removed needless GroupClear() calls
v1.00
*Initial release
Attachments
-
138.1 KB Views: 578