- Joined
- Mar 3, 2006
- Messages
- 1,564
JASS:
scope FireNova initializer Init
private keyword NovaData
private keyword MislData
globals
// Constants
private constant integer ABILTY_ID = 'A000' // rawcode of the Dummy Spell
private constant integer M_UNIT_ID = 'e000' // rawcode of the Missile Unit
private constant integer N_UNIT_ID = 'e001' // rawcode of the Nova Unit
private constant integer NOVA_SIZE = 36 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03
private constant real N_TIMER_INTERVAL = 0.015
private constant real M_DIST = 32.00
private constant real N_DIST = 16.00
private constant real NOVA_RADIUS = 544.00 // radius of the Nova
private constant real dA = 360/NOVA_SIZE
private constant real AB_CONST_FACTOR = 50.00
private constant real AB_LEVEL_FACTOR = 50.00
private constant real AB_PREV_LVL_FACTOR = 1
private constant attacktype ATKTYPE = ATTACK_TYPE_MAGIC
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private integer mindex = 0
private integer nindex = 0
private NovaData iFilter // Filter Data
private boolexpr fFilter // Filter function
private group TempGroup = CreateGroup()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage.evaluate(al -1)
endif
return AB_CONST_FACTOR + AB_LEVEL_FACTOR * al + AB_PREV_LVL_FACTOR * prevDmg
endfunction
private struct NovaData
unit Caster
unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup = CreateGroup() // Damaged Units Group
real dmg
static method NovaExpand takes nothing returns nothing
local thistype dat
local integer i = 0
local integer j
local real x
local real y
local real a
local unit u
loop // this loop cycles through all the casters which have cast the spell
exitwhen i >= nindex
set dat = temp_ndat[i]
// Nova Expanding
set j = 0
set a = 0
set dat.expand = dat.expand + N_DIST
loop
exitwhen j >= NOVA_SIZE
set x = dat.Cx + dat.expand * Cos( a * bj_DEGTORAD )
set y = dat.Cy + dat.expand * Sin( a * bj_DEGTORAD )
call SetUnitX( dat.Nova[j] , x )
call SetUnitY( dat.Nova[j] , y )
set j = j + 1
set a = a + dA
endloop
// Damage Units that the nova has reached
set iFilter = dat
call GroupEnumUnitsInRange(TempGroup, dat.Cx, dat.Cy, dat.expand, fFilter)
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
call UnitDamageTarget(dat.Caster, u, dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= NOVA_RADIUS then // check if the nova has reached its max AoE
set nindex = nindex - 1
set temp_ndat[i] = temp_ndat[nindex]
set i = i - 1
call dat.destroy()
endif
set i = i + 1
endloop
set u = null
endmethod
static method create takes unit caster , real damage , real posX, real posY returns NovaData
local thistype dat = thistype.allocate()
local integer i = 0
local real A = 0.00
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(dat.Caster)
set dat.Cx = posX
set dat.Cy = posY
set dat.dmg = damage
call DisplayTimedTextToPlayer(dat.Owner,0,0,10,"|cffff0000" + R2S(dat.dmg) + "|r")
loop
exitwhen i >= NOVA_SIZE
set dat.Nova[i] = CreateUnit( dat.Owner , N_UNIT_ID , dat.Cx , dat.Cy , A )
set A = A + dA
set i = i + 1
endloop
if nindex == 0 then
call TimerStart(ntm,N_TIMER_INTERVAL,true,function NovaData.NovaExpand)
endif
set temp_ndat[nindex] = dat
set nindex = nindex + 1
return dat
endmethod
static method FilterUnit takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) >= .305 and IsUnitEnemy(GetFilterUnit(),iFilter.Owner) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitInGroup(GetFilterUnit(),iFilter.dGroup)
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= NOVA_SIZE
call KillUnit(.Nova[i])
set .Nova[i] = null
set .expand = 0
set i = i + 1
endloop
if nindex == 0 then
call PauseTimer(ntm)
endif
endmethod
endstruct
private struct MislData
unit Caster
unit Missile
location CastPoint
real Distance
real Damage
real face
static method MoveMissile takes nothing returns nothing
local MislData dat
local integer i = 0
local real X = 0
local real Y = 0
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set dat.Distance = dat.Distance - M_DIST
set X = GetUnitX(dat.Missile)
set Y = GetUnitY(dat.Missile)
set X = X + M_DIST * Cos(dat.face)
set Y = Y + M_DIST * Sin(dat.face)
if DistanceBetweenPoints(GetUnitLoc(dat.Missile),dat.CastPoint) < M_DIST then
//if dat.Distance < M_DIST * 0.75 then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.create(dat.Caster , dat.Damage , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
call dat.destroy()
else
call SetUnitPosition(dat.Missile,X,Y)
endif
set i = i + 1
endloop
endmethod
static method create takes unit u , location target returns MislData
local MislData dat = MislData.allocate()
local real x1
local real y1
local real x2
local real y2
local real dx
local real dy
set temp_mdat[mindex] = dat
set dat.Caster = u
set x1 = GetUnitX(dat.Caster)
set y1 = GetUnitY(dat.Caster)
set dat.CastPoint = target
set x2 = GetLocationX(dat.CastPoint)
set y2 = GetLocationY(dat.CastPoint)
set dat.Distance = 0
set dx = x2 - x1
set dy = y2 - y1
set dat.Distance = SquareRoot(dx * dx + dy * dy)
//call DisplayTimedTextToPlayer(Player(0),0,0,10,"|cffff0000" + R2S(dat.Distance) + "|r")
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,x1,y1,dat.face)
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MoveMissile)
endif
set mindex = mindex + 1
return dat
endmethod
method onDestroy takes nothing returns nothing
call KillUnit(.Missile)
set .Missile = null
set .face = 0
call RemoveLocation(.CastPoint)
if mindex == 0 then
call PauseTimer(mtm)
endif
endmethod
endstruct
private function FBConditions takes nothing returns boolean
return GetSpellAbilityId() == ABILTY_ID
endfunction
private function Actions takes nothing returns nothing
call MislData.create(GetTriggerUnit(), GetSpellTargetLoc())
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 FBConditions))
call TriggerAddAction(t,function Actions)
set fFilter = Filter(function NovaData.FilterUnit)
endfunction
endscope
JASS:
scope FireShield initializer Init
private keyword Data
globals
private constant integer ABIL_ID = 'A002'
private constant integer UNIT_ID = 'e002'
private constant integer N = 3
private constant real shift = 360.00 / N
private constant real r = 128.00
private constant real dA = 5
private constant real INTERVAL = 0.03
private timer tmr = CreateTimer()
private integer index = 0
private Data array temp_data
endglobals
private function Duration takes integer aldur returns real
return aldur*6.
endfunction
private function Damage takes integer aldam returns real
return aldam*10.
endfunction
private struct Data
unit Caster
unit array Charge[N]
real A
real temp_A
real durtime
timer dur = CreateTimer()
static method rotate takes nothing returns nothing
local Data d
local integer i = 0
local integer j
local real X
local real Y
loop
exitwhen i >= index
set d = temp_data[i]
if TimerGetRemaining(d.dur) > 0.00 then
set d.A = d.A + dA
if d.A >= 360 then
set d.A = d.A - 360
endif
set d.temp_A = d.A
set j = 0
loop
exitwhen j >= N
set X = GetUnitX(d.Caster) + r * Cos(d.temp_A * bj_DEGTORAD)
set Y = GetUnitY(d.Caster) + r * Sin(d.temp_A * bj_DEGTORAD)
call SetUnitPosition(d.Charge[j],X,Y)
call SetUnitFacing(d.Charge[j],d.temp_A + 90)
set d.temp_A = d.temp_A + shift
set j = j + 1
endloop
else
set index = index - 1
set temp_data[i] = temp_data[index]
set i = i - 1
call d.destroy()
endif
set i = i + 1
endloop
endmethod
static method create takes unit u returns Data
local Data d = Data.allocate()
local integer i = 0
local real temp_A = 0
local real X
local real Y
set d.Caster = u
set d.durtime = Duration(GetUnitAbilityLevel(d.Caster,ABIL_ID))
loop
exitwhen i >= N
set X = GetUnitX(d.Caster) + r * Cos(temp_A * bj_DEGTORAD)
set Y = GetUnitY(d.Caster) + r * Sin(temp_A * bj_DEGTORAD)
set d.Charge[i] =CreateUnit(GetOwningPlayer(d.Caster),UNIT_ID,X,Y,temp_A + 90)
set i = i + 1
set temp_A = temp_A + shift
endloop
call TimerStart(d.dur,d.durtime,false,null)
if index == 0 then
call TimerStart(tmr,INTERVAL,true,function Data.rotate)
endif
set temp_data[index] = d
set index = index + 1
return d
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
if index == 0 then
call PauseTimer(tmr)
endif
loop
exitwhen i >= N
call KillUnit(.Charge[i])
set.Charge[i] = null
set i = i + 1
endloop
endmethod
endstruct
private function FSConditions takes nothing returns boolean
return GetSpellAbilityId() == ABIL_ID
endfunction
private function FSActions takes nothing returns nothing
call Data.create(GetTriggerUnit())
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 FSConditions))
call TriggerAddAction(t,function FSActions)
endfunction
endscope
'A000' and 'A002' are both based on Channel Spell but with different raw code.
There is an overlap occurrs when I cast the "first spell"; it fires the second one but when I cast the "second spell" the first don't overlap. Why do they overlap ?
Thanks & RewardThanks in advance and +rep for any help