- Joined
- Mar 3, 2006
- Messages
- 1,564
Hello, vJASSers
I have asked many vJASSers about learning vJASS but every time I code a spell I fail.
Once before I asked for making a missile spell then after that I asked for making a Nova Spell. I tried to combine between the 2 spells. It worked but on a separate 2 trigger and linked them through some functions.
Now, I was attempting to make the spell in one trigger but it doesn't work. I know I asked too much about vJASS but please tell me what's wrong with my second script.
First Script (2 Separate Triggers)
I know that I used this script more than once in my threads but I do that to learn completely how to make AoE spells (Target and self Target) using vJASS. So please vJASSers don't lose your patience or temper.
And thanks for any help in advance.
I have asked many vJASSers about learning vJASS but every time I code a spell I fail.
Once before I asked for making a missile spell then after that I asked for making a Nova Spell. I tried to combine between the 2 spells. It worked but on a separate 2 trigger and linked them through some functions.
Now, I was attempting to make the spell in one trigger but it doesn't work. I know I asked too much about vJASS but please tell me what's wrong with my second script.
First Script (2 Separate Triggers)
JASS:
scope SpellTemplate initializer Init
private keyword Data
globals
private constant real TIMER_INTERVAL = 0.03
private constant real DIST = 32 // value of the distance cut every timer interval high value means high speed
private constant integer ABIL_ID = 'A000' //change this to the rawcode of your spell
private constant integer UNIT_ID = 'e000' // rawcode of the dummy (Missile) unit
//Other constant globals here...
private Data array data
private integer index = 0
private timer tim
// Other changable globals here...
endglobals
private function Execute takes nothing returns nothing
local integer i = 0
local Data d
local location missilePoint
local location stepPoint
// Other local variables here...
loop
exitwhen i >= index
set d = data[i]
set missilePoint = GetUnitLoc(d.missile)
if DistanceBetweenPoints(missilePoint, d.CastPoint) < 25 then
call d.destroy()
call CreateNova(d.caster,GetLocationX(d.CastPoint),GetLocationY(d.CastPoint))
else
set stepPoint = PolarProjectionBJ(missilePoint, DIST, AngleBetweenPoints(missilePoint, d.CastPoint))
call SetUnitPositionLoc(d.missile, stepPoint)
call RemoveLocation(stepPoint)
endif
call RemoveLocation(missilePoint)
set i = i + 1
endloop
//Any leak cleaning code here...
endfunction
private struct Data
//Declare struct members here...
unit caster
unit missile
integer ID
location CastPoint
static method create takes unit caster, location target returns Data //make sure you change this based on what data you need
local Data d = Data.allocate()
//Other create code here...
set data[index] = d
set d.ID = index
set d.CastPoint = target
set d.caster = caster
set d.missile = CreateUnit(GetOwningPlayer(d.caster), UNIT_ID, GetUnitX(d.caster), GetUnitY(d.caster), 0)
call SetUnitPosition(d.missile, GetUnitX(d.caster), GetUnitY(d.caster))
if index == 0 then
call TimerStart(tim, TIMER_INTERVAL, true, function Execute)
endif
set index = index + 1
return d
endmethod
method onDestroy takes nothing returns nothing
set index = index-1
set data[this.ID] = data[index]
set data[this.ID].ID = this.ID
if index==0 then
call PauseTimer(tim)
endif
//Other destroy code here (such as leak cleaning, removing units etc)...
call KillUnit(this.missile)
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABIL_ID
endfunction
private function Actions takes nothing returns nothing
call Data.create(GetTriggerUnit(), GetSpellTargetLoc()) //make sure you change this based on what data your spell needs
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddAction(t, function Actions)
call TriggerAddCondition(t, Condition(function Conditions))
set tim = CreateTimer()
//Other initializations things here...
endfunction
endscope
JASS:
library AoETemplate initializer Init
private keyword Data
globals
// Constants
private constant real TIMER_INTERVAL = 0.015
private constant real DIST = 16.00
private constant real NOVA_RADIUS = 512.00 // radius of the Nova
private constant integer NOVA_SIZE = 36 // number of the Nova Units
private constant real dA = 360/NOVA_SIZE
private constant integer UNIT_ID = 'e001' // rawcode of the Nova Unit
private constant integer ABIL_ID = 'A000' // rawcode of the Dummy Spell
private constant attacktype ATKTYPE = ATTACK_TYPE_MAGIC
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
private constant real AB_CONST_FACTOR = 50.00
private constant real AB_LEVEL_FACTOR = 50.00
private constant real AB_PREV_LVL_FACTOR = 0
// Variables
private timer tm = CreateTimer()
private Data array temp_dat
private integer index = 0
private Data iFilter // Filter Data
private boolexpr fFilter // Filter function
private group TempGroup = CreateGroup()
endglobals
function Damage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = Damage.evaluate(al -1)
endif
return AB_CONST_FACTOR + AB_LEVEL_FACTOR * al + AB_PREV_LVL_FACTOR * prevDmg
endfunction
private struct Data
unit Caster
unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup = CreateGroup() // Damaged Units Group
real dmg
static method NovaExpand takes nothing returns nothing
local thistype dat
local integer i = 0
local integer j
local real x
local real y
local real a
local unit u
loop // this loop cycles through all the casters which have cast the spell
exitwhen i >= index
set dat = temp_dat[i]
// Nova Expanding
set j = 0
set a = 0
set dat.expand = dat.expand + DIST
loop
exitwhen j >= NOVA_SIZE
set x = dat.Cx + dat.expand * Cos( a * bj_DEGTORAD )
set y = dat.Cy + dat.expand * Sin( a * bj_DEGTORAD )
call SetUnitX( dat.Nova[j] , x )
call SetUnitY( dat.Nova[j] , y )
set j = j + 1
set a = a + dA
endloop
// Damage Units that the nova has reached
set iFilter = dat
call GroupEnumUnitsInRange(TempGroup, dat.Cx, dat.Cy, dat.expand, fFilter)
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
call UnitDamageTarget(dat.Caster, u, dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= NOVA_RADIUS then // check if the nova has reached its max AoE
set index = index - 1
set temp_dat[i] = temp_dat[index]
set i = i - 1
call dat.destroy()
endif
set i = i + 1
endloop
set u = null
endmethod
static method create takes unit caster , real posX, real posY returns Data
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(GetUnitAbilityLevel(dat.Caster,ABIL_ID))
// the following function displays a msg of the amount of damage that the spell deals
// make sure when you use it to remove the following function or add "//" before it
//call DisplayTimedTextToPlayer(dat.Owner,0,0,10,"|cffff0000" + R2S(dat.dmg) + "|r")
loop
exitwhen i >= NOVA_SIZE
set dat.Nova[i] = CreateUnit( dat.Owner , UNIT_ID , dat.Cx , dat.Cy , A )
set A = A + dA
set i = i + 1
endloop
if index == 0 then
call TimerStart(tm,TIMER_INTERVAL,true,function Data.NovaExpand)
endif
set temp_dat[index] = dat
set index = index + 1
return dat
endmethod
static method FilterUnit takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) >= .305 and IsUnitEnemy(GetFilterUnit(),iFilter.Owner) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitInGroup(GetFilterUnit(),iFilter.dGroup)
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= NOVA_SIZE
call KillUnit(.Nova[i])
set .Nova[i] = null
set .expand = 0
set i = i + 1
endloop
if index == 0 then
call PauseTimer(tm)
endif
endmethod
endstruct
function CreateNova takes unit caster , real x , real y returns nothing
call Data.create(caster,x,y)
endfunction
private function Init takes nothing returns nothing
set fFilter = Filter(function Data.FilterUnit)
endfunction
endlibrary
JASS:
scope FireNova initializer Init
private keyword NovaData
private keyword MislData
globals
// Constants
private constant integer ABIL_ID = 'A000' // rawcode of the Dummy Spell
private constant integer M_UNIT_ID = 'e000' // rawcode of the Missile Unit
private constant integer N_UNIT_ID = 'e001' // rawcode of the Nova Unit
private constant integer NOVA_SIZE = 36 // number of the Nova Units
private constant real M_TIMER_INTERVAL = 0.015
private constant real N_TIMER_INTERVAL = 0.015
private constant real M_DIST = 16.00
private constant real N_DIST = 16.00
private constant real NOVA_RADIUS = 544.00 // radius of the Nova
private constant real dA = 360/NOVA_SIZE
private constant real AB_CONST_FACTOR = 50.00
private constant real AB_LEVEL_FACTOR = 50.00
private constant real AB_PREV_LVL_FACTOR = 1
private constant attacktype ATKTYPE = ATTACK_TYPE_MAGIC
private constant damagetype DMGTYPE = DAMAGE_TYPE_FIRE
// Variables
private timer mtm = CreateTimer()
private timer ntm = CreateTimer()
private MislData array temp_mdat
private NovaData array temp_ndat
private integer mindex = 0
private integer nindex = 0
private NovaData iFilter // Filter Data
private boolexpr fFilter // Filter function
private group TempGroup = CreateGroup()
endglobals
function NovaDamage takes integer al returns real
local real prevDmg
if al == 1 then
set prevDmg = 0
else
set prevDmg = NovaDamage.evaluate(al -1)
endif
return AB_CONST_FACTOR + AB_LEVEL_FACTOR * al + AB_PREV_LVL_FACTOR * prevDmg
endfunction
private struct NovaData
unit Caster
unit array Nova[NOVA_SIZE]
real expand
real Cx
real Cy
player Owner
group dGroup = CreateGroup() // Damaged Units Group
real dmg
static method NovaExpand takes nothing returns nothing
local thistype dat
local integer i = 0
local integer j
local real x
local real y
local real a
local unit u
loop // this loop cycles through all the casters which have cast the spell
exitwhen i >= nindex
set dat = temp_ndat[i]
// Nova Expanding
set j = 0
set a = 0
set dat.expand = dat.expand + N_DIST
loop
exitwhen j >= NOVA_SIZE
set x = dat.Cx + dat.expand * Cos( a * bj_DEGTORAD )
set y = dat.Cy + dat.expand * Sin( a * bj_DEGTORAD )
call SetUnitX( dat.Nova[j] , x )
call SetUnitY( dat.Nova[j] , y )
set j = j + 1
set a = a + dA
endloop
// Damage Units that the nova has reached
set iFilter = dat
call GroupEnumUnitsInRange(TempGroup, dat.Cx, dat.Cy, dat.expand, fFilter)
loop
set u = FirstOfGroup(TempGroup)
exitwhen u == null
call GroupAddUnit(dat.dGroup, u)
call UnitDamageTarget(dat.Caster, u, dat.dmg, false, false, ATKTYPE, DMGTYPE, null)
call GroupRemoveUnit(TempGroup, u)
endloop
if dat.expand >= NOVA_RADIUS then // check if the nova has reached its max AoE
set nindex = nindex - 1
set temp_ndat[i] = temp_ndat[nindex]
set i = i - 1
call dat.destroy()
endif
set i = i + 1
endloop
set u = null
endmethod
static method create takes player p , real damage , real posX, real posY returns NovaData
local thistype dat = thistype.allocate()
local integer i = 0
local real A = 0.00
set dat.Owner = p
set dat.Cx = posX
set dat.Cy = posY
set dat.dmg = damage
call DisplayTimedTextToPlayer(dat.Owner,0,0,10,"|cffff0000" + R2S(dat.dmg) + "|r")
loop
exitwhen i >= NOVA_SIZE
set dat.Nova[i] = CreateUnit( dat.Owner , N_UNIT_ID , dat.Cx , dat.Cy , A )
set A = A + dA
set i = i + 1
endloop
if nindex == 0 then
call TimerStart(ntm,N_TIMER_INTERVAL,true,function NovaData.NovaExpand)
endif
set temp_ndat[nindex] = dat
set nindex = nindex + 1
return dat
endmethod
static method FilterUnit takes nothing returns boolean
return GetWidgetLife(GetFilterUnit()) >= .305 and IsUnitEnemy(GetFilterUnit(),iFilter.Owner) and not IsUnitType(GetFilterUnit(),UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitInGroup(GetFilterUnit(),iFilter.dGroup)
endmethod
method onDestroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= NOVA_SIZE
call KillUnit(.Nova[i])
set .Nova[i] = null
set .expand = 0
set i = i + 1
endloop
if nindex == 0 then
call PauseTimer(ntm)
endif
endmethod
endstruct
private struct MislData
unit Missile
player Owner
location CastPoint
real Damage
real face
static method MoveMissile takes nothing returns nothing
local MislData dat
local integer i = 0
local location MLoc
loop
exitwhen i >= mindex
set dat = temp_mdat[i]
set MLoc = GetUnitLoc(dat.Missile)
call DisplayTimedTextToPlayer(Player(0),0,0,6,R2S(DistanceBetweenPoints(MLoc,dat.CastPoint)))
if DistanceBetweenPoints(MLoc , dat.CastPoint) < 64 then
set mindex = mindex - 1
set temp_mdat[i] = temp_mdat[mindex]
set i = i - 1
call NovaData.create(dat.Owner , dat.Damage , GetLocationX(MLoc) , GetLocationY(MLoc))
call dat.destroy()
endif
call SetUnitX(dat.Missile , GetLocationX(MLoc) + M_DIST * Cos(bj_DEGTORAD * dat.face))
call SetUnitY(dat.Missile , GetLocationY(MLoc) + M_DIST * Sin(bj_DEGTORAD * dat.face))
call RemoveLocation(MLoc)
set i = i + 1
endloop
endmethod
static method create takes unit u , location target returns MislData
local thistype dat = thistype.allocate()
local real X
local real Y
set dat.CastPoint = target
set dat.Owner = GetOwningPlayer(u)
set dat.face = AngleBetweenPoints(GetUnitLoc(u) , dat.CastPoint)
set dat.Missile = CreateUnit( dat.Owner , M_UNIT_ID , GetUnitX(u) , GetUnitY(u) , dat.face )
set dat.Damage = NovaDamage(GetUnitAbilityLevel(u , ABIL_ID))
if mindex == 0 then
call TimerStart(mtm,M_TIMER_INTERVAL,true,function MislData.MoveMissile)
endif
set temp_mdat[mindex] = dat
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 Conditions takes nothing returns boolean
return GetSpellAbilityId() == ABIL_ID
endfunction
private function Actions takes nothing returns nothing
call MislData.create(GetTriggerUnit(), GetSpellTargetLoc())
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(t,Condition(function Conditions))
call TriggerAddAction(t,function Actions)
set fFilter = Filter(function NovaData.FilterUnit)
endfunction
endscope
I know that I used this script more than once in my threads but I do that to learn completely how to make AoE spells (Target and self Target) using vJASS. So please vJASSers don't lose your patience or temper.
And thanks for any help in advance.