- Joined
- Jan 28, 2012
- Messages
- 266
I am having trouble with a spell meteor shower that I am making,it is not running properly it does not create the meteors.
edit: uploaded an example map
Edit: SOLVED
Edit3: New bug, see last post
JASS:
private function ep takes nothing returns nothing
local spelleffect this = next[0]
local Target t
local spelleffect i
local real angle
local real dis
call BJDebugMsg("its working")
loop
exitwhen 0 == this
set time[this] = time[this]-PERIOD
if time[this]<= 0 then
set angle = GetRandomReal(Sangle[this],Eangle[this])
set dis = GetRandomReal(0,distance[this])
set t = Target.create(this.target.x+Cos(angle)*dis,this.target.y+Sin(angle)*dis,0)
call BJDebugMsg("Target is " + I2S(t))
//call BJDebugMsg("t.x ="+R2S(t.x)+" t.y="+R2S(t.y)+"|| tar.x="+R2S(this.target.x)+" tar.y="+R2S(this.target.y))
set i = spelleffect.createProxy(this,this.caster, t)
//call BJDebugMsg("proxy.t.x="+R2S(i.target.x))
call this.spell.core(i)
// call BJDebugMsg("Proxy Ran Successfully")
set left[this]= left[this]-1
if left[this]<= 0 then
set next[prev[this]]=next[this]
set prev[next[this]]=prev[this]
call this.spell.unlock()//this is neccessary as it always calls back to the core via proxy
if this.isProxy then
call this.destroy()//also neccessary
endif
else
set time[this] = time[this]+this[1]
endif
endif
set this = next[this]
endloop
if next[0] != 0 then
call TimerStart(EP_Timer,PERIOD,false,function ep)
endif
endfunction
function ep_cast takes nothing returns boolean
local spelleffect this = RUNNING
local real face = GetUnitFacing(this.spell.caster.unit)
call BJDebugMsg("checking if it is already running")
if next[0] == 0 then
call BJDebugMsg("Nope, it wasn't")
call TimerStart(EP_Timer,PERIOD,false,function ep)
endif
call BJDebugMsg("Still not broken yet")
set next[this] = 0
set prev[this] = prev[0]
set next[prev[this]]=this
set prev[0] = this
call this.spell.lock()
set distance[this] = this[2]
set Sangle[this] = (face-this[3])*bj_DEGTORAD
set Eangle[this] = (face+this[3])*bj_DEGTORAD
set left[this] = R2I(this[0])
call BJDebugMsg("left[this]="+I2S(left[this]))
call ReturnEffect(false)
return true
endfunction
JASS:
method core takes spelleffect current returns boolean
local spelleffect Snext
local integer next
debug call BJDebugMsg("Running core for "+I2S(current))
if current < 0 then
set next = 1
set Snext = this[0]
else
set next = current.next
if current.isProxy then
debug call BJDebugMsg(I2S(current)+" is a Proxy")
//debug call BJDebugMsg("Getting Next Proxy")
debug call BJDebugMsg("Getting Next Proxy")
if current.next != 0 then
set Snext = spelleffect.createProxy(this[next],current.caster, current.target)
endif
call BJDebugMsg("In core Target is " + I2S(Snext.target))
debug call BJDebugMsg("Succsessful")
//call Snext.target.lock()
call current.destroy()
else
set Snext = this[next]
endif
endif
if next == 0 then
debug call BJDebugMsg("there are no effects left, unlocking")
call unlock()
return true
endif
debug call BJDebugMsg("Running core, attempting to run effect " + I2S(Snext.next -1))
if Snext.run() then
debug call BJDebugMsg("The effect ran, going to next effect")
call core(this[next])
return false
endif
call BJDebugMsg("Snext Ran")
debug call BJDebugMsg("The effect ran, and is waiting to finish")
return false
endmethod
JASS:
library SpellGenerator /* v0.2.3.0
*************************************************************************************
*
* Enables the generation of spells in game and can also be used
* to easily make new spells with just a few keystrokes
*
*************************************************************************************
*
* */uses /*
* */ Target /*
* */ SFX /*
* */ Effects /*
* */ SpellProjectile/*
***************************************************************************************
*
* struct Spell extends array
* boolean permanent whether to keep or destroy the spell when it has no instances
*
* method operator [] takes integer i returns integer
* this retur
* method operator []= takes integer i integer returns nothing
* be warned you can leak effects if you do not unlock the effect first
* method lock takes nothing returns nothing
* locks the spell preventing it from getting destroyed
* method unlock takes nothing returns nothing
* when you are done with a spell you should unlock it
* has no effect on permanent spells
*
* static method createEx takes nothing returns Spell
*
*****/
private module allocator
static integer array recycle
static integer c = 0
static method allocate takes nothing returns thistype
local thistype this = recycle[0]
if this == 0 then
set this = c+1
set c = this
else
set recycle[0] = recycle[this]
endif
endmodule
private module deallocate
method deallocate takes nothing returns nothing
set recycle[this] = recycle[0]
set recycle[0] = this
endmethod
endmodule
private module serarray
spelleffect_root d0
spelleffect_root d1
spelleffect_root d2
spelleffect_root d3
method operator [] takes integer i returns spelleffect_root
if i < 2 then
if i == 0 then
return d0
endif
return d1
endif
if i == 2 then
return d2
endif
return d3
endmethod
method operator []= takes integer i, integer what returns nothing
if i < 2 then
if i ==0 then
set d0 = what
return
endif
set d1 = what
return
endif
if i == 2 then
set d2 = what
return
endif
set d3 = what
endmethod
endmodule
private module searray
spelleffect d0
spelleffect d1
spelleffect d2
spelleffect d3
method operator [] takes integer i returns spelleffect
if i < 2 then
if i == 0 then
return d0
endif
return d1
endif
if i == 2 then
return d2
endif
return d3
endmethod
method operator []= takes integer i, integer what returns nothing
if i < 2 then
if i ==1 then
set d1 = what
return
endif
set d0 = what
return
endif
if i == 2 then
set d2 = what
return
endif
set d3 = what
endmethod
endmodule
struct Spell_Cast extends array
Target caster
Target target
Spell root
//integer current
integer instance
integer effects
implement searray
implement allocator
set instance = 0
set effects = 0
return this
endmethod
implement deallocate
method lock takes nothing returns nothing
set .instance = .instance+1
endmethod
method destroy takes nothing returns nothing
call this[0].destroy()
call this[1].destroy()
call this[2].destroy()
call this[3].destroy()
call root.unlock()
call target.unlock()
call caster.unlock()
call deallocate()
endmethod
method unlock takes nothing returns nothing
set .instance = .instance-1
if .instance < 1 then
call destroy()
endif
endmethod
method core takes spelleffect current returns boolean
local spelleffect Snext
local integer next
debug call BJDebugMsg("Running core for "+I2S(current))
if current < 0 then
set next = 1
set Snext = this[0]
else
set next = current.next
if current.isProxy then
debug call BJDebugMsg(I2S(current)+" is a Proxy")
//debug call BJDebugMsg("Getting Next Proxy")
debug call BJDebugMsg("Getting Next Proxy")
if current.next != 0 then
set Snext = spelleffect.createProxy(this[next],current.caster, current.target)
endif
call BJDebugMsg("In core Target is " + I2S(Snext.target))
debug call BJDebugMsg("Succsessful")
//call Snext.target.lock()
call current.destroy()
else
set Snext = this[next]
endif
endif
if next == 0 then
debug call BJDebugMsg("there are no effects left, unlocking")
call unlock()
return true
endif
debug call BJDebugMsg("Running core, attempting to run effect " + I2S(Snext.next -1))
if Snext.run() then
debug call BJDebugMsg("The effect ran, going to next effect")
call core(this[next])
return false
endif
call BJDebugMsg("Snext Ran")
debug call BJDebugMsg("The effect ran, and is waiting to finish")
return false
endmethod
static method create takes Spell root, Target t returns thistype
local thistype this = allocate()
local integer i = 0
set target = t
call t.lock()
loop
if root[i] != 0 then
set this[i] = spelleffect.create( root[i], this)
set this[i].next = i+1
endif
set i = i+1
exitwhen i == 4
endloop
set .root = root
return this
endmethod
endstruct
struct Spell extends array
boolean permanent
private integer instance
implement serarray
implement allocator
return this
endmethod
implement deallocate
method destroy takes nothing returns nothing
call deallocate()
call this[0].unlock()
call this[1].unlock()
call this[2].unlock()
call this[3].unlock()
endmethod
static method create takes spelleffect_root first returns thistype
local thistype this = allocate()
set this[0] = first
return this
endmethod
static method createEx takes spelleffect_root s0, spelleffect_root s1, spelleffect_root s2, spelleffect_root s3, boolean destroy returns thistype
local thistype this = allocate()
call s0.lock()
call s1.lock()
call s2.lock()
call s3.lock()
set this[0] = s0
set this[1] = s1
set this[2] = s2
set this[3] = s3
set permanent = not destroy
return this
endmethod
method lock takes nothing returns nothing
set .instance = .instance+1
endmethod
method unlock takes nothing returns nothing
set .instance = .instance-1
if not permanent and .instance < 0 then
call destroy()
endif
endmethod
method cast takes unit caster, Target target returns boolean // the return value is whether the spell completed every thing instantly, or if it is waiting.
local Spell_Cast cast = Spell_Cast.create(this,target)
call lock()
call cast.lock()
set cast.caster = Target[caster]
call cast.caster.lock()
set cast.target = target
return cast.core(-1)
endmethod
endstruct
function CreateSpell takes spelleffect_root s0, spelleffect_root s1, spelleffect_root s2, spelleffect_root s3, boolean destroy returns Spell
local Spell this = Spell.allocate()
call s0.lock()
call s1.lock()
call s2.lock()
call s3.lock()
static if DEBUG_MOD then
if s0 == 0 then
call BJDebugMsg("Trying to create a spell with a null first effect")
return 0
endif
endif
set this[0] = s0
set this[1] = s1
set this[2] = s2
set this[3] = s3
set this.permanent = not destroy
return this
endfunction
endlibrary
JASS:
library Effects uses Target
globals
private force eval = CreateForce()
spelleffect RUNNING
spellprojectile PROJECTILE
private boolean FINISHED
endglobals
function ReturnEffect takes boolean continue returns nothing
set FINISHED = continue
endfunction
module Rarray
real d0
real d1
real d2
real d3
method operator [] takes integer i returns real
if i < 2 then
if i == 0 then
return d0
endif
return d1
endif
if i == 2 then
return d2
endif
return d3
endmethod
method operator []= takes integer i, real r returns nothing
if i < 2 then
if i == 0 then
set d0 = r
return
endif
set d1 = r
return
endif
if i == 2 then
set d2 = r
return
endif
set d3 = r
return
endmethod
endmodule
struct spelleffect_root
boolexpr action
integer instance
integer model
implement Rarray
static method create takes nothing returns thistype
local thistype this = allocate()
return this
endmethod
/*static method createEx takes boolexpr b, real d0, real d1, real d2, real d3 returns thistype
local thistype this = allocate()
set action = b
set this[0]= d0
set this[1]= d1
set this[2] = d2
set this[3] = d3
set instance = 0
return this
endmethod*/
method unlock takes nothing returns nothing
if this!= 0 then
set instance = instance-1
if instance < 1 then
call this.destroy()
endif
endif
endmethod
method lock takes nothing returns nothing
set instance = instance+1
endmethod
endstruct
struct spelleffect
boolexpr action
Spell_Cast spell
integer next
integer model
Target caster
Target target
spelleffect master
method destroy takes nothing returns nothing
if this.isProxy then
call target.unlock()
call caster.unlock()
call spell.unlock()
endif
call deallocate()
endmethod
method operator isProxy takes nothing returns boolean
return master != 0
endmethod
implement Rarray
static method create takes spelleffect_root root, Spell_Cast boss returns thistype
local thistype this = allocate()
set action = root.action
set this[0] = root[0]
set this[1] = root[1]
set this[2] = root[2]
set this[3] = root[3]
set this.spell = boss
set this.model = root.model
set this.target = boss.target
set this.master = 0
set this.caster = boss.caster
set boss[boss.effects]= this
set boss.effects = boss.effects+1
return this
endmethod
method run takes nothing returns boolean
set RUNNING = this
set FINISHED = true
call BJDebugMsg("running effect")
if Filter(function spellprojectile.meteor) == action then
call BJDebugMsg("action exists")
endif
call ForceEnumPlayersCounted(eval,action,1)
call BJDebugMsg("itran")
return FINISHED
endmethod
static method createProxy takes spelleffect master,Target caster, Target t returns thistype
local thistype this = allocate()
call master.spell.lock()
set .action = master.action
set this[0]= master[0]
set this[1]= master[1]
set this[2]= master[2]
set this[3]= master[3]
set .next = master.next
set .master = master
set .target = t
call t.lock()
set .caster = caster
return this
endmethod
endstruct
function CreateSpellEffect takes boolexpr b, real d0, real d1, real d2, real d3, integer model returns spelleffect_root
local spelleffect_root this = spelleffect_root.create()
set this.action = b
set this[0] = d0
set this[1] = d1
set this[2] = d2
set this[3] = d3
set this.model = model
return this
endfunction
endlibrary
JASS:
scope SpellTest initializer init
private function test_cast takes nothing returns boolean
if GetSpellAbilityId() == 'A001' then
debug call BJDebugMsg("casting Spell")
call EffectDepository_pillaroffire.cast(GetTriggerUnit(),Target.create(GetSpellTargetX(),GetSpellTargetY(),0))
debug call BJDebugMsg("Spell cast")
elseif GetSpellAbilityId() == 'A002' then
call BJDebugMsg("castingMeteor")
call EffectDepository_MeteorShower.cast(GetTriggerUnit(),Target.create(GetSpellTargetX(),GetSpellTargetY(),0))
endif
return false
endfunction
/*function Test_RandomSpell takes nothing returns boolean
local Spell_Main rspell CreateSpell(CreateSpellEffect(RegProjectile, 900, 150, 80, 0,GetSFX(SFX_FIRE_EFFECTS, 1, 6)),CreateSpellEffect(Filter(function pof_cast), 300, 15, 3, 0,GetSFX(SFX_FIRE_EFFECTS, 0, 4)),CreateSpellEffect(Filter(function pof_cast),300,5,12,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),0,false)
call BJDebugMsg("casting Spell")
if GetSpellAbilityId() == 'A002' then
endif
endfunction*/
function init takes nothing returns nothing
//debug call BJDebugMsg("Creating Spell PillarofFire")
set EffectDepository_pillaroffire = CreateSpell(CreateSpellEffect(RegProjectile, 900, 150, 0, 0,GetSFX(SFX_FIRE_EFFECTS, 1, 6)),CreateSpellEffect(Filter(function EffectDepository_pof_cast), 300, 15, 3, 0,GetSFX(SFX_FIRE_EFFECTS, 0, 4)),CreateSpellEffect(Filter(function EffectDepository_pof_cast),300,5,12,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),0,false)
//debug call BJDebugMsg("SpellCreated "+I2S(EffectDepository_pillaroffire))
//set EffectDepository_pillaroffire = CreateSpell(CreateSpellEffect(Filter(function spellprojectile.meteor), 1, 600, 0, 0,GetSFX(SFX_FIRE_EFFECTS, 1, 6)),CreateSpellEffect(Filter(function EffectDepository_pof_cast), 300, 15, 3, 0,GetSFX(SFX_FIRE_EFFECTS, 0, 4)),CreateSpellEffect(Filter(function EffectDepository_pof_cast),300,5,12,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),0,false)
// set EffectDepository_MeteorShower = CreateSpell(/*
// */CreateSpellEffect(Filter(function ep_cast),13,5.13,300,180,0),/*
// */CreateSpellEffect(Filter(function spellprojectile.meteor),1,1200,0,0,GetRandomSFX(SFX_MAGIC_EFFECTS, GetRandomInt(0,1))),/*
// */CreateSpellEffect(Filter(function EffectDepository_Pure_Damage),50,75,0,0,GetRandomSFX(SFX_MAGIC_EFFECTS, 0)),/*
// */0,false)
set EffectDepository_MeteorShower = CreateSpell(/*
*/CreateSpellEffect(Filter(function ep_cast),1,0.13,300,180,0),/*
*/CreateSpellEffect(Filter(function spellprojectile.meteor),1,600,0,0,GetSFX(SFX_FIRE_EFFECTS, 1, 3)),/*
*/0,0,false)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST,function test_cast)
endfunction
endscope
JASS:
library LibraryOfEffects uses Effects, SpellGenerator
globals
private spelleffect array next
private spelleffect array prev
private real array Sangle
private real array Eangle
private integer array left
private real array time
private real array distance
private timer EP_Timer = CreateTimer()
private constant real PERIOD = 2.0
endglobals
private function ep takes nothing returns nothing
local spelleffect this = next[0]
local Target t
local spelleffect i
local real angle
local real dis
call BJDebugMsg("its working")
loop
exitwhen 0 == this
set time[this] = time[this]-PERIOD
if time[this]<= 0 then
set angle = GetRandomReal(Sangle[this],Eangle[this])
set dis = GetRandomReal(0,distance[this])
set t = Target.create(this.target.x+Cos(angle)*dis,this.target.y+Sin(angle)*dis,0)
call BJDebugMsg("Target is " + I2S(t))
//call BJDebugMsg("t.x ="+R2S(t.x)+" t.y="+R2S(t.y)+"|| tar.x="+R2S(this.target.x)+" tar.y="+R2S(this.target.y))
set i = spelleffect.createProxy(this,this.caster, t)
//call BJDebugMsg("proxy.t.x="+R2S(i.target.x))
call this.spell.core(i)
// call BJDebugMsg("Proxy Ran Successfully")
set left[this]= left[this]-1
if left[this]<= 0 then
set next[prev[this]]=next[this]
set prev[next[this]]=prev[this]
call this.spell.unlock()//this is neccessary as it always calls back to the core via proxy
if this.isProxy then
call this.destroy()//also neccessary
endif
else
set time[this] = time[this]+this[1]
endif
endif
set this = next[this]
endloop
if next[0] != 0 then
call TimerStart(EP_Timer,PERIOD,false,function ep)
endif
endfunction
function ep_cast takes nothing returns boolean
local spelleffect this = RUNNING
local real face = GetUnitFacing(this.spell.caster.unit)
call BJDebugMsg("checking if it is already running")
if next[0] == 0 then
call BJDebugMsg("Nope, it wasn't")
call TimerStart(EP_Timer,PERIOD,false,function ep)
endif
call BJDebugMsg("Still not broken yet")
set next[this] = 0
set prev[this] = prev[0]
set next[prev[this]]=this
set prev[0] = this
call this.spell.lock()
set distance[this] = this[2]
set Sangle[this] = (face-this[3])*bj_DEGTORAD
set Eangle[this] = (face+this[3])*bj_DEGTORAD
set left[this] = R2I(this[0])
call BJDebugMsg("left[this]="+I2S(left[this]))
call ReturnEffect(false)
return true
endfunction
endlibrary
JASS:
library SpellProjectile uses Missile Target Effects
globals
boolexpr RegProjectile
endglobals
struct spellprojectile extends array
static method onRemove takes Missile this returns boolean
local spelleffect se = this.data
call se.spell.core(se)
return true
endmethod
static method reg takes nothing returns boolean
local Spell_Cast spell = RUNNING.spell
local real x = spell.caster.x
local real y = spell.caster.y
local integer i = 0
local real a = 1
local group g
local Target u
local Missile new// = Missile.create(x,y,65,x+1000*Cos(a),y+1000*Sin(a),0)
if RUNNING.target.isGroup then
set g = CreateGroup()
call GroupAddGroup(g,RUNNING.target.group)
loop
set u = Target[FirstOfGroup(g)]
exitwhen 0 == u
set new = Missile.createLoc(AdvLoc.create(x, y, RUNNING.caster.z),AdvLoc.create(u.x,u.y,u.z))
set new.target = u.unit
set new.height = RUNNING[1]
set new.speed=RUNNING[0]*0.0325000
set new.model=GetSFXPath(RUNNING.model)
set new.source=spell.caster.unit
set new.collision=RUNNING[2]
set new.open = RUNNING[3]
set new.data = spelleffect.createProxy(RUNNING, spell.caster, u)
call launch(new)
endloop
else
if RUNNING.target.isUnit then
set new = Missile.createLoc(AdvLoc.create(x, y, RUNNING.caster.z),AdvLoc.create(RUNNING.target.x,RUNNING.target.y,RUNNING.target.z))
set new.target = RUNNING.target.unit
else
set new = Missile.createLoc(AdvLoc.create(x,y,RUNNING.caster.z),AdvLoc.create(RUNNING.target.x,RUNNING.target.y,0))
endif
//set new.arc= RUNNING[1]
set new.height = RUNNING[1]
set new.speed=RUNNING[0]*0.0325000
set new.model=GetSFXPath(RUNNING.model)
set new.open = RUNNING[3]
set new.source=spell.caster.unit
set new.collision=RUNNING[2]
set new.data = RUNNING
call launch(new)
endif
call ReturnEffect(false)
return true
endmethod
// meteor 0 is fall time, 1 is height, 2 is makes it circle
static method meteor takes nothing returns boolean
local Spell_Cast spell = RUNNING.spell
local real x = spell.target.x
local real y = spell.target.y
local integer i = 0
local real sp = 5/RUNNING[0]*0.0325000
local group g
local Target u
local Missile new// = Missile.create(x,y,65,x+1000*Cos(a),y+1000*Sin(a),0)
call BJDebugMsg("Running Meteor")
if RUNNING.target.isGroup then
set g = CreateGroup()
call GroupAddGroup(g,RUNNING.target.group)
loop
set u = Target[FirstOfGroup(g)]
exitwhen 0 == u
set new = Missile.createLoc(AdvLoc.create(u.x+5, u.y, u.z+RUNNING[1]),AdvLoc.create(u.x,u.z,u.z))
set new.target = u.unit
//set new.height = RUNNING[1]
set new.open = RUNNING[2]
set new.speed=sp
set new.model=GetSFXPath(RUNNING.model)
set new.source=spell.caster.unit
set new.collision=80
//set new.distance = 200
set new.data = spelleffect.createProxy(RUNNING, spell.caster, u)
call launch(new)
endloop
call DestroyGroup(g)
set g =null
else
set u = RUNNING.target
if RUNNING.target.isUnit then
set new = Missile.createLoc(AdvLoc.create(x+5, y, u.z+RUNNING[1]),AdvLoc.create(x,y,u.z))
set new.target = RUNNING.target.unit
else
call BJDebugMsg("target is pos")
set new = Missile.createLoc(AdvLoc.create(x+5, y, 500/*+RUNNING[1]*/),AdvLoc.create(x,y,u.z))
endif
//set new.arc= RUNNING[1]
//set new.height = u.z+RUNNING[1]
set new.speed=sp
set new.model=GetSFXPath(RUNNING.model)
set new.source=spell.caster.unit
//set new.distance = 200
set new.open = RUNNING[2]
set new.collision=80
set new.data = RUNNING
call launch(new)
endif
call BJDebugMsg("Meteor ran succesfully created missile "+I2S(new))
call ReturnEffect(false)
return true
endmethod
implement MissileStruct
static method onInit takes nothing returns nothing
set RegProjectile= Filter(function spellprojectile.reg)
endmethod
endstruct
endlibrary
Edit3: New bug, see last post
Attachments
Last edited: