Name | Type | is_array | initial_value |
l | location | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Fireball Version 1.01
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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
//====================================================================================================
// User-edit data
//====================================================================================================
// Make sure to change the dummy spell damage and area of effect text to be
//appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 512.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant integer FRIENDLY = 1 // (=0 for all units) OR (=1 for enemy only)
private constant integer GROUND = 1 // 0/1 to exclude/include ground units
private constant integer FLYING = 1 // 0/1 to exclude/include flying units
private constant integer STRUCTURE = 1 // 0/1 to exclude/include structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor;
private constant real BUILDN_FACTOR = 0.75 // Building damage factor;
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
//
//====================================================================================================
// The following variables (for advanced users) can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
//====================================================================================================
// End of User-edit data
//====================================================================================================
// 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 D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius.evaluate(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
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
real rad
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, null)
call GroupEnumUnitsInRange(TempGroup, dat.Cx, dat.Cy, dat.expand, Filter(function NovaData.MatchingUnit))
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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 radius, 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
set dat.rad = radius
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 MatchingUnit takes nothing returns boolean
local boolean m1 = FALSE
local boolean CheckDone = FALSE
local boolean mF = FALSE
local boolean mG = FALSE
local boolean mS = FALSE
if FRIENDLY == 1 then
if IsUnitEnemy(GetFilterUnit(),iFilter.Owner) then
set m1 = TRUE
endif
else
set m1 = TRUE
endif
if FLYING == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
if GROUND == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
if STRUCTURE == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
return GetWidgetLife(GetFilterUnit()) >= .405 and m1 and mF and mG and mS 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 Radius
real face
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real X = 0
local real Y = 0
local location loc
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 loc = GetUnitLoc(dat.Missile)
if DistanceBetweenPoints(loc,dat.CastPoint) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.create(dat.Caster , dat.Damage , dat.Radius , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
call dat.destroy()
else
set X = X + M_DIST * Cos(dat.face)
set Y = Y + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,X,Y)
endif
call RemoveLocation(loc)
set i = i + 1 // this index loops through all the casters
endloop
endmethod
static method MissileCreate 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)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,x1,y1,dat.face * bj_RADTODEG)
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
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 FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetLoc())
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
endfunction
endscope
//TESH.scrollpos=289
//TESH.alwaysfold=0
// Fireball Version 1.02
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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
// 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()
//====================================================================================================
// User-edit data
//====================================================================================================
// Make sure to change the dummy spell damage and area of effect text to be
//appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant integer FRIENDLY = 1 // (=0 for all units) OR (=1 for enemy only)
private constant integer GROUND = 1 // 0/1 to exclude/include ground units
private constant integer FLYING = 1 // 0/1 to exclude/include flying units
private constant integer STRUCTURE = 1 // 0/1 to exclude/include structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor;
private constant real BUILDN_FACTOR = 0.75 // Building damage factor;
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
//
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
//====================================================================================================
// End of User-edit data
//====================================================================================================
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
private struct NovaData
unit Caster
unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup // Already Damaged Units Group
real dmg
real rad
static method NovaExpand takes nothing returns nothing
local NovaData 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 // loop for moving the nova units
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, Filter(function NovaData.MatchingUnit))
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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 NovaCreate takes unit caster , real damage , real radius, real posX, real posY returns NovaData
local NovaData dat = NovaData.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
set dat.rad = radius
set dat.dGroup = CreateGroup()
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
//call BJDebugMsg(I2S(dat))
return dat
endmethod
static method MatchingUnit takes nothing returns boolean
local boolean m1 = FALSE
local boolean CheckDone = FALSE
local boolean mF = FALSE
local boolean mG = FALSE
local boolean mS = FALSE
if FRIENDLY == 1 then
if IsUnitEnemy(GetFilterUnit(),iFilter.Owner) then
set m1 = TRUE
endif
else
set m1 = TRUE
endif
if FLYING == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
if GROUND == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
if STRUCTURE == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
return GetWidgetLife(GetFilterUnit()) >= .405 and m1 and mF and mG and mS 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 Radius
real face
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real X = 0
local real Y = 0
local location loc
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 loc = GetUnitLoc(dat.Missile)
if DistanceBetweenPoints(loc,dat.CastPoint) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster , dat.Damage , dat.Radius , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
call dat.destroy()
else
set X = X + M_DIST * Cos(dat.face)
set Y = Y + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,X,Y)
endif
call RemoveLocation(loc)
set i = i + 1 // this index loops through all the casters
endloop
endmethod
static method MissileCreate 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)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,x1,y1,dat.face * bj_RADTODEG)
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
//call BJDebugMsg(R2S(dat.Damage))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
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 FB_Actions takes nothing returns nothing
// for MUI testing
//local integer i = 0
//local integer MAX = 1
if GetSpellAbilityId() == ABILTY_ID then
//loop
//exitwhen i >= MAX
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetLoc())
//set i = i + 1
//endloop
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),'e000',0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),'e001',0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=294
//TESH.alwaysfold=0
// Fireball Version 1.10
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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
// 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()
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell damage and area of effect text to be
//appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00
// changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00
// changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0
// changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00
// changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00
// changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0
// changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant integer FRIENDLY = 1
// (=0 to harm all units) OR (=1 to harm enemy only)
private constant integer GROUND = 1
// 0/1 to exclude/include ground units
private constant integer FLYING = 1
// 0/1 to exclude/include flying units
private constant integer STRUCTURE = 1
// 0/1 to exclude/include structure units
// Factors
private constant real UNIT_FACTOR = 1.00
// Unit damage factor.
private constant real BUILDN_FACTOR = 0.75
// Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
//====================================================================================================
// End of User-edit data //
//====================================================================================================
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
private struct NovaData extends array
unit Caster
static unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup // Already Damaged Units Group
real dmg
real rad
implement Alloc
static method NovaExpand takes nothing returns nothing
local NovaData 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 // loop for moving the nova units
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( Nova[(dat-1)*NOVA_SIZE + j] , x )
call SetUnitY( Nova[(dat-1)*NOVA_SIZE + 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, Filter(function NovaData.MatchingUnit))
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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 DestroyGroup(dat.dGroup)
set j = 0
loop
exitwhen j >= NOVA_SIZE
call KillUnit(Nova[(dat-1)*NOVA_SIZE + j])
set Nova[(dat-1)*NOVA_SIZE + j] = null
set dat.expand = 0
set j = j + 1
endloop
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
endmethod
static method NovaCreate takes unit caster , real damage , real radius, real posX, real posY returns NovaData
local NovaData dat = NovaData.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
set dat.rad = radius
set dat.dGroup = CreateGroup()
loop
exitwhen i >= NOVA_SIZE
set Nova[(dat-1)*NOVA_SIZE + 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 MatchingUnit takes nothing returns boolean
local boolean m1 = FALSE
local boolean CheckDone = FALSE
local boolean mF = FALSE
local boolean mG = FALSE
local boolean mS = FALSE
if FRIENDLY == 1 then
if IsUnitEnemy(GetFilterUnit(),iFilter.Owner) then
set m1 = TRUE
endif
else
set m1 = TRUE
endif
if FLYING == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_FLYING) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
if GROUND == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_GROUND) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
if STRUCTURE == 1 then
if IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE) and CheckDone == FALSE then
set CheckDone = TRUE
set mF = TRUE
set mG = TRUE
set mS = TRUE
endif
endif
return GetWidgetLife(GetFilterUnit()) >= .405 and m1 and mF and mG and mS and not IsUnitInGroup(GetFilterUnit(),iFilter.dGroup)
endmethod
endstruct
private struct MislData extends array
unit Caster
unit Missile
location CastPoint
real Distance
real Damage
real Radius
real face
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real X = 0
local real Y = 0
local location loc
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 loc = GetUnitLoc(dat.Missile)
if DistanceBetweenPoints(loc,dat.CastPoint) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster , dat.Damage , dat.Radius , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call RemoveLocation(dat.CastPoint)
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set X = X + M_DIST * Cos(dat.face)
set Y = Y + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,X,Y)
endif
call RemoveLocation(loc)
set i = i + 1 // this index loops through all the casters
endloop
endmethod
static method MissileCreate 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)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,x1,y1,dat.face * bj_RADTODEG)
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
return dat
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
// for MUI testing
//local integer i = 0
//local integer MAX = 1
if GetSpellAbilityId() == ABILTY_ID then
//loop
//exitwhen i >= MAX
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetLoc())
//set i = i + 1
//endloop
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),'e000',0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),'e001',0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=114
//TESH.alwaysfold=0
// Fireball Version 1.11
scope FireNova initializer Init
native UnitAlive takes unit u returns boolean
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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
// 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 group TempGroup = CreateGroup()
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell damage and area of effect text to be
//appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00
// changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00
// changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0
// changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00
// changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00
// changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0
// changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE
// true/false to harm enemy/all units
private constant boolean GROUND = TRUE
// true/false to include/exclude ground units
private constant boolean FLYING = TRUE
// true/false to include/exclude flying units
private constant boolean STRUCTURE = TRUE
// true/false to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00
// Unit damage factor.
private constant real BUILDN_FACTOR = 0.75
// Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
//====================================================================================================
// End of User-edit data //
//====================================================================================================
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
private struct NovaData extends array
unit Caster
static unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup // Already Damaged Units Group
real dmg
real rad
private static unit filterUnit
implement Alloc
static method NovaExpand takes nothing returns nothing
local NovaData 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 // loop for moving the nova units
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( Nova[(dat-1)*NOVA_SIZE + j] , x )
call SetUnitY( Nova[(dat-1)*NOVA_SIZE + 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, Filter(function NovaData.MatchingUnit))
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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 DestroyGroup(dat.dGroup)
set j = 0
loop
exitwhen j >= NOVA_SIZE
call KillUnit(Nova[(dat-1)*NOVA_SIZE + j])
set Nova[(dat-1)*NOVA_SIZE + j] = null
set dat.expand = 0
set j = j + 1
endloop
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
endmethod
static method NovaCreate takes unit caster , real damage , real radius, real posX, real posY returns NovaData
local NovaData dat = NovaData.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
set dat.rad = radius
set dat.dGroup = CreateGroup()
loop
exitwhen i >= NOVA_SIZE
set Nova[(dat-1)*NOVA_SIZE + 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 MatchingUnit takes nothing returns boolean
set filterUnit=GetFilterUnit()
if (not UnitAlive(thistype.filterUnit)) or/*
*/( IsUnitInGroup(thistype.filterUnit,iFilter.dGroup)) or/*
*/( FRIENDLY and IsUnitAlly(thistype.filterUnit,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(thistype.filterUnit,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(thistype.filterUnit,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(thistype.filterUnit,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
endstruct
private struct MislData extends array
unit Caster
unit Missile
location CastPoint
real Distance
real Damage
real Radius
real face
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real X = 0
local real Y = 0
local location loc
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 loc = GetUnitLoc(dat.Missile)
if DistanceBetweenPoints(loc,dat.CastPoint) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster , dat.Damage , dat.Radius , GetUnitX(dat.Missile) , GetUnitY(dat.Missile))
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call RemoveLocation(dat.CastPoint)
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set X = X + M_DIST * Cos(dat.face)
set Y = Y + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,X,Y)
endif
call RemoveLocation(loc)
set i = i + 1 // this index loops through all the casters
endloop
endmethod
static method MissileCreate 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)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(dat.Caster),M_UNIT_ID,x1,y1,dat.face * bj_RADTODEG)
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
return dat
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
// for MUI testing
//local integer i = 0
//local integer MAX = 1
if GetSpellAbilityId() == ABILTY_ID then
//loop
//exitwhen i >= MAX
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetLoc())
//set i = i + 1
//endloop
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),'e000',0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),'e001',0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=197
//TESH.alwaysfold=0
// Fireball Version 1.12
scope FNova initializer Init
private keyword NovaData
private keyword MislData
globals
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell damage and area of effect text to be
//appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // true/false to harm enemy/all units
private constant boolean GROUND = TRUE // true/false to include/exclude ground units
private constant boolean FLYING = TRUE // true/false to include/exclude flying units
private constant boolean STRUCTURE = TRUE // true/false to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
//====================================================================================================
// End of User-edit data //
//====================================================================================================
// 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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
// 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
private group TempGroup = CreateGroup()
private hashtable Nova_Flag = InitHashtable()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
implement Alloc
static method MatchingUnit takes unit FilterUnit returns boolean
local unit u = FilterUnit
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set n = null
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
endmethod
static method NovaCreate takes unit caster , real damage , real radius, real posX, real posY returns NovaData
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set u = null
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
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Distance
real Damage
real Radius
real face
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x1 = 0
local real y1 = 0
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 0
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set dat.Distance = dat.Distance - M_DIST
set x1 = GetUnitX(dat.Missile)
set y1 = GetUnitY(dat.Missile)
set x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x1
set dy = y2 - y1
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster , dat.Damage , dat.Radius , x1 , y1)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x1 = x1 + M_DIST * Cos(dat.face)
set y1 = y1 + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,x1,y1)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y 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 x1 = GetUnitX(u)
set y1 = GetUnitY(u)
set x2 = X
set y2 = Y
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dat.Distance = 0
set dat.Distance = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitPathing(dat.Missile, false )
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
return dat
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=51
//TESH.alwaysfold=0
// Fireball Version 1.14
scope FNova initializer Init
private keyword NovaData
private keyword MislData
globals
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell damage and area of effect text to be
//appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // true/false to harm enemy/all units
private constant boolean GROUND = TRUE // true/false to include/exclude ground units
private constant boolean FLYING = TRUE // true/false to include/exclude flying units
private constant boolean STRUCTURE = TRUE // true/false to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
//====================================================================================================
// End of User-edit data //
//====================================================================================================
// 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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
// 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
private group TempGroup = CreateGroup()
private hashtable Nova_Flag = InitHashtable()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
implement Alloc
static method MatchingUnit takes unit FilterUnit returns boolean
local unit u = FilterUnit
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set n = null
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
call dat.deallocate()
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
endmethod
static method NovaCreate takes unit caster , real damage , real radius, real posX, real posY returns NovaData
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set u = null
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
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Distance
real Damage
real Radius
real face
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x1 = 0
local real y1 = 0
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 0
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set dat.Distance = dat.Distance - M_DIST
set x1 = GetUnitX(dat.Missile)
set y1 = GetUnitY(dat.Missile)
set x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x1
set dy = y2 - y1
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster , dat.Damage , dat.Radius , x1 , y1)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call dat.deallocate()
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x1 = x1 + M_DIST * Cos(dat.face)
set y1 = y1 + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,x1,y1)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y 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 x1 = GetUnitX(u)
set y1 = GetUnitY(u)
set x2 = X
set y2 = Y
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dat.Distance = 0
set dat.Distance = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitPathing(dat.Missile, false )
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
return dat
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=72
//TESH.alwaysfold=0
// Immolation Fireball Version 1.20
scope FNova initializer Init
private keyword NovaData
private keyword MislData
private keyword ImmoData
globals
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell text to be appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // true/false to harm enemy/all units
private constant boolean GROUND = TRUE // true/false to include/exclude ground units
private constant boolean FLYING = TRUE // true/false to include/exclude flying units
private constant boolean STRUCTURE = TRUE // true/false to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
// Immolation (Damage Over Time)
private constant boolean IMMOLATION = TRUE // true/false to Allow/Disallow Damage Over Time
// Immolation Damage (ID) [per 1 Second]
private constant real ID_CONST_FACTOR = 00.00 // changes 'ConstantFactor'
private constant real ID_LEVEL_FACTOR = 01.00 // changes 'AbilityLevelFactor'
private constant real ID_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Immolation Length(Duration) (IL) [in seconds]
private constant real IL_CONST_FACTOR = 05.00 // changes 'ConstantFactor'
private constant real IL_LEVEL_FACTOR = 05.00 // changes 'AbilityLevelFactor'
private constant real IL_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
//====================================================================================================
// End of User-edit data //
//====================================================================================================
// 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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real I_TIMER_INTERVAL = 0.1 // this will determine the immolation damage frequency
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
private constant real K = 60.00
private constant string UnitModel = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
private constant string BuildingModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
private constant string UAttPoint = "chest"
private constant string BAttPoint = "sprite"
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private timer itm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private ImmoData array temp_idat
private integer mindex = 0
private integer nindex = 0
private integer iindex = 0
private NovaData iFilter
private hashtable Nova_Flag = InitHashtable()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
function ImmoDamage takes integer al returns real
local real prevIDmg
if al == 0 then
set prevIDmg = 0
else
set prevIDmg = ImmoDamage(al - 1)
endif
return ID_CONST_FACTOR + ID_LEVEL_FACTOR * al + ID_PREV_LVL_FACTOR * prevIDmg
endfunction
function ImmoDuration takes integer al returns real
local real prevIDur
if al == 0 then
set prevIDur = 0
else
set prevIDur = ImmoDuration(al - 1)
endif
return IL_CONST_FACTOR + IL_LEVEL_FACTOR * al + IL_PREV_LVL_FACTOR * prevIDur
endfunction
private struct ImmoData extends array
unit caster
unit target
integer executecount
real damage
real duration
effect FX
implement Alloc
static method Interval takes nothing returns nothing
local thistype dat
local integer i = 0
loop
exitwhen i >= iindex
set dat = temp_idat[i]
set dat.executecount = dat.executecount + 1
if dat.executecount > dat.duration/I_TIMER_INTERVAL then
set iindex = iindex - 1
set temp_idat[i] = temp_idat[iindex]
set i = i - 1
set dat.caster = null
set dat.target = null
set dat.executecount = 0
call DestroyEffect(dat.FX)
set dat.FX = null
call dat.deallocate()
if iindex == 0 then
call PauseTimer(itm)
endif
else
if IsUnitType(dat.target,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.caster,dat.target,BUILDN_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(BuildingModel,dat.target,BAttPoint)
endif
else
call UnitDamageTarget(dat.caster,dat.target,UNIT_FACTOR *dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(UnitModel,dat.target,UAttPoint)
endif
endif
endif
set i = i + 1
endloop
endmethod
static method StartDoT takes unit caster,unit target, real damage, real duration returns nothing
local thistype dat = thistype.allocate()
local integer i = 0
local unit temp_u
set temp_idat[iindex] = dat
set dat.caster = caster
set dat.target = target
set dat.executecount = 0
set dat.duration = duration
set dat.damage = damage
if iindex == 0 then
call TimerStart(itm, I_TIMER_INTERVAL , true , function thistype.Interval )
endif
set iindex = iindex + 1
endmethod
endstruct
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
real IDamage
real IDuration
implement Alloc
static method MatchingUnit takes unit FilterUnit returns boolean
local unit u = FilterUnit
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/ IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
local group TempGroup = CreateGroup() //change
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
if IMMOLATION == true and GetWidgetLife(u) >= 0.405 then
call ImmoData.StartDoT(dat.Caster,u,dat.IDamage,dat.IDuration)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set n = null
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
call dat.deallocate()
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
call DestroyGroup(TempGroup) //change
endmethod
static method NovaCreate takes unit caster,real damage,real radius,real idamage,real iduration,real posX,real posY returns NovaData
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
set dat.IDamage = idamage
set dat.IDuration = iduration
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set u = null
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
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Distance
real Damage
real Radius
real IDamage
real IDuration
real face
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x = 0
local real y = 0
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 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 x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x
set dy = y2 - y
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster,dat.Damage,dat.Radius,dat.IDamage,dat.IDuration,x,y)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call dat.deallocate()
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x = x + M_DIST * Cos(dat.face)
set y = y + M_DIST * Sin(dat.face)
call SetUnitPosition(dat.Missile,x,y)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y returns MislData
local MislData dat = MislData.allocate()
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
local real dx = 0.
local real dy = 0.
set temp_mdat[mindex] = dat
set x1 = GetUnitX(u)
set y1 = GetUnitY(u)
set x2 = X
set y2 = Y
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dat.Distance = 0
set dat.Distance = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitPathing(dat.Missile, false )
call SetUnitPosition(dat.Missile,x1,y1)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.IDamage = ImmoDamage(GetUnitAbilityLevel(u , ABILTY_ID)) * I_TIMER_INTERVAL
set dat.IDuration = ImmoDuration(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
return dat
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=487
//TESH.alwaysfold=0
// Immolation Fireball Version 1.21
scope FNova initializer Init
private keyword NovaData
private keyword MislData
private keyword ImmoData
globals
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell text to be appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // true/false to harm enemy/all units
private constant boolean GROUND = TRUE // true/false to include/exclude ground units
private constant boolean FLYING = TRUE // true/false to include/exclude flying units
private constant boolean STRUCTURE = TRUE // true/false to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
// Immolation (Damage Over Time)
private constant boolean IMMOLATION = TRUE // true/false to Allow/Disallow Damage Over Time
// Immolation Damage (ID) [per 1 Second]
private constant real ID_CONST_FACTOR = 00.00 // changes 'ConstantFactor'
private constant real ID_LEVEL_FACTOR = 01.00 // changes 'AbilityLevelFactor'
private constant real ID_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Immolation Length(Duration) (IL) [in seconds]
private constant real IL_CONST_FACTOR = 05.00 // changes 'ConstantFactor'
private constant real IL_LEVEL_FACTOR = 05.00 // changes 'AbilityLevelFactor'
private constant real IL_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
private constant real CASTER_HAND_Z = 64.00 // This value controls the height at which the missile will appear relative to the caster. Change it according to the model and its scale
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
//====================================================================================================
// End of User-edit data //
//====================================================================================================
// 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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real I_TIMER_INTERVAL = 0.1 // this will determine the immolation damage frequency
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
private constant real K = 60.00
private constant string UnitModel = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
private constant string BuildingModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
private constant string UAttPoint = "chest"
private constant string BAttPoint = "sprite"
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private timer itm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private ImmoData array temp_idat
private integer mindex = 0
private integer nindex = 0
private integer iindex = 0
private NovaData iFilter
private hashtable Nova_Flag = InitHashtable()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
function ImmoDamage takes integer al returns real
local real prevIDmg
if al == 0 then
set prevIDmg = 0
else
set prevIDmg = ImmoDamage(al - 1)
endif
return ID_CONST_FACTOR + ID_LEVEL_FACTOR * al + ID_PREV_LVL_FACTOR * prevIDmg
endfunction
function ImmoDuration takes integer al returns real
local real prevIDur
if al == 0 then
set prevIDur = 0
else
set prevIDur = ImmoDuration(al - 1)
endif
return IL_CONST_FACTOR + IL_LEVEL_FACTOR * al + IL_PREV_LVL_FACTOR * prevIDur
endfunction
private struct ImmoData extends array
unit caster
unit target
integer executecount
real damage
real duration
effect FX
implement Alloc
static method Interval takes nothing returns nothing
local thistype dat
local integer i = 0
loop
exitwhen i >= iindex
set dat = temp_idat[i]
set dat.executecount = dat.executecount + 1
if dat.executecount > dat.duration/I_TIMER_INTERVAL then
set iindex = iindex - 1
set temp_idat[i] = temp_idat[iindex]
set i = i - 1
set dat.caster = null
set dat.target = null
set dat.executecount = 0
call DestroyEffect(dat.FX)
set dat.FX = null
call dat.deallocate()
if iindex == 0 then
call PauseTimer(itm)
endif
else
if IsUnitType(dat.target,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.caster,dat.target,BUILDN_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(BuildingModel,dat.target,BAttPoint)
endif
else
call UnitDamageTarget(dat.caster,dat.target,UNIT_FACTOR *dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(UnitModel,dat.target,UAttPoint)
endif
endif
endif
set i = i + 1
endloop
endmethod
static method StartDoT takes unit caster,unit target, real damage, real duration returns nothing
local thistype dat = thistype.allocate()
local integer i = 0
local unit temp_u
set temp_idat[iindex] = dat
set dat.caster = caster
set dat.target = target
set dat.executecount = 0
set dat.duration = duration
set dat.damage = damage
if iindex == 0 then
call TimerStart(itm, I_TIMER_INTERVAL , true , function thistype.Interval )
endif
set iindex = iindex + 1
endmethod
endstruct
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
real IDamage
real IDuration
implement Alloc
static method MatchingUnit takes unit FilterUnit returns boolean
local unit u = FilterUnit
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/ IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
local group TempGroup = CreateGroup() //change
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
if IMMOLATION == true and GetWidgetLife(u) >= 0.405 then
call ImmoData.StartDoT(dat.Caster,u,dat.IDamage,dat.IDuration)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set n = null
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
call dat.deallocate()
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
call DestroyGroup(TempGroup) //change
endmethod
static method NovaCreate takes unit caster,real damage,real radius,real idamage,real iduration,real posX,real posY returns NovaData
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
set dat.IDamage = idamage
set dat.IDuration = iduration
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set u = null
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
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Distance
real Damage
real Radius
real IDamage
real IDuration
real face
real a
real h
real k
real v1
real x1
real y1
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x = 0
local real y = 0
local real z
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 0
local real v
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 x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x
set dy = y2 - y
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster,dat.Damage,dat.Radius,dat.IDamage,dat.IDuration,x,y)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call dat.deallocate()
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x = x + M_DIST * Cos(dat.face)
set y = y + M_DIST * Sin(dat.face)
set dx = x - dat.x1
set dy = y - dat.y1
set v = dat.v1 + SquareRoot(dx*dx + dy*dy)
set z = (dat.a * ( v - dat.h ) * ( v - dat.h )) + dat.k
call SetUnitPosition(dat.Missile,x,y)
call SetUnitFlyHeight(dat.Missile,z,0.0)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y returns MislData
local MislData dat = MislData.allocate()
local real x1 = 0.
local real y1 = 0.
local real x2 = 0.
local real y2 = 0.
local real dx = 0.
local real dy = 0.
local real z1 = 0.
local real v1 = 0.
local real z2 = 0.
local real v2 = 0.
local real phi = 0.
local real error = 0.0
set temp_mdat[mindex] = dat
set x1 = GetUnitX(u)
set dat.x1 = x1
set y1 = GetUnitY(u)
set dat.y1 = y1
// Fail-Safe in case the caster and the cast location is at points (x=[-1,1],y=[-1,1])
if ((x1 >= -1 and x1 <= 1) and (y1 >= -1 and y1 <= 1) and X == x1 and Y == y1) then
set error = 1.0
endif
set z1 = CASTER_HAND_Z
set dat.k = GetUnitFlyHeight(u) + z1 + K
set x2 = X + error
set y2 = Y + error
set z2 = 0.0
set phi = SquareRoot((z2 - dat.k)/(z1 - dat.k))
set v1 = SquareRoot(x1*x1 + y1*y1)
set dat.v1 = v1
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dat.Distance = 0
set dat.Distance = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set v2 = v1 + dat.Distance
set dat.h = ((phi*v1) + v2)/(1.0 + phi)
set dat.a = (z2 - dat.k)/((dat.h - v2)*(dat.h - v2))
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitFlyHeight(dat.Missile,z1,0.0)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.IDamage = ImmoDamage(GetUnitAbilityLevel(u , ABILTY_ID)) * I_TIMER_INTERVAL
set dat.IDuration = ImmoDuration(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
return dat
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=66
//TESH.alwaysfold=0
// Immolation Fireball Version 1.22
scope FNova initializer Init
private keyword NovaData
private keyword MislData
private keyword ImmoData
globals
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell text to be appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // true/false to harm enemy/all units
private constant boolean GROUND = TRUE // true/false to include/exclude ground units
private constant boolean FLYING = TRUE // true/false to include/exclude flying units
private constant boolean STRUCTURE = TRUE // true/false to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
// Immolation (Damage Over Time)
private constant boolean IMMOLATION = TRUE // true/false to Allow/Disallow Damage Over Time
// Immolation Damage (ID) [per 1 Second]
private constant real ID_CONST_FACTOR = 00.00 // changes 'ConstantFactor'
private constant real ID_LEVEL_FACTOR = 01.00 // changes 'AbilityLevelFactor'
private constant real ID_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Immolation Length(Duration) (IL) [in seconds]
private constant real IL_CONST_FACTOR = 05.00 // changes 'ConstantFactor'
private constant real IL_LEVEL_FACTOR = 05.00 // changes 'AbilityLevelFactor'
private constant real IL_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
private constant real CASTER_HAND_Z = 64.00 // This value controls the height at which the missile will appear relative to the caster. Change it according to the model and its scale
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
//====================================================================================================
// End of User-edit data //
//====================================================================================================
// 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 = 12 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real I_TIMER_INTERVAL = 0.1 // this will determine the immolation damage frequency
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
private constant real K = 60.00
private constant string UnitModel = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
private constant string BuildingModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
private constant string UAttPoint = "chest"
private constant string BAttPoint = "sprite"
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private timer itm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private ImmoData array temp_idat
private integer mindex = 0
private integer nindex = 0
private integer iindex = 0
private NovaData iFilter
private hashtable Nova_Flag = InitHashtable()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endfunction
function ImmoDamage takes integer al returns real
local real prevIDmg
if al == 0 then
set prevIDmg = 0
else
set prevIDmg = ImmoDamage(al - 1)
endif
return ID_CONST_FACTOR + ID_LEVEL_FACTOR * al + ID_PREV_LVL_FACTOR * prevIDmg
endfunction
function ImmoDuration takes integer al returns real
local real prevIDur
if al == 0 then
set prevIDur = 0
else
set prevIDur = ImmoDuration(al - 1)
endif
return IL_CONST_FACTOR + IL_LEVEL_FACTOR * al + IL_PREV_LVL_FACTOR * prevIDur
endfunction
private struct ImmoData extends array
unit caster
unit target
integer executecount
real damage
real duration
effect FX
implement Alloc
static method Interval takes nothing returns nothing
local thistype dat
local integer i = 0
loop
exitwhen i >= iindex
set dat = temp_idat[i]
set dat.executecount = dat.executecount + 1
if dat.executecount > dat.duration/I_TIMER_INTERVAL then
set iindex = iindex - 1
set temp_idat[i] = temp_idat[iindex]
set i = i - 1
set dat.caster = null
set dat.target = null
set dat.executecount = 0
call DestroyEffect(dat.FX)
set dat.FX = null
call dat.deallocate()
if iindex == 0 then
call PauseTimer(itm)
endif
else
if IsUnitType(dat.target,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.caster,dat.target,BUILDN_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(BuildingModel,dat.target,BAttPoint)
endif
else
call UnitDamageTarget(dat.caster,dat.target, UNIT_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(UnitModel,dat.target,UAttPoint)
endif
endif
endif
set i = i + 1
endloop
endmethod
static method StartDoT takes unit caster,unit target, real damage, real duration returns nothing
local thistype dat = thistype.allocate()
local integer i = 0
local unit temp_u
set temp_idat[iindex] = dat
set dat.caster = caster
set dat.target = target
set dat.executecount = 0
set dat.duration = duration
set dat.damage = damage
if iindex == 0 then
call TimerStart(itm, I_TIMER_INTERVAL , true , function thistype.Interval )
endif
set iindex = iindex + 1
endmethod
endstruct
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
real IDamage
real IDuration
implement Alloc
static method MatchingUnit takes unit FilterUnit returns boolean
local unit u = FilterUnit
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/ IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
local group TempGroup = CreateGroup()
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
if IMMOLATION == true and GetWidgetLife(u) >= 0.405 then
call ImmoData.StartDoT(dat.Caster,u,dat.IDamage,dat.IDuration)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set n = null
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
call dat.deallocate()
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
call DestroyGroup(TempGroup)
endmethod
static method NovaCreate takes unit caster,real damage,real radius,real idamage,real iduration,real posX,real posY returns nothing
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
set dat.IDamage = idamage
set dat.IDuration = iduration
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set u = null
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
endmethod
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Damage
real Radius
real IDamage
real IDuration
real face
real a
real h
real k
real v1
real x1
real y1
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x = 0
local real y = 0
local real z
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 0
local real v
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set x = GetUnitX(dat.Missile)
set y = GetUnitY(dat.Missile)
set x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x
set dy = y2 - y
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster,dat.Damage,dat.Radius,dat.IDamage,dat.IDuration,x,y)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call dat.deallocate()
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x = x + M_DIST * Cos(dat.face)
set y = y + M_DIST * Sin(dat.face)
set dx = x - dat.x1
set dy = y - dat.y1
set v = dat.v1 + SquareRoot(dx*dx + dy*dy)
set z = (dat.a * ( v - dat.h ) * ( v - dat.h )) + dat.k
call SetUnitPosition(dat.Missile,x,y)
call SetUnitFlyHeight(dat.Missile,z,0.0)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y returns nothing
local MislData dat = MislData.allocate()
local real x1 = 0.0
local real y1 = 0.0
local real x2 = 0.0
local real y2 = 0.0
local real dx = 0.0
local real dy = 0.0
local real z1 = 0.0
local real v1 = 0.0
local real z2 = 0.0
local real v2 = 0.0
local real phi = 0.0
local real dist = 0.0
local real error = 0.0
set temp_mdat[mindex] = dat
set x1 = GetUnitX(u)
set dat.x1 = x1
set y1 = GetUnitY(u)
set dat.y1 = y1
// Fail-Safe in case the caster and the cast location is at points (x=[-1,1],y=[-1,1])
if ((x1 >= -1 and x1 <= 1) and (y1 >= -1 and y1 <= 1) and X == x1 and Y == y1) then
set error = 1.0
endif
set z1 = CASTER_HAND_Z
set dat.k = GetUnitFlyHeight(u) + z1 + K // in case of flying units
set x2 = X + error
set y2 = Y + error
set z2 = 0.0
set phi = SquareRoot((z2 - dat.k)/(z1 - dat.k))
set v1 = SquareRoot(x1*x1 + y1*y1)
set dat.v1 = v1
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dist = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set v2 = v1 + dist
set dat.h = ((phi*v1) + v2)/(1.0 + phi)
set dat.a = (z2 - dat.k)/((dat.h - v2)*(dat.h - v2))
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitFlyHeight(dat.Missile,z1,0.0)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.IDamage = ImmoDamage(GetUnitAbilityLevel(u , ABILTY_ID)) * I_TIMER_INTERVAL
set dat.IDuration = ImmoDuration(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Immolation Fireball Version 1.23
scope FNova initializer Init_IFireball
private keyword NovaData
private keyword MislData
private keyword ImmoData
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 = 18 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real I_TIMER_INTERVAL = 0.1 // this will determine the immolation damage frequency
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
private constant real K = 60.00
private constant string UnitModel = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
private constant string BuildingModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
private constant string UAttPoint = "chest"
private constant string BAttPoint = "sprite"
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private timer itm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private ImmoData array temp_idat
private integer mindex = 0
private integer nindex = 0
private integer iindex = 0
private NovaData iFilter
private hashtable Nova_Flag = InitHashtable()
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell text to be appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant boolean D_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array Damage // set the values in the function named "Spell_Data_Table"
// Formula:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant boolean R_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array Range // set the values in the function named "Spell_Data_Table"
// Formula:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // TRUE/FALSE to harm enemy/all units
private constant boolean GROUND = TRUE // TRUE/FALSE to include/exclude ground units
private constant boolean FLYING = TRUE // TRUE/FALSE to include/exclude flying units
private constant boolean STRUCTURE = TRUE // TRUE/FALSE to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
// Immolation (Damage Over Time)
private constant boolean IMMOLATION = TRUE // TRUE/FALSE to Allow/Disallow Immolation (Damage Over Time)
// Immolation Damage (ID) [per 1 Second]
private constant boolean ID_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array ImmoDmg // set the values in the function named "Spell_Data_Table"
// Formula
private constant real ID_CONST_FACTOR = 00.00 // changes 'ConstantFactor'
private constant real ID_LEVEL_FACTOR = 01.00 // changes 'AbilityLevelFactor'
private constant real ID_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Immolation Length(Duration) (IL) [in seconds]
private constant boolean IL_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array ImmoDur // set the values in the function named "Spell_Data_Table"
// Formula
private constant real IL_CONST_FACTOR = 05.00 // changes 'ConstantFactor'
private constant real IL_LEVEL_FACTOR = 05.00 // changes 'AbilityLevelFactor'
private constant real IL_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
private constant real CASTER_HAND_Z = 64.00 // This value controls the height at which the missile will appear relative to the caster. Change it according to the model and its scale
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
endglobals
function Spell_Data_Table takes nothing returns nothing
// If your spell is more than 3 levels just add Damage[]/Range[]/ImmoDmg[]/ImmoDur[] under its appropriate place
// Remember that if you don't add this line the Damage/Range/ImmoDmg/ImmoDur will be 0 for level 4+
// Damage Table
set Damage[1] = 50.0
set Damage[2] = 100.0
set Damage[3] = 200.0
// Range Table
set Range[1] = 500.0
set Range[2] = 500.0
set Range[3] = 500.0
// Immolation Damage Table
set ImmoDmg[1] = 2.0
set ImmoDmg[2] = 4.0
set ImmoDmg[3] = 8.0
// Immolation Duration Table
set ImmoDur[1] = 10.0
set ImmoDur[2] = 15.0
set ImmoDur[3] = 30.0
endfunction
//====================================================================================================
// End of User-edit data //
//====================================================================================================
function NovaDamage takes integer al returns real
local real prevDmg
if D_TABLE then
return Damage[al]
else
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endif
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if R_TABLE then
return Range[al]
else
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endif
endfunction
function ImmoDamage takes integer al returns real
local real prevIDmg
if ID_TABLE then
return ImmoDmg[al]
else
if al == 0 then
set prevIDmg = 0
else
set prevIDmg = ImmoDamage(al - 1)
endif
return ID_CONST_FACTOR + ID_LEVEL_FACTOR * al + ID_PREV_LVL_FACTOR * prevIDmg
endif
endfunction
function ImmoDuration takes integer al returns real
local real prevIDur
if IL_TABLE then
return ImmoDur[al]
else
if al == 0 then
set prevIDur = 0
else
set prevIDur = ImmoDuration(al - 1)
endif
return IL_CONST_FACTOR + IL_LEVEL_FACTOR * al + IL_PREV_LVL_FACTOR * prevIDur
endif
endfunction
private struct ImmoData extends array
unit caster
unit target
integer executecount
real damage
real duration
effect FX
implement Alloc
static method Interval takes nothing returns nothing
local thistype dat
local integer i = 0
loop
exitwhen i >= iindex
set dat = temp_idat[i]
set dat.executecount = dat.executecount + 1
if dat.executecount > dat.duration/I_TIMER_INTERVAL then
set iindex = iindex - 1
set temp_idat[i] = temp_idat[iindex]
set i = i - 1
set dat.caster = null
set dat.target = null
set dat.executecount = 0
call DestroyEffect(dat.FX)
set dat.FX = null
call dat.deallocate()
if iindex == 0 then
call PauseTimer(itm)
endif
else
if IsUnitType(dat.target,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.caster,dat.target,BUILDN_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(BuildingModel,dat.target,BAttPoint)
endif
else
call UnitDamageTarget(dat.caster,dat.target, UNIT_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(UnitModel,dat.target,UAttPoint)
endif
endif
endif
set i = i + 1
endloop
endmethod
static method StartDoT takes unit caster,unit target, real damage, real duration returns nothing
local thistype dat = thistype.allocate()
local integer i = 0
local unit temp_u
set temp_idat[iindex] = dat
set dat.caster = caster
set dat.target = target
set dat.executecount = 0
set dat.duration = duration
set dat.damage = damage
if iindex == 0 then
call TimerStart(itm, I_TIMER_INTERVAL , true , function thistype.Interval )
endif
set iindex = iindex + 1
endmethod
endstruct
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
real IDamage
real IDuration
implement Alloc
static method MatchingUnit takes unit FilterUnit returns boolean
local unit u = FilterUnit
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/ IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
local group TempGroup = CreateGroup()
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
if IMMOLATION == true and GetWidgetLife(u) >= 0.405 then
call ImmoData.StartDoT(dat.Caster,u,dat.IDamage,dat.IDuration)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set n = null
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
call dat.deallocate()
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set u = null
call DestroyGroup(TempGroup)
endmethod
static method NovaCreate takes unit caster,real damage,real radius,real idamage,real iduration,real posX,real posY returns nothing
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
set dat.IDamage = idamage
set dat.IDuration = iduration
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set u = null
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
endmethod
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Damage
real Radius
real IDamage
real IDuration
real face
real a
real h
real k
real v1
real x1
real y1
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x = 0
local real y = 0
local real z
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 0
local real v
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set x = GetUnitX(dat.Missile)
set y = GetUnitY(dat.Missile)
set x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x
set dy = y2 - y
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster,dat.Damage,dat.Radius,dat.IDamage,dat.IDuration,x,y)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call dat.deallocate()
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x = x + M_DIST * Cos(dat.face)
set y = y + M_DIST * Sin(dat.face)
set dx = x - dat.x1
set dy = y - dat.y1
set v = dat.v1 + SquareRoot(dx*dx + dy*dy)
set z = (dat.a * ( v - dat.h ) * ( v - dat.h )) + dat.k
call SetUnitPosition(dat.Missile,x,y)
call SetUnitFlyHeight(dat.Missile,z,0.0)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y returns nothing
local MislData dat = MislData.allocate()
local real x1 = 0.0
local real y1 = 0.0
local real x2 = 0.0
local real y2 = 0.0
local real dx = 0.0
local real dy = 0.0
local real z1 = 0.0
local real v1 = 0.0
local real z2 = 0.0
local real v2 = 0.0
local real phi = 0.0
local real dist = 0.0
local real error = 0.0
set temp_mdat[mindex] = dat
set x1 = GetUnitX(u)
set dat.x1 = x1
set y1 = GetUnitY(u)
set dat.y1 = y1
// Fail-Safe in case the caster and the cast location is at points (x=[-1,1],y=[-1,1])
if ((x1 >= -1 and x1 <= 1) and (y1 >= -1 and y1 <= 1) and X == x1 and Y == y1) then
set error = 1.0
endif
set z1 = CASTER_HAND_Z
set dat.k = GetUnitFlyHeight(u) + z1 + K // in case of flying units
set x2 = X + error
set y2 = Y + error
set z2 = 0.0
set phi = SquareRoot((z2 - dat.k)/(z1 - dat.k))
set v1 = SquareRoot(x1*x1 + y1*y1)
set dat.v1 = v1
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dist = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set v2 = v1 + dist
set dat.h = ((phi*v1) + v2)/(1.0 + phi)
set dat.a = (z2 - dat.k)/((dat.h - v2)*(dat.h - v2))
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitFlyHeight(dat.Missile,z1,0.0)
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.Radius = NovaRadius(GetUnitAbilityLevel(u , ABILTY_ID))
set dat.IDamage = ImmoDamage(GetUnitAbilityLevel(u , ABILTY_ID)) * I_TIMER_INTERVAL
set dat.IDuration = ImmoDuration(GetUnitAbilityLevel(u , ABILTY_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init_IFireball takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
call Spell_Data_Table()
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
Its important to copy all the contents of the
trigger "BoundSentinel"
trigger "Alloc"
to your map in order for this spell to function properly.
//TESH.scrollpos=0
//TESH.alwaysfold=0
library BoundSentinel initializer init
//*************************************************
//* BoundSentinel
//* -------------
//* Don't leave your units unsupervised, naughty
//* them may try to get out of the map bounds and
//* crash your game.
//*
//* To implement, just get a vJass compiler and
//* copy this library/trigger to your map.
//*
//*************************************************
//==================================================
globals
// High enough so the unit is no longer visible, low enough so the
// game doesn't crash...
//
// I think you need 0.0 or soemthing negative prior to patch 1.22
//
private constant real EXTRA = 500.0
endglobals
//=========================================================================================
globals
private real maxx
private real maxy
private real minx
private real miny
endglobals
//=======================================================================
private function dis takes nothing returns nothing
local unit u=GetTriggerUnit()
local real x=GetUnitX(u)
local real y=GetUnitY(u)
if(x>maxx) then
set x=maxx
elseif(x<minx) then
set x=minx
endif
if(y>maxy) then
set y=maxy
elseif(y<miny) then
set y=miny
endif
call SetUnitX(u,x)
call SetUnitY(u,y)
set u=null
endfunction
private function init takes nothing returns nothing
local trigger t=CreateTrigger()
local region r=CreateRegion()
local rect rc
set minx=GetCameraBoundMinX() - EXTRA
set miny=GetCameraBoundMinY() - EXTRA
set maxx=GetCameraBoundMaxX() + EXTRA
set maxy=GetCameraBoundMaxY() + EXTRA
set rc=Rect(minx,miny,maxx,maxy)
call RegionAddRect(r, rc)
call RemoveRect(rc)
call TriggerRegisterLeaveRegion(t,r, null)
call TriggerAddAction(t, function dis)
//this is not necessary but I'll do it anyway:
set t=null
set r=null
set rc=null
endfunction
endlibrary
//TESH.scrollpos=43
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Alloc ~~ By Sevion ~~ Version 1.09 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Alloc?
// - Alloc implements an intuitive allocation method for array structs
//
// =Pros=
// - Efficient.
// - Simple.
// - Less overhead than regular structs.
//
// =Cons=
// - Must use array structs (hardly a con).
// - Must manually call OnDestroy.
// - Must use Delegates for inheritance.
// - No default values for variables (use onInit instead).
// - No array members (use another Alloc struct as a linked list or type declaration).
//
// Methods:
// - struct.allocate()
// - struct.deallocate()
//
// These methods are used just as they should be used in regular structs.
//
// Modules:
// - Alloc
// Implements the most basic form of Alloc. Includes only create and destroy
// methods.
//
// Details:
// - Less overhead than regular structs
//
// - Use array structs when using Alloc. Put the implement at the top of the struct.
//
// - Alloc operates almost exactly the same as default structs in debug mode with the exception of onDestroy.
//
// How to import:
// - Create a trigger named Alloc.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Nestharus for the method of allocation and suggestions on further merging.
// - Bribe for suggestions like the static if and method names.
// - PurgeandFire111 for some suggestions like the merging of Alloc and AllocX as well as OnDestroy stuff.
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Alloc
module Alloc
private static integer instanceCount = 0
private thistype recycle
static method allocate takes nothing returns thistype
local thistype this
if (thistype(0).recycle == 0) then
debug if (instanceCount == 8190) then
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to allocate too many instances!")
debug return 0
debug endif
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = thistype(0).recycle
set thistype(0).recycle = thistype(0).recycle.recycle
endif
debug set this.recycle = -1
return this
endmethod
method deallocate takes nothing returns nothing
debug if (this.recycle != -1) then
debug call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Alloc ERROR: Attempted to deallocate an invalid instance at [" + I2S(this) + "]!")
debug return
debug endif
set this.recycle = thistype(0).recycle
set thistype(0).recycle = this
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
Firstly and Importantly, you must copy paste all the triggers in the (External) Category to your map.
Copy paste all of the contents of the trigger "Fireball 112" below to an empty trigger in your map.
Change the values to your needs that are in the frame:
//====================================================================================================
// User-edit data //
//====================================================================================================
Copy this data from the Object Editor:
UNITS:
Custom Units
|
--Neutral Passive
|
--Melee
|
--Units
|-- Fire Missile (Missile)
|-- Fire Missile (Nova)
ABILITIES: (Optional)
Custom Abilities
|
--Neutral Hostile
|
--Heroes
|
-- Fireball (Fire Nova)
//TESH.scrollpos=333
//TESH.alwaysfold=0
// Immolation Fireball Version 1.24
scope FNova initializer Init_IFireball
private keyword NovaData
private keyword MislData
private keyword ImmoData
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 = 18 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.03 // this will determine the missile speed
private constant real N_TIMER_INTERVAL = 0.02 // this will determine the nova expand speed
private constant real I_TIMER_INTERVAL = 0.1 // this will determine the immolation damage frequency
private constant real M_DIST = 32.00 // missile step
private constant real N_DIST = 16.00 // nova expand step
private constant real dA = 360/NOVA_SIZE
private constant real K = 60.00
private constant string UnitModel = "Abilities\\Spells\\Other\\BreathOfFire\\BreathOfFireDamage.mdl"
private constant string BuildingModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeEmbers.mdl"
private constant string UAttPoint = "chest"
private constant string BAttPoint = "sprite"
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private timer itm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private ImmoData array temp_idat
private integer mindex = 0
private integer nindex = 0
private integer iindex = 0
private group TempGroup = CreateGroup()
private NovaData iFilter
private hashtable Nova_Flag = InitHashtable()
//====================================================================================================
// User-edit data //
//====================================================================================================
// Make sure to change the dummy spell text to be appropriate with the following variables.
// General Formula: ConstantFactor + AbilityLevel * AbilityLevelFactor + PrevLevelFactor * PrevLevelValue
// The following variable can be changed according to the desired results
// Damage Variables:
private constant boolean D_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array Damage // set the values in the function named "Spell_Data_Table"
// Formula:
private constant real D_CONST_FACTOR = 50.00 // changes 'ConstantFactor'
private constant real D_LEVEL_FACTOR = 50.00 // changes 'AbilityLevelFactor'
private constant real D_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Area of Effect (AoE) Variables:
private constant boolean R_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array Range // set the values in the function named "Spell_Data_Table"
// Formula:
private constant real R_CONST_FACTOR = 500.00 // changes 'ConstantFactor'
private constant real R_LEVEL_FACTOR = 0.00 // changes 'AbilityLevelFactor'
private constant real R_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Range can be edited from the dummy spell
// Targets:
private constant boolean FRIENDLY = TRUE // TRUE/FALSE to harm enemy/all units
private constant boolean GROUND = TRUE // TRUE/FALSE to include/exclude ground units
private constant boolean FLYING = TRUE // TRUE/FALSE to include/exclude flying units
private constant boolean STRUCTURE = TRUE // TRUE/FALSE to include/exclude structure units
// Factors
private constant real UNIT_FACTOR = 1.00 // Unit damage factor.
private constant real BUILDN_FACTOR = 0.75 // Building damage factor.
// this will be multiplied with the spell damage
// Becareful -ve values will heal.
// Destroy Trees/Destructibles
// Sorry, not done yet !!
// Immolation (Damage Over Time)
private constant boolean IMMOLATION = TRUE // TRUE/FALSE to Allow/Disallow Immolation (Damage Over Time)
// Immolation Damage (ID) [per 1 Second]
private constant boolean ID_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array ImmoDmg // set the values in the function named "Spell_Data_Table"
// Formula
private constant real ID_CONST_FACTOR = 00.00 // changes 'ConstantFactor'
private constant real ID_LEVEL_FACTOR = 01.00 // changes 'AbilityLevelFactor'
private constant real ID_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
// Immolation Length(Duration) (IL) [in seconds]
private constant boolean IL_TABLE = FALSE // TRUE/FALSE to use Table/Formula
// Table:
private constant real array ImmoDur // set the values in the function named "Spell_Data_Table"
// Formula
private constant real IL_CONST_FACTOR = 05.00 // changes 'ConstantFactor'
private constant real IL_LEVEL_FACTOR = 05.00 // changes 'AbilityLevelFactor'
private constant real IL_PREV_LVL_FACTOR = 0 // changes 'PrevLevelFactor'
private constant real CASTER_HAND_Z = 64.00 // This value controls the height at which the missile will appear relative to the caster. Change it according to the model and its scale
//====================================================================================================
// The following variables can also be changed but will affect the spell
// This is the Attack type and damage type; they are affected
//by the type of the target unit's armor.
private constant attacktype ATKTYPE = ATTACK_TYPE_NORMAL // Spell Attack Type
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE // Fire Damage Type
endglobals
function Spell_Data_Table takes nothing returns nothing
// If your spell is more than 3 levels just add Damage[]/Range[]/ImmoDmg[]/ImmoDur[] under its appropriate place
// Remember that if you don't add this line the Damage/Range/ImmoDmg/ImmoDur will be 0 for level 4+
// Damage Table
set Damage[1] = 50.0
set Damage[2] = 100.0
set Damage[3] = 200.0
// Range Table
set Range[1] = 500.0
set Range[2] = 500.0
set Range[3] = 500.0
// Immolation Damage Table
set ImmoDmg[1] = 2.0
set ImmoDmg[2] = 4.0
set ImmoDmg[3] = 8.0
// Immolation Duration Table
set ImmoDur[1] = 10.0
set ImmoDur[2] = 15.0
set ImmoDur[3] = 30.0
//====================================================================================================
// End of User-edit data //
//====================================================================================================
endfunction
function NovaDamage takes integer al returns real
local real prevDmg
if D_TABLE then
return Damage[al]
else
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage(al - 1)
endif
return D_CONST_FACTOR + D_LEVEL_FACTOR * al + D_PREV_LVL_FACTOR * prevDmg
endif
endfunction
function NovaRadius takes integer al returns real
local real prevRad
if R_TABLE then
return Range[al]
else
if al == 1 then
set prevRad = 0
else
set prevRad = NovaRadius(al - 1)
endif
return R_CONST_FACTOR + R_LEVEL_FACTOR * al + R_PREV_LVL_FACTOR * prevRad
endif
endfunction
function ImmoDamage takes integer al returns real
local real prevIDmg
if ID_TABLE then
return ImmoDmg[al]
else
if al == 0 then
set prevIDmg = 0
else
set prevIDmg = ImmoDamage(al - 1)
endif
return ID_CONST_FACTOR + ID_LEVEL_FACTOR * al + ID_PREV_LVL_FACTOR * prevIDmg
endif
endfunction
function ImmoDuration takes integer al returns real
local real prevIDur
if IL_TABLE then
return ImmoDur[al]
else
if al == 0 then
set prevIDur = 0
else
set prevIDur = ImmoDuration(al - 1)
endif
return IL_CONST_FACTOR + IL_LEVEL_FACTOR * al + IL_PREV_LVL_FACTOR * prevIDur
endif
endfunction
private struct ImmoData extends array
unit caster
unit target
integer executecount
real damage
real duration
effect FX
implement Alloc
static method Interval takes nothing returns nothing
local thistype dat
local integer i = 0
loop
exitwhen i >= iindex
set dat = temp_idat[i]
set dat.executecount = dat.executecount + 1
if dat.executecount > dat.duration/I_TIMER_INTERVAL then
set iindex = iindex - 1
set temp_idat[i] = temp_idat[iindex]
set i = i - 1
set dat.caster = null
set dat.target = null
set dat.executecount = 0
call DestroyEffect(dat.FX)
set dat.FX = null
call dat.deallocate()
if iindex == 0 then
call PauseTimer(itm)
endif
else
if IsUnitType(dat.target,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.caster,dat.target,BUILDN_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(BuildingModel,dat.target,BAttPoint)
endif
else
call UnitDamageTarget(dat.caster,dat.target, UNIT_FACTOR*dat.damage,false,false,ATKTYPE,DMGTYPE,null)
if dat.FX == null then
set dat.FX = AddSpecialEffectTarget(UnitModel,dat.target,UAttPoint)
endif
endif
endif
set i = i + 1
endloop
endmethod
static method StartDoT takes unit caster,unit target, real damage, real duration returns nothing
local thistype dat = thistype.allocate()
local integer i = 0
local unit temp_u
set temp_idat[iindex] = dat
set dat.caster = caster
set dat.target = target
set dat.executecount = 0
set dat.duration = duration
set dat.damage = damage
if iindex == 0 then
call TimerStart(itm, I_TIMER_INTERVAL , true , function thistype.Interval )
endif
set iindex = iindex + 1
endmethod
endstruct
private struct NovaData extends array
unit Caster
real expand
real X
real Y
player Owner
real dmg
real rad
real IDamage
real IDuration
implement Alloc
static method MatchingUnit takes unit u returns boolean
if IsUnitType(u,UNIT_TYPE_DEAD) or/*
*/ IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE) or/*
*/( LoadBoolean(Nova_Flag, iFilter, GetHandleId(u))) or/*
*/( FRIENDLY and IsUnitAlly(u,iFilter.Owner)) or/*
*/(not FLYING and IsUnitType(u,UNIT_TYPE_FLYING)) or/*
*/(not GROUND and IsUnitType(u,UNIT_TYPE_GROUND)) or/*
*/(not STRUCTURE and IsUnitType(u,UNIT_TYPE_STRUCTURE)) then
return false
endif
return true
endmethod
static method NovaExpand takes nothing returns nothing
local NovaData dat
local integer i = 0
local integer j
local real X
local real Y
local real A
local unit u
local unit n
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 // loop for moving the nova units
exitwhen j >= NOVA_SIZE
set X = dat.X + dat.expand * Cos( A * bj_DEGTORAD )
set Y = dat.Y + dat.expand * Sin( A * bj_DEGTORAD )
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call SetUnitX(n,X)
call SetUnitY(n,Y)
set A = A + dA
set j = j + 1
endloop
// Nova Damage
call GroupEnumUnitsInRange(TempGroup, dat.X, dat.Y, dat.expand, null)
set iFilter = dat
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
if MatchingUnit(u) then
if IsUnitType(u,UNIT_TYPE_STRUCTURE) then
call UnitDamageTarget(dat.Caster, u, BUILDN_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
else
call UnitDamageTarget(dat.Caster, u, UNIT_FACTOR*dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
endif
if IMMOLATION == true and GetWidgetLife(u) >= 0.405 then
call ImmoData.StartDoT(dat.Caster,u,dat.IDamage,dat.IDuration)
endif
call SaveBoolean(Nova_Flag,dat,GetHandleId(u),true)
endif
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= dat.rad 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
set j = 0
loop
exitwhen j >= NOVA_SIZE
set n = LoadUnitHandle( Nova_Flag , - dat , j )
call KillUnit(n)
set dat.expand = 0
set j = j + 1
endloop
call FlushChildHashtable( Nova_Flag , - dat )
call FlushChildHashtable( Nova_Flag , dat )
call dat.deallocate()
if nindex == 0 then
call PauseTimer(ntm)
endif
endif
set i = i + 1
endloop
set n = null
endmethod
static method NovaCreate takes unit caster,real damage,real radius,real idamage,real iduration,real posX,real posY returns nothing
local NovaData dat = NovaData.allocate()
local integer i = 0
local real A = 0.00
local unit u
set dat.Caster = caster
set dat.Owner = GetOwningPlayer(caster)
set dat.X = posX
set dat.Y = posY
set dat.dmg = damage
set dat.rad = radius
set dat.IDamage = idamage
set dat.IDuration = iduration
loop
exitwhen i >= NOVA_SIZE
set u = CreateUnit( dat.Owner , N_UNIT_ID , dat.X , dat.Y , A )
call SaveUnitHandle( Nova_Flag , - dat , i , u )
set A = A + dA
set i = i + 1
endloop
set u = null
if nindex == 0 then
call TimerStart(ntm,N_TIMER_INTERVAL,true,function NovaData.NovaExpand)
endif
set temp_ndat[nindex] = dat
set nindex = nindex + 1
endmethod
endstruct
private struct MislData extends array
unit Caster
unit Missile
real CastPointX
real CastPointY
real Damage
real Radius
real IDamage
real IDuration
real face
real a
real h
real k
real v1
real x1
real y1
implement Alloc
static method MissileMove takes nothing returns nothing
local MislData dat
local integer i = 0
local real x = 0
local real y = 0
local real z
local real x2 = 0
local real y2 = 0
local real dx = 0
local real dy = 0
local real v
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set x = GetUnitX(dat.Missile)
set y = GetUnitY(dat.Missile)
set x2 = dat.CastPointX
set y2 = dat.CastPointY
set dx = x2 - x
set dy = y2 - y
if SquareRoot(dx*dx + dy*dy) < M_DIST then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.NovaCreate(dat.Caster,dat.Damage,dat.Radius,dat.IDamage,dat.IDuration,x,y)
call KillUnit(dat.Missile)
set dat.Missile = null
set dat.face = 0
call dat.deallocate()
if mindex == 0 then
call PauseTimer(mtm)
endif
else
set x = x + M_DIST * Cos(dat.face)
set y = y + M_DIST * Sin(dat.face)
set dx = x - dat.x1
set dy = y - dat.y1
set v = dat.v1 + SquareRoot(dx*dx + dy*dy)
set z = (dat.a * ( v - dat.h ) * ( v - dat.h )) + dat.k
call SetUnitPosition(dat.Missile,x,y)
call SetUnitFlyHeight(dat.Missile,z,0.0)
endif
set i = i + 1
endloop
endmethod
static method MissileCreate takes unit u , real X , real Y returns nothing
local MislData dat = MislData.allocate()
local integer al = GetUnitAbilityLevel(u , ABILTY_ID)
local real x1 = 0.0
local real y1 = 0.0
local real x2 = 0.0
local real y2 = 0.0
local real dx = 0.0
local real dy = 0.0
local real z1 = 0.0
local real v1 = 0.0
local real z2 = 0.0
local real v2 = 0.0
local real phi = 0.0
local real dist = 0.0
local real error = 0.0
set temp_mdat[mindex] = dat
set x1 = GetUnitX(u)
set dat.x1 = x1
set y1 = GetUnitY(u)
set dat.y1 = y1
// Fail-Safe in case the caster and the cast location is at points (x=[-1,1],y=[-1,1])
if ((x1 >= -1 and x1 <= 1) and (y1 >= -1 and y1 <= 1) and X == x1 and Y == y1) then
set error = 1.0
endif
set z1 = CASTER_HAND_Z
set dat.k = GetUnitFlyHeight(u) + z1 + K // in case of flying units
set x2 = X + error
set y2 = Y + error
set z2 = 0.0
set phi = SquareRoot((z2 - dat.k)/(z1 - dat.k))
set v1 = SquareRoot(x1*x1 + y1*y1)
set dat.v1 = v1
set dx = x2 - x1
set dy = y2 - y1
set dat.Caster = u
set dat.CastPointX = X
set dat.CastPointY = Y
set dist = SquareRoot(dx * dx + dy * dy)
set dat.face = Atan2(y2 - y1, x2 - x1)
set v2 = v1 + dist
set dat.h = ((phi*v1) + v2)/(1.0 + phi)
set dat.a = (z2 - dat.k)/((dat.h - v2)*(dat.h - v2))
set dat.Missile = CreateUnit(GetOwningPlayer(u),M_UNIT_ID,x1,y1,dat.face*bj_RADTODEG)
call SetUnitFlyHeight(dat.Missile,z1,0.0)
set dat.Damage = NovaDamage(al)
set dat.Radius = NovaRadius(al)
set dat.IDamage = ImmoDamage(al) * I_TIMER_INTERVAL
set dat.IDuration = ImmoDuration(al)
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MissileMove)
endif
set mindex = mindex + 1
endmethod
endstruct
private function FB_Actions takes nothing returns nothing
if GetSpellAbilityId() == ABILTY_ID then
call MislData.MissileCreate(GetTriggerUnit(), GetSpellTargetX(),GetSpellTargetY())
endif
endfunction
private function Init_IFireball takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddAction(t,function FB_Actions)
call Spell_Data_Table()
//Preload the dummy units to reduce lag on first cast
call RemoveUnit(CreateUnit(Player(12),M_UNIT_ID,0.,0.,0.))
call RemoveUnit(CreateUnit(Player(12),N_UNIT_ID,0.,0.,0.))
endfunction
endscope