Procrastination Incarnate
Development Director
Join Date: Feb 2004
Posts: 8,190
|
Anitarf's Olympic Spellpack
|
This was my submission to the Spell Olympics last year, I figure it's about time I submitted it. The pack consists of seven spells, for their descriptions read the documentation included with their code or download the testmap and try them out.
The spells require the following libraries (not every spell requires all of them):
TimerUtils, Table, GroupGet, LineSegments, IsTerrainWalkable, xe, ABuff |
The spells in this pack are:  Illuminate: scope Illuminate initializer Init
globals
private constant integer SPELL_ABILITY = 'A007'
private constant integer BUFF_SPELL = 'A009'
private constant string BUFF_SPELL_ORDER = "faeriefire"
private constant integer BUFF_BUFF = 'B002'
endglobals
private constant function InitialDamage takes integer level returns real
return 0.0
endfunction
private constant function BuffApplyRadius takes integer level returns real
return 100.0+50.0*level
endfunction
private constant function BuffDuration takes integer level returns real
return 30.0
endfunction
private constant function BuffDPS takes integer level returns real
return 1.0+2.0*level
endfunction
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype=DAMAGE_TYPE_UNIVERSAL
set spellDamage.atype=ATTACK_TYPE_NORMAL
set spellDamage.tag=0
set spellDamage.exception=UNIT_TYPE_STRUCTURE
set spellDamage.visibleOnly=true
endfunction
globals
private aBuffType abt
private xecast xec
private xedamage xed
endglobals
private function CreateRefresh takes aBuff eventBuff returns nothing
set xec.owningplayer=GetOwningPlayer(eventBuff.caster)
set xec.level=eventBuff.level
call xec.castOnTarget(eventBuff.target.u)
endfunction
private function Periodic takes aBuff eventBuff returns nothing
call xed.damageTarget(eventBuff.caster, eventBuff.target.u, BuffDPS(eventBuff.level)*ABuff_PERIODIC_EVENT_PERIOD)
endfunction
private function Cleanup takes aBuff eventBuff returns nothing
local integer i=0
loop
exitwhen GetUnitAbilityLevel(eventBuff.target.u, BUFF_BUFF)>0
exitwhen i>5
call TriggerSleepAction(0.0)
set i=i+1
endloop
call UnitRemoveAbility(eventBuff.target.u, BUFF_BUFF)
endfunction
globals
private group tempg = CreateGroup()
private boolexpr tempbx
private unit tempcaster
private integer templevel
endglobals
private function Targets takes nothing returns boolean
local unit u=GetFilterUnit()
if IsUnitInRangeXY(u, GetUnitX(u), GetUnitY(u), BuffApplyRadius(templevel)) and xed.allowedTarget(tempcaster,u) then
call xed.damageTarget(tempcaster, u, InitialDamage(templevel))
call ABuffApply(abt, u, tempcaster, BuffDuration(templevel), templevel, 0 )
endif
set u=null
return false
endfunction
private function SpellEffect takes nothing returns nothing
local unit u
local location l
if GetSpellAbilityId() == SPELL_ABILITY then
set tempcaster=GetTriggerUnit()
set templevel=GetUnitAbilityLevel(tempcaster, SPELL_ABILITY)
set u = GetSpellTargetUnit()
if u == null then
set l = GetSpellTargetLoc()
if GetLocationX(l)==0.0 and GetLocationY(l)==0.0 then
call GroupEnumUnitsInRange(tempg,GetUnitX(tempcaster),GetUnitY(tempcaster),BuffApplyRadius(templevel)+XE_MAX_COLLISION_SIZE,tempbx)
else
call GroupEnumUnitsInRange(tempg,GetLocationX(l),GetLocationY(l),BuffApplyRadius(templevel)+XE_MAX_COLLISION_SIZE,tempbx)
endif
call RemoveLocation(l)
set l = null
else
call GroupEnumUnitsInRange(tempg,GetUnitX(u),GetUnitY(u),BuffApplyRadius(templevel)+XE_MAX_COLLISION_SIZE,tempbx)
set u = null
endif
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set tempbx=Condition(function Targets)
set xec=xecast.create()
set xec.abilityid=BUFF_SPELL
set xec.orderstring=BUFF_SPELL_ORDER
set xed=xedamage.create()
call DamageOptions(xed)
call XE_PreloadAbility(BUFF_SPELL)
set abt=aBuffType.create()
set abt.eventCreate = ABuffEvent_Create.CreateRefresh
set abt.eventRefresh = ABuffEvent_Refresh.CreateRefresh
set abt.eventCleanup = ABuffEvent_Cleanup.Cleanup
set abt.eventPeriodic = ABuffEvent_Periodic.Periodic
endfunction
endscope  Glacial Wall: scope GlacialWall initializer Init
globals
private constant integer SPELL_ABILITY = 'A004'
private constant real SPELL_PERIOD = 0.5
private constant integer CHAOS_ABILITY = 'S000'
private constant integer BUFF_ABILITY = 'A005'
private constant integer BUFF_BUFF = 'Bfro'
private constant real WALL_UNIT_MAX_OFFSET = 48.0
private constant boolean WALL_UNIT_RANDOM_FACING = true
private constant real WALL_UNIT_FACING = 0.0
endglobals
private constant function WallDuration takes integer level returns real
return 3.0+3.0*level
endfunction
private constant function WallLength takes integer level returns real
return 250.0+level*250.0
endfunction
private constant function WallUnitInterval takes integer level returns real
return 0.1
endfunction
private constant function WallUnitCount takes integer level returns integer
return 5+4*level
endfunction
private function BuffTargets takes unit inRange, player wallOwner returns boolean
return not(IsUnitType(inRange, UNIT_TYPE_FLYING)) and IsUnitEnemy(inRange, wallOwner) and GetWidgetLife(inRange)>0.405
endfunction
private constant function BuffApplyRadius takes integer level returns real
return 128.0
endfunction
private constant function BuffDuration takes integer level returns real
return 3.0
endfunction
private keyword instance
globals
private aBuffType abt
private timer slow
private instance array instances
private integer instanceCount = 0
private group tempg = CreateGroup()
private boolexpr tempbx
private instance tempsi
endglobals
private function Targets takes nothing returns boolean
return BuffTargets(GetFilterUnit(), tempsi.owner)
endfunction
private function Periodic takes nothing returns nothing
local integer i=0
local real r
local unit u
loop
exitwhen i>=instanceCount
set tempsi = instances[i]
set r = tempsi.segments/2.0
call GroupEnumUnitsInRangeOfSeg(tempg, tempsi.x-tempsi.dx*r,tempsi.y-tempsi.dy*r, tempsi.x+tempsi.dx*r,tempsi.y+tempsi.dy*r, BuffApplyRadius(tempsi.level), tempbx)
loop
set u=FirstOfGroup(tempg)
exitwhen u==null
call ABuffApply(abt, u, tempsi.caster, BuffDuration(tempsi.level), tempsi.level, 0 )
call GroupRemoveUnit(tempg, u)
endloop
set i=i+1
endloop
endfunction
private function Create takes aBuff eventBuff returns nothing
call UnitAddAbility(eventBuff.target.u, BUFF_ABILITY)
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
call UnitMakeAbilityPermanent(eventBuff.target.u, true, BUFF_ABILITY)
endfunction
private function Refresh takes aBuff eventBuff returns nothing
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
endfunction
private function Cleanup takes aBuff eventBuff returns nothing
call UnitRemoveAbility(eventBuff.target.u, BUFF_ABILITY)
call UnitRemoveAbility(eventBuff.target.u, BUFF_BUFF)
endfunction
private function SpellExpire takes nothing returns nothing
local instance si = instance(GetTimerData(GetExpiredTimer()))
call si.destroy()
endfunction
private function SpawnUnit takes instance si, real facing, integer side returns nothing
local real offset=GetRandomReal(-WALL_UNIT_MAX_OFFSET, WALL_UNIT_MAX_OFFSET)
local real x=si.x+si.dx*si.segments/2.0*side+Cos(si.angle)*offset
local real y=si.y+si.dy*si.segments/2.0*side+Sin(si.angle)*offset
local unit u
if WALL_UNIT_RANDOM_FACING then
set facing=GetRandomReal(0,360)
endif
set u=CreateUnit(si.owner, XE_DUMMY_UNITID, x, y, facing)
call UnitAddAbility(u, CHAOS_ABILITY)
call UnitAddAbility(u, 'Aloc')
call IssueImmediateOrder(u, "holdposition")
call SetUnitX(u, x)
call SetUnitY(u, y)
call GroupAddUnit(si.wallunits, u)
set u = null
endfunction
private function SpawnSegment takes nothing returns nothing
local instance si = instance(GetTimerData(GetExpiredTimer()))
local real facing = si.angle*bj_RADTODEG+WALL_UNIT_FACING
call SpawnUnit(si, facing, 1)
if si.segments!=0 then
call SpawnUnit(si, facing, -1)
endif
if si.segments>=WallUnitCount(si.level)-1 then
call TimerStart(si.t, WallDuration(si.level)-((si.segments/2)*WallUnitInterval(si.level)), false, function SpellExpire)
else
set si.segments=si.segments+2
call TimerStart(si.t, WallUnitInterval(si.level), false, function SpawnSegment)
endif
endfunction
private function DestroyWallEnum takes nothing returns nothing
local unit u = GetEnumUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
call KillUnit(u)
call SetUnitX(u, x)
call SetUnitY(u, y)
set u= null
endfunction
private struct instance
private integer index
real x
real y
real dx
real dy
real angle
integer segments=0
unit caster
player owner
integer level
timer t
group wallunits
static method create takes unit caster, integer level, real targetx, real targety returns instance
local instance si=instance.allocate()
local real length=WallLength(level)
local real count=WallUnitCount(level)
set si.angle=Atan2(targety-GetUnitY(caster), targetx-GetUnitX(caster))
set si.caster=caster
set si.owner=GetOwningPlayer(caster)
set si.level=level
set si.x=targetx
set si.y=targety
set si.dx=Sin(si.angle)*length/(count-1)
set si.dy=-Cos(si.angle)*length/(count-1)
if count/2==count/2.0 then
set si.segments=1
endif
if si.wallunits==null then
set si.wallunits=CreateGroup()
endif
set si.t=NewTimer()
call SetTimerData(si.t, integer(si))
call TimerStart(si.t, 0.0, false, function SpawnSegment)
if instanceCount==0 then
set slow=NewTimer()
call TimerStart(slow, SPELL_PERIOD, true, function Periodic)
endif
set instances[instanceCount]=si
set si.index=instanceCount
set instanceCount=instanceCount+1
return si
endmethod
method onDestroy takes nothing returns nothing
set instanceCount=instanceCount-1
set instances[this.index]=instances[instanceCount]
set instances[instanceCount].index=this.index
call ForGroup(this.wallunits, function DestroyWallEnum)
call GroupClear(this.wallunits)
call ReleaseTimer(this.t)
if instanceCount==0 then
call ReleaseTimer(slow)
endif
endmethod
endstruct
private function SpellEffect takes nothing returns nothing
local integer lvl
local location l
if GetSpellAbilityId() == SPELL_ABILITY then
set lvl =GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ABILITY)
set l = GetSpellTargetLoc()
call instance.create(GetTriggerUnit(), lvl, GetLocationX(l), GetLocationY(l))
call RemoveLocation(l)
set l = null
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set tempbx=Condition(function Targets)
call XE_PreloadAbility(BUFF_ABILITY)
call XE_PreloadAbility(CHAOS_ABILITY)
set abt=aBuffType.create()
set abt.ignoreAsBuff = true
set abt.eventCreate = ABuffEvent_Create.Create
set abt.eventRefresh = ABuffEvent_Refresh.Refresh
set abt.eventCleanup = ABuffEvent_Cleanup.Cleanup
endfunction
endscope  Lightning Blast: scope LightningBlast initializer Init
globals
private constant integer SPELL_ABILITY = 'A006'
private constant integer MAX_TARGETS = 7
private constant string LIGHTNING_TYPE = "CHIM"
private constant real LIGHTNING_DURATION = 0.25
private constant real MAX_START_OFFSET = 256.0
private constant real MAX_NODE_OFFSET = 128.0
private constant real START_HEIGHT = 1024.0
private constant real FORK_HEIGHT_FACTOR = 0.55
private constant integer MAX_FORK_TARGETCOUNT_DIFFERENCE = 2
endglobals
private constant function TargetRadius takes integer level returns real
return 512.0
endfunction
private constant function TargetMaxCount takes integer level returns integer
return level*2+1
endfunction
private constant function Damage takes integer level returns real
return 50.0+25.0*level
endfunction
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype=DAMAGE_TYPE_UNIVERSAL
set spellDamage.atype=ATTACK_TYPE_NORMAL
set spellDamage.tag=0
set spellDamage.exception=UNIT_TYPE_STRUCTURE
call spellDamage.useSpecialEffect(GetAbilityEffectById(SPELL_ABILITY, EFFECT_TYPE_TARGET, 0), "origin")
endfunction
private keyword instance
globals
private xedamage xed
endglobals
private struct node
private node parent=0
private node childA=0
private node childB=0
private real x=0.0
private real y=0.0
private real h=0.0
private lightning light
static method create takes instance si, node parent, integer start, integer end, real height returns node
local node n=node.allocate()
local integer i=start
set n.parent=parent
loop
set n.x=n.x+GetUnitX(si.targets[i])
set n.y=n.y+GetUnitY(si.targets[i])
exitwhen i==end
set i=i+1
endloop
set n.x=n.x/(end-start+1)
set n.y=n.y/(end-start+1)
if start!=end then
set n.h=height*FORK_HEIGHT_FACTOR
set n.x=n.x+(si.startx-si.hitx)*n.h/si.starth
set n.y=n.y+(si.starty-si.hity)*n.h/si.starth
set n.h=n.h+GetRandomReal(-MAX_NODE_OFFSET, MAX_NODE_OFFSET)*n.h/si.starth
set n.x=n.x+GetRandomReal(-MAX_NODE_OFFSET, MAX_NODE_OFFSET)*n.h/si.starth
set n.y=n.y+GetRandomReal(-MAX_NODE_OFFSET, MAX_NODE_OFFSET)*n.h/si.starth
if MAX_FORK_TARGETCOUNT_DIFFERENCE>=(end-start+1-2) then
set i=GetRandomInt(start, end-1)
else
set i=(end-start+1-2-MAX_FORK_TARGETCOUNT_DIFFERENCE)
set i=GetRandomInt(start+(i/2), end-1-(i/2))
endif
set n.childA=node.create(si,n, start,i, n.h )
set n.childB=node.create(si,n, i+1,end, n.h )
else
set n.h=0
call xed.damageTarget(si.caster, si.targets[start], Damage(si.level))
endif
if parent==0 then
set n.light=AddLightningEx(LIGHTNING_TYPE, false, si.startx,si.starty,si.starth, n.x,n.y,n.h)
else
set n.light=AddLightningEx(LIGHTNING_TYPE, false, parent.x,parent.y,parent.h, n.x,n.y,n.h)
endif
return n
endmethod
method onDestroy takes nothing returns nothing
if .childA!=0 then
call .childA.destroy()
call .childB.destroy()
endif
call DestroyLightning(.light)
endmethod
endstruct
globals
private group tempg = CreateGroup()
private boolexpr tempbx
private instance tempsi
private GroupGet_Distance distance
endglobals
private function Targets takes nothing returns boolean
local unit u=GetFilterUnit()
if xed.allowedTarget(tempsi.caster,u) and IsUnitInRangeXY(u, tempsi.hitx, tempsi.hity, TargetRadius(tempsi.level)) then
set u=null
return true
endif
set u=null
return false
endfunction
private function EndLightning takes nothing returns nothing
call instance(GetTimerData(GetExpiredTimer())).destroy()
endfunction
private struct instance
unit array targets[MAX_TARGETS]
real hitx=0.0
real hity=0.0
real startx=0.0
real starty=0.0
real starth=0.0
node first
integer level
unit caster
timer t
static method create takes unit caster, integer level, unit target returns instance
local instance si = instance.allocate()
local integer i = 0
set si.hitx=GetUnitX(target)
set si.hity=GetUnitY(target)
set si.level=level
set si.caster=caster
set tempsi=si
set si.startx=si.hitx+GetRandomReal(-MAX_START_OFFSET,MAX_START_OFFSET)
set si.starty=si.hity+GetRandomReal(-MAX_START_OFFSET,MAX_START_OFFSET)
set si.starth=START_HEIGHT
call GroupEnumUnitsInRange(tempg,GetUnitX(target),GetUnitY(target),TargetRadius(level) + XE_MAX_COLLISION_SIZE , tempbx)
call GroupRemoveUnit(tempg, target)
set bj_groupCountUnits = 0
call ForGroup(tempg, function CountUnitsInGroupEnum)
loop
exitwhen bj_groupCountUnits<TargetMaxCount(level)
set bj_groupRandomConsidered = 0
set bj_groupRandomCurrentPick = null
call ForGroup(tempg, function GroupPickRandomUnitEnum)
call GroupRemoveUnit(tempg, bj_groupRandomCurrentPick)
set bj_groupCountUnits=bj_groupCountUnits-1
endloop
call GroupAddUnit(tempg, target)
set distance.x=GetUnitX(target)
set distance.y=GetUnitY(target)
set si.targets[0]=GroupGetHighestEx(tempg, distance)
loop
exitwhen i>=bj_groupCountUnits
call GroupRemoveUnit(tempg, si.targets[i])
set distance.x=GetUnitX(si.targets[i])
set distance.y=GetUnitY(si.targets[i])
set i=i+1
set si.targets[i]=GroupGetLowestEx(tempg, distance)
endloop
set si.first=node.create(si, 0, 0,bj_groupCountUnits, si.starth)
set si.t=NewTimer()
call SetTimerData(si.t, integer(si))
call TimerStart(si.t, LIGHTNING_DURATION, false, function EndLightning)
return si
endmethod
method onDestroy takes nothing returns nothing
call ReleaseTimer(.t)
call .first.destroy()
set .first=0
endmethod
endstruct
private function SpellEffect takes nothing returns nothing
local integer lvl
local unit u
if GetSpellAbilityId() == SPELL_ABILITY then
set lvl =GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ABILITY)
set u = GetSpellTargetUnit()
call instance.create(GetTriggerUnit(), lvl, u)
set u = null
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set distance=GroupGet_Distance.create()
set tempbx=Condition(function Targets)
set xed=xedamage.create()
call DamageOptions(xed)
endfunction
endscope  Thornwine Armour: scope ThornwineArmour initializer Init
globals
private constant integer SPELL_ABILITY = 'A001'
private constant integer BUFF_ABILITY = 'A002'
private constant integer BUFF_BUFF = 'B000'
private constant integer DAMAGE_SHIELD_PRIORITY = 5
private constant string EFFECT = "Objects\\Spawnmodels\\NightElf\\EntBirthTarget\\EntBirthTarget.mdl"
private constant real EFFECT_PERIOD_MINLIFE = 0.8
private constant real EFFECT_PERIOD_MAXLIFE = 0.2
private constant real EFFECT_MAXLIFE = 500.0
endglobals
private constant function ShieldStartLife takes integer level returns real
return 100.0
endfunction
private constant function ShieldMaxLife takes integer level returns real
return 200.0 + 100.0*level
endfunction
private constant function ShieldRegeneration takes integer level returns real
return 1.0+3.0*level
endfunction
private constant function ShieldRefreshLife takes integer level, real remainingLife returns real
return remainingLife+ShieldStartLife(level)
endfunction
private constant function ShieldDuration takes integer level returns real
return 0.0
endfunction
private constant function DamagePrevented takes integer level, real damage, real shieldLife returns real
return 20.0
endfunction
private constant function ReturnDamage takes boolean triggered, integer tag returns boolean
return not(triggered)
endfunction
private constant function DamageReturned takes integer level, real shieldLife, real prevented returns real
return shieldLife*0.1
endfunction
private function DamageOptions takes xedamage returnedDamage returns nothing
set returnedDamage.dtype=DAMAGE_TYPE_UNIVERSAL
set returnedDamage.atype=ATTACK_TYPE_NORMAL
set returnedDamage.tag=0
set returnedDamage.damageAllies=true
set returnedDamage.required=UNIT_TYPE_MELEE_ATTACKER
endfunction
private keyword shd
private function TimedEffect takes nothing returns nothing
local shd s = shd(GetTimerData(GetExpiredTimer()))
local real r = s.shdlife/EFFECT_MAXLIFE
if r>1.0 then
set r=1.0
endif
set r=EFFECT_PERIOD_MINLIFE/((EFFECT_PERIOD_MINLIFE/EFFECT_PERIOD_MAXLIFE)*r + 1*(1-r))
call DestroyEffect( AddSpecialEffectTarget(EFFECT, s.u, "origin"))
call TimerStart(s.t, r, false, function TimedEffect)
endfunction
private struct shd extends ADamage_shield
timer t
unit u
integer level=0
real shdlife=0
real prevented=0
static method create takes unit u, integer level returns shd
local shd s = shd.allocate(u, DAMAGE_SHIELD_PRIORITY)
set s.shdlife=ShieldStartLife(level)
set s.level = level
set s.u=u
set s.t=NewTimer()
call SetTimerData(s.t, integer(s))
call TimerStart(s.t, 0.0, false, function TimedEffect)
return s
endmethod
method refresh takes integer level returns nothing
set .level=level
set .shdlife=ShieldRefreshLife(level, .shdlife)
if .shdlife>ShieldMaxLife(level) then
set .shdlife=ShieldMaxLife(level)
endif
endmethod
method regen takes integer level returns nothing
set .shdlife=.shdlife+ShieldRegeneration(level)*ABuff_PERIODIC_EVENT_PERIOD
if .shdlife>ShieldMaxLife(level) then
set .shdlife=ShieldMaxLife(level)
endif
endmethod
method damaged takes unit damageSource, real damage returns real
set .prevented = DamagePrevented(.level, damage, .shdlife)
if .prevented > damage then
set .prevented = damage
endif
if .prevented > .shdlife then
set .prevented = .shdlife
endif
set .shdlife=.shdlife-.prevented
return .prevented
endmethod
method onDestroy takes nothing returns nothing
call PauseTimer(.t)
call ReleaseTimer(this.t)
endmethod
endstruct
globals
private xedamage xed
endglobals
private struct damageUnit
unit target
unit source
real damage
endstruct
private function DelayedDamage takes nothing returns nothing
local damageUnit d = damageUnit(GetTimerData(GetExpiredTimer()))
call ReleaseTimer(GetExpiredTimer())
call xed.damageTarget(d.source, d.target, d.damage)
call d.destroy()
endfunction
globals
private aBuffType abt
endglobals
private function Create takes aBuff eventBuff returns nothing
set eventBuff.data=integer(shd.create(eventBuff.target.u, eventBuff.level))
call UnitAddAbility(eventBuff.target.u, BUFF_ABILITY)
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
call UnitMakeAbilityPermanent(eventBuff.target.u, true, BUFF_ABILITY)
endfunction
private function Refresh takes aBuff eventBuff returns nothing
set eventBuff.data=eventBuff.olddata
call shd(eventBuff.data).refresh(eventBuff.level)
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
endfunction
private function Cleanup takes aBuff eventBuff returns nothing
call shd(eventBuff.data).destroy()
call UnitRemoveAbility(eventBuff.target.u, BUFF_ABILITY)
call UnitRemoveAbility(eventBuff.target.u, BUFF_BUFF)
endfunction
private function Periodic takes aBuff eventBuff returns nothing
call shd(eventBuff.data).regen(eventBuff.level)
endfunction
private function Damaged takes aBuff eventBuff, real damage, unit damageSource returns nothing
local shd s = shd(eventBuff.data)
local damageUnit d
local timer t
if s.prevented>0.0 and xed.allowedTarget(eventBuff.target.u, damageSource) and ReturnDamage(xedamage.isInUse(), xedamage.CurrentDamageTag) then
set t = NewTimer()
set d = damageUnit.create()
set d.damage = DamageReturned(eventBuff.level, s.shdlife+s.prevented, s.prevented)
set d.target = damageSource
set d.source = s.u
call SetTimerData(t, integer(d))
call TimerStart(t, 0.0, false, function DelayedDamage)
endif
if s.shdlife<=0.0 then
call ABuffDestroy(eventBuff)
endif
endfunction
private function SpellEffect takes nothing returns nothing
local integer lvl
if GetSpellAbilityId() == SPELL_ABILITY then
set lvl = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ABILITY)
call ABuffApply(abt, GetSpellTargetUnit(), GetTriggerUnit(), ShieldDuration(lvl), lvl, 0 )
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set xed=xedamage.create()
call DamageOptions(xed)
call XE_PreloadAbility(BUFF_ABILITY)
set abt=aBuffType.create()
set abt.ignoreAsBuff = true
set abt.eventCreate = ABuffEvent_Create.Create
set abt.eventRefresh = ABuffEvent_Refresh.Refresh
set abt.eventCleanup = ABuffEvent_Cleanup.Cleanup
set abt.eventPeriodic = ABuffEvent_Periodic.Periodic
set abt.eventDamaged = ABuffEvent_BUnitDamaged.Damaged
endfunction
endscope  Razor Gale: scope RazorGale initializer Init
globals
private constant integer SPELL_ABILITY = 'A003'
private constant real SPELL_PERIOD = XE_ANIMATION_PERIOD
private constant integer DAMAGE_PERIOD_FACTOR = 3
private constant real ANIM_SPEED_START = 1.2
private constant real ANIM_SPEED_END = 0.9
private constant boolean DISABLE_SPELL_SOUND = true
endglobals
private constant function GlideSpeed takes integer level returns real
return 750.0
endfunction
private constant function GlideMaxDistance takes integer level returns real
return 1000.0
endfunction
private constant function GlideMinDistance takes integer level returns real
return 1000.0
endfunction
private constant function Damage takes integer level returns real
return 50.0+50.0*level
endfunction
private constant function DamageRadius takes integer level returns real
return 128.0
endfunction
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype=DAMAGE_TYPE_UNIVERSAL
set spellDamage.atype=ATTACK_TYPE_NORMAL
set spellDamage.tag=0
set spellDamage.exception=UNIT_TYPE_STRUCTURE
endfunction
private keyword instance
globals
private xedamage xed
private timer slide
private instance array instances
private integer instanceCount = 0
private group tempg = CreateGroup()
private boolexpr tempbx
private real tempx
private real tempy
private instance tempsi
endglobals
private function Targets takes nothing returns boolean
local unit u=GetFilterUnit()
if not(IsUnitInGroup(u, tempsi.affected)) and IsUnitInRangeXY(u, tempx, tempy, DamageRadius(tempsi.level)) then
call GroupAddUnit(tempsi.affected, u)
set u=null
return true
endif
set u=null
return false
endfunction
private function Periodic takes nothing returns nothing
local integer i=0
loop
exitwhen i>=instanceCount
set tempsi = instances[i]
set tempx = GetUnitX(tempsi.caster)+tempsi.dx
set tempy = GetUnitY(tempsi.caster)+tempsi.dy
set tempsi.time=tempsi.time-SPELL_PERIOD
if tempsi.time>0.0 and IsTerrainWalkable(tempx,tempy) then
call SetUnitX(tempsi.caster, tempx)
call SetUnitY(tempsi.caster, tempy)
if tempsi.whenToDamage <= 0 then
set tempsi.whenToDamage=DAMAGE_PERIOD_FACTOR
call GroupEnumUnitsInRange(tempg,tempx,tempy,DamageRadius(tempsi.level) + XE_MAX_COLLISION_SIZE , tempbx)
call xed.damageGroup(tempsi.caster, tempg, Damage(tempsi.level))
endif
set tempsi.whenToDamage=tempsi.whenToDamage-1
set i=i+1
else
call tempsi.finish()
endif
endloop
endfunction
private function Animation_Finish takes nothing returns nothing
local instance si=instance(GetTimerData(GetExpiredTimer()))
call SetUnitTimeScale(si.caster, 1.0)
call si.destroy()
endfunction
private function Animation_Child takes nothing returns nothing
local instance si=instance(GetTimerData(GetExpiredTimer()))
call SetUnitFlyHeight(si.caster, 0.0, 48.0/0.125*si.timescale)
call ReleaseTimer(GetExpiredTimer())
endfunction
private function Animation takes nothing returns nothing
local instance si=instance(GetTimerData(GetExpiredTimer()))
local timer t
if si.active then
set t = NewTimer()
call SetTimerData(t, integer(si))
call SetUnitTimeScale(si.caster, si.timescale)
call SetUnitAnimationByIndex(si.caster, 6)
call SetUnitFlyHeight(si.caster, 48.0, 48.0/0.125*si.timescale)
call TimerStart(t, 0.125/si.timescale, false, function Animation_Child)
call TimerStart(GetExpiredTimer(), 0.35/si.timescale, false, function Animation)
set si.timescale=si.timescale+si.dtimescale*0.35/si.timescale
else
call SetUnitTimeScale(si.caster, 1.5)
call TimerStart(GetExpiredTimer(), 0.45, false, function Animation_Finish)
endif
endfunction
private struct instance
private integer index
private timer t
real timescale
real dtimescale
boolean active = true
boolean interrupted = false
integer whenToDamage = DAMAGE_PERIOD_FACTOR
unit caster
integer level
real dx
real dy
group affected
real time
static method create takes unit caster, integer level, real targetx, real targety returns instance
local instance si=instance.allocate()
local real distance
local real factor=1.0
call UnitAddAbility(caster, XE_HEIGHT_ENABLER)
call UnitRemoveAbility(caster, XE_HEIGHT_ENABLER)
set si.caster=caster
set si.level=level
set si.dx=targetx-GetUnitX(caster)
set si.dy=targety-GetUnitY(caster)
set distance = SquareRoot(si.dx*si.dx+si.dy*si.dy)+1.0
if distance>GlideMaxDistance(level) then
set factor = GlideMaxDistance(level)/distance
elseif distance<GlideMinDistance(level) then
set factor = GlideMinDistance(level)/distance
endif
set si.time = factor*distance/GlideSpeed(level)
set factor = factor/si.time*SPELL_PERIOD
set si.dx=si.dx*factor
set si.dy=si.dy*factor
set si.timescale=ANIM_SPEED_START
set si.dtimescale=(ANIM_SPEED_END-ANIM_SPEED_START)/(GlideMaxDistance(level)/GlideSpeed(level))
if si.affected == null then
set si.affected=CreateGroup()
endif
set si.t=NewTimer()
call SetTimerData(si.t, integer(si))
call TimerStart(si.t, 0.0, false, function Animation)
if DISABLE_SPELL_SOUND then
call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_SPELLS, 0.0)
endif
if instanceCount==0 then
set slide=NewTimer()
call TimerStart(slide, SPELL_PERIOD, true, function Periodic)
endif
set instances[instanceCount]=si
set si.index=instanceCount
set instanceCount=instanceCount+1
return si
endmethod
static method get takes unit u returns instance
local integer i=0
loop
exitwhen i==instanceCount
if instances[i].caster==u then
return instances[i]
endif
set i=i+1
endloop
return 0
endmethod
method finish takes nothing returns nothing
set this.active=false
set instanceCount=instanceCount-1
set instances[this.index]=instances[instanceCount]
set instances[instanceCount].index=this.index
if instanceCount==0 then
call ReleaseTimer(slide)
if DISABLE_SPELL_SOUND then
call VolumeGroupReset()
endif
endif
endmethod
method onDestroy takes nothing returns nothing
if not(this.interrupted) then
call IssueImmediateOrder(this.caster, "stop")
endif
call ReleaseTimer(this.t)
call GroupClear(this.affected)
endmethod
endstruct
private function SpellEffect takes nothing returns nothing
local integer lvl
local unit u
local location l
if GetSpellAbilityId() == SPELL_ABILITY then
set lvl =GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ABILITY)
set u = GetSpellTargetUnit()
if u == null then
set l = GetSpellTargetLoc()
call instance.create(GetTriggerUnit(), lvl, GetLocationX(l), GetLocationY(l))
call RemoveLocation(l)
set l = null
else
call instance.create(GetTriggerUnit(), lvl, GetUnitX(u), GetUnitY(u))
set u = null
endif
endif
endfunction
private function SpellStop takes nothing returns nothing
local instance si
if GetSpellAbilityId() == SPELL_ABILITY then
set si = instance.get(GetTriggerUnit())
if si != 0 then
call si.finish()
set si.interrupted=true
endif
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
call TriggerAddAction( tr, function SpellStop )
set tempbx=Condition(function Targets)
set xed=xedamage.create()
call DamageOptions(xed)
endfunction
endscope  Lurking Shadow: scope LurkingShadow initializer Init
globals
private constant integer SPELL_ABILITY = 'A00A'
private constant integer BUFF_ABILITY = 'A008'
private constant integer BUFF_BUFF = 'B001'
private constant boolean DAMAGE_WHEN_CASTING = true
private constant boolean DAMAGE_WHEN_TARGETED = true
private constant string DAMAGE_EFFECT_MAIN = "Abilities\\Spells\\Undead\\OrbOfDeath\\OrbOfDeathMissile.mdl"
private constant string DAMAGE_EFFECT_MAIN_AP = "origin"
private constant string DAMAGE_EFFECT_UNIT = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"
private constant string DAMAGE_EFFECT_UNIT_AP = "origin"
endglobals
private constant function BuffDuration takes integer level returns real
return 30.0
endfunction
private constant function Damage takes integer level returns real
return 25.0+25.0*level
endfunction
private constant function DamageRadius takes integer level returns real
return 100.0+50.0*level
endfunction
private function DamageOptions takes xedamage spellDamage returns nothing
set spellDamage.dtype=DAMAGE_TYPE_UNIVERSAL
set spellDamage.atype=ATTACK_TYPE_NORMAL
set spellDamage.tag=0
set spellDamage.exception=UNIT_TYPE_STRUCTURE
endfunction
globals
private aBuffType abt
private xedamage xed
endglobals
private function Create takes aBuff eventBuff returns nothing
call UnitAddAbility(eventBuff.target.u, BUFF_ABILITY)
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
call UnitMakeAbilityPermanent(eventBuff.target.u, true, BUFF_ABILITY)
endfunction
private function Refresh takes aBuff eventBuff returns nothing
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
endfunction
private function Cleanup takes aBuff eventBuff returns nothing
call UnitRemoveAbility(eventBuff.target.u, BUFF_ABILITY)
call UnitRemoveAbility(eventBuff.target.u, BUFF_BUFF)
endfunction
private function SpellCast takes aBuff eventBuff, integer spellId, unit target returns nothing
call DestroyEffect(AddSpecialEffectTarget(DAMAGE_EFFECT_MAIN, eventBuff.target.u, DAMAGE_EFFECT_MAIN_AP))
call xed.damageAOE(eventBuff.caster, GetUnitX(eventBuff.target.u),GetUnitY(eventBuff.target.u),DamageRadius(eventBuff.level),Damage(eventBuff.level) )
endfunction
private function SpellTargeted takes aBuff eventBuff, integer spellId, unit caster returns nothing
call DestroyEffect(AddSpecialEffectTarget(DAMAGE_EFFECT_MAIN, eventBuff.target.u, DAMAGE_EFFECT_MAIN_AP))
call xed.damageAOE(eventBuff.caster, GetUnitX(eventBuff.target.u),GetUnitY(eventBuff.target.u),DamageRadius(eventBuff.level),Damage(eventBuff.level) )
endfunction
private function SpellEffect takes nothing returns nothing
local integer lvl
if GetSpellAbilityId() == SPELL_ABILITY then
set lvl = GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ABILITY)
call ABuffApply(abt, GetSpellTargetUnit(), GetTriggerUnit(), BuffDuration(lvl), lvl, 0 )
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set xed=xedamage.create()
call DamageOptions(xed)
call xed.useSpecialEffect(DAMAGE_EFFECT_UNIT,DAMAGE_EFFECT_UNIT_AP)
call XE_PreloadAbility(BUFF_ABILITY)
set abt=aBuffType.create()
set abt.eventCreate = ABuffEvent_Create.Create
set abt.eventRefresh = ABuffEvent_Refresh.Refresh
set abt.eventCleanup = ABuffEvent_Cleanup.Cleanup
if DAMAGE_WHEN_CASTING then
set abt.eventSpellCast = ABuffEvent_BUnitSpellCast.SpellCast
endif
if DAMAGE_WHEN_TARGETED then
set abt.eventSpellTargeted = ABuffEvent_BUnitSpellTargeted.SpellTargeted
endif
endfunction
endscope  Sacred Ground: scope SacredGround initializer Init
globals
private constant integer SPELL_ABILITY = 'A000'
private constant integer BUFF_ABILITY = 'A00C'
private constant integer BUFF_BUFF = 'B003'
private constant integer DAMAGE_SHIELD_PRIORITY = 10
private constant integer ANIM_ID = 3
private constant real ANIM_SPEED_START = 1.25
private constant real ANIM_DURATION_START = 2.0
private constant real ANIM_SPEED_LOOP = 0.25
private constant real ANIM_DURATION_LOOP = 0.75
private constant real ANIM_SPEED_END = 2.25
private constant real ANIM_DURATION_END = 1.0
endglobals
private constant function SpellDuration takes integer level returns real
return 10.0
endfunction
private constant function DamagePreventedFactor takes integer level returns real
return 0.05+0.15*level
endfunction
private constant function PreventedToManaFactor takes integer level returns real
return 0.5
endfunction
private constant function AuraRange takes integer level returns real
return 500.0
endfunction
private function AuraTargets takes unit affected, unit auraGiver returns boolean
return IsUnitAlly(affected, GetOwningPlayer(auraGiver))
endfunction
private struct shd extends ADamage_shield
integer level
real prevented
static method create takes unit u, integer level returns shd
local shd s = shd.allocate(u, DAMAGE_SHIELD_PRIORITY)
set s.level = level
return s
endmethod
method damaged takes unit damageSource, real damage returns real
set .prevented = damage*DamagePreventedFactor(.level)
return .prevented
endmethod
endstruct
globals
private aBuffType abt
endglobals
private function Create takes aBuff eventBuff returns nothing
set eventBuff.data=shd.create(eventBuff.target.u, eventBuff.level)
call UnitAddAbility(eventBuff.target.u, BUFF_ABILITY)
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
call UnitMakeAbilityPermanent(eventBuff.target.u, true, BUFF_ABILITY)
endfunction
private function Refresh takes aBuff eventBuff returns nothing
set eventBuff.data=eventBuff.olddata
set shd(eventBuff.data).level=eventBuff.level
call SetUnitAbilityLevel(eventBuff.target.u, BUFF_ABILITY, eventBuff.level)
endfunction
private function Cleanup takes aBuff eventBuff returns nothing
call shd(eventBuff.data).destroy()
call UnitRemoveAbility(eventBuff.target.u, BUFF_ABILITY)
call UnitRemoveAbility(eventBuff.target.u, BUFF_BUFF)
endfunction
private function Damaged takes aBuff eventBuff, real damage, unit damageSource returns nothing
local real restore = shd(eventBuff.data).prevented*PreventedToManaFactor(eventBuff.level)
call SetUnitState(eventBuff.target.u, UNIT_STATE_MANA, GetUnitState(eventBuff.target.u, UNIT_STATE_MANA)+restore)
endfunction
private keyword instance
globals
private instance array instances
private integer instanceCount = 0
endglobals
private function Animation_Finish takes nothing returns nothing
local instance si = GetTimerData(GetExpiredTimer())
call si.destroy()
endfunction
private function Animation takes nothing returns nothing
local instance si = GetTimerData(GetExpiredTimer())
set si.time=si.time-ANIM_DURATION_LOOP
if si.time>ANIM_DURATION_END then
call SetUnitTimeScale(si.caster, si.timescale)
set si.timescale=-si.timescale
call TimerStart(GetExpiredTimer(), ANIM_DURATION_LOOP, false, function Animation)
else
set si.time=si.time+ANIM_DURATION_LOOP
call SetUnitTimeScale(si.caster, ANIM_SPEED_END*(ANIM_DURATION_END/si.time))
call TimerStart(GetExpiredTimer(), si.time, false, function Animation_Finish)
endif
endfunction
private struct instance
private integer index
private timer t
boolean interrupted = false
unit caster
integer level
real time
real timescale
static method create takes unit caster, integer level returns instance
local instance si=instance.allocate()
set si.caster=caster
set si.level=level
set si.time=SpellDuration(level)-ANIM_DURATION_START
set si.timescale=ANIM_SPEED_LOOP
set si.t=NewTimer()
call SetTimerData(si.t, integer(si))
call SetUnitTimeScale(caster, ANIM_SPEED_START)
call SetUnitAnimationByIndex(caster, ANIM_ID)
call TimerStart(si.t, ANIM_DURATION_START, false, function Animation)
call UnitSetABuffAura(caster, abt, level, ABuffAuraTargets.AuraTargets, AuraRange(level))
set instances[instanceCount]=si
set si.index=instanceCount
set instanceCount=instanceCount+1
return si
endmethod
static method get takes unit u returns instance
local integer i=0
loop
exitwhen i==instanceCount
if instances[i].caster==u then
return instances[i]
endif
set i=i+1
endloop
return 0
endmethod
method onDestroy takes nothing returns nothing
set instanceCount=instanceCount-1
set instances[this.index]=instances[instanceCount]
set instances[instanceCount].index=this.index
call UnitRemoveABuffAura(this.caster, abt)
call ReleaseTimer(this.t)
call SetUnitTimeScale(this.caster, 1.0)
if not(this.interrupted) then
call IssueImmediateOrder(this.caster, "stop")
endif
endmethod
endstruct
private function SpellEffect takes nothing returns nothing
local integer lvl
if GetSpellAbilityId() == SPELL_ABILITY then
set lvl =GetUnitAbilityLevel(GetTriggerUnit(), SPELL_ABILITY)
call instance.create(GetTriggerUnit(), lvl)
endif
endfunction
private function SpellStop takes nothing returns nothing
local instance si
if GetSpellAbilityId() == SPELL_ABILITY then
set si = instance.get(GetTriggerUnit())
if si != 0 then
set si.interrupted=true
call si.destroy()
endif
endif
endfunction
private function Init takes nothing returns nothing
local trigger tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddAction( tr, function SpellEffect )
set tr = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( tr, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
call TriggerAddAction( tr, function SpellStop )
set abt=aBuffType.create()
set abt.ignoreAsBuff = true
set abt.eventCreate = ABuffEvent_Create.Create
set abt.eventRefresh = ABuffEvent_Refresh.Refresh
set abt.eventCleanup = ABuffEvent_Cleanup.Cleanup
set abt.eventDamaged = ABuffEvent_BUnitDamaged.Damaged
endfunction
endscope
__________________
Last edited by Anitarf : 06-24-2010 at 07:49 PM.
|