HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Buggs after first cast

07-16-2008, 03:57 PM#1
Ciebron
hi im new here, i usally hang out in THW but no one there could seem to solve my problem. well here's my problem when i first cast this spell it works perfectly but when i cast it a second time is just blows up directly(after end cast) at the casters position.

i have tried to remove the lighting in case i leak one of those, that was not. i think it have to do with tabels im not sure.

p.s, i have played some with the code that why it can look abit messed up

Collapse JASS:
//!=============================================================================!\\
//! Orb of Zeus by Ciebron.                                                     !\\
//! Give Credits is you use this in your map                                    !\\
//! --------------------------------------------------------------------------- !\\
//! Channels a orb made from the god Zeus him self. the long u channel          !\\
//! the more the ball will grow, when release it will be such force that the    !\\
//! ball will fly up in the air and strike lighting from above and when         !\\
//! it lands it will deal damage to nearby units                                !\\
//! --------------------------------------------------------------------------- !\\
//! Requires:                                                                   !\\
//! ¯¯¯¯¯¯¯¯¯                                                                   !\\
//! - Object Editor  - A hero                                                   !\\
//! - Object Editor  - The Orb of Zeuz ability                                  !\\
//! - Object Editor  - The Orb Dummy Unit                                       !\\
//! - Trigger Editor - This Trigger                                             !\\
//! - Trigger Editor - CSData - by Vexorian                                     !\\
//! - Trigger Editor - CSSaftey - by Vexorian                                   !\\
//! - Trigger Editor - Table - by Vexorian                                      !\\
//!   ([url]http://www.wc3campaigns.net/showthread.php?t=80534[/url])                      !\\
//! --------------------------------------------------------------------------- !\\
scope OrbofZeus initializer Init
//!=============================================================================!\\
//!=================================Setup Starts================================!\\
//!=============================================================================!\\
globals
private constant integer Abil_id = 'A000' //!Ability rawcode
private constant integer Dum_id = 'h000' //!Dummy rawcode
private constant string ESFX = "Abilities\\Spells\\Items\\AIlb\\AIlbSpecialArt.mdl" //!SFX when the lightning hit the target
private constant string GSFX = "Abilities\\Spells\\Human\\ThunderClap\\ThunderClapCaster.mdl" //! Effect that gets created @ the ground when the ball hits it
private constant string Lighttype = "FORK" //!lightning type
private constant real LightningRange = 400. //! Range of the lightnings
private constant integer MaximumTargets = 3 //! Maximum nr of target allowed (cant be 0 duh)
private constant real Maxdist = 1500. //! distance the orb will move
private constant real Time = 3. //! Time to Travel Maxdist
private constant real Curve = 6. //! adjust this if the ball goes to high or to low for ur taste (lower, the higher the ball will get and the other way around)
private constant string AttachPoint = "origin"

    //! dont touch these
    private group OrbofZeus = CreateGroup()
    private HandleTable activeTable
endglobals

private function SetDamage takes real a returns real
    return a*1.5 //!damage formula, a is based b.size (atm it deals 1.5*b.size)
endfunction
//!=============================================================================!\\  
//!=================================Setup Ends==================================!\\
//!=============================================================================!\\

private struct Data
unit caster
unit dummy
unit array victims [MaximumTargets]

real cos
real sin
real size
real z
real dist
real fulltime
real time
real dmg
real distance
real Movedist

real lightningtime

lightning array Lightning [MaximumTargets]

integer count

player play

timer t

    static method create takes nothing returns Data
        local Data d = Data.allocate()
        local location loc = GetSpellTargetLoc()
        local real tx = GetLocationX(loc)
        local real ty = GetLocationY(loc)
        local real x
        local real y
        local real angle
        local real scale
        local integer index = 0
        
        //! just for debugging
        loop
            exitwhen index >= MaximumTargets
            set d.Lightning[index] = null
            set index = index + 1
        endloop
        
        //! setup stuff
        set d.caster = GetTriggerUnit()
        set x = GetUnitX(d.caster)
        set y = GetUnitY(d.caster)
        set angle = Atan2(ty-y,tx-x)
        set d.play = GetOwningPlayer(d.caster)
        set d.cos = Cos(angle)
        set d.sin = Sin(angle)
        set d.dummy = CreateUnit(d.play,Dum_id,x+100*d.cos,y+100*d.sin,0.)
        set d.size = 1
        set scale = 1+(0.25*d.size)
        set d.Movedist = (Maxdist/Time)/(1./.035)
        set d.t = NewTimer()
        set d.count = 0
        set d.z = 20
        call SetUnitScale(d.dummy,scale,scale,scale)
        
        call SetCSData(d.t, d)
        call TimerStart(d.t,1.,true,function Data.OrbGrow)
        
        call RemoveLocation(loc)
        set loc = null
        
        return d
    endmethod
    
    static method OrbGrow takes nothing returns nothing
    local Data d = GetCSData(GetExpiredTimer())
    local real scale
    
    //! make's the orb grow
    set d.size = d.size + 1
    set scale = 1+(0.25*d.size)
    call SetUnitScale(d.dummy,scale,scale,scale)
    endmethod
    
    static method Move takes nothing returns nothing
        local Data d = GetCSData(GetExpiredTimer())
        local real x = GetUnitX(d.dummy)+d.Movedist*d.cos // New Y cord
        local real y = GetUnitY(d.dummy)+d.Movedist*d.sin // New X cord
        local group g //group for picking units
        local unit victim //used in the loop to damage and create lightnings
        local integer index = 0 //used in the group to set array index
        
        set d.dist = d.dist + d.Movedist
        set d.z = JumpParabola(d.dist,Maxdist,Curve)
    
        call SetUnitFlyHeight(d.dummy,d.z,0.)
        
        //! check if the unit is @ the ground, if it is we make it blow up
        if d.z > 0. then
            //! if the lightning's have been alive for .25 sec we destroy them else we move them
            if d.lightningtime >= .25 then
                loop
                    exitwhen index >= d.count
                    if d.Lightning[index] != null then
                        call DestroyLightning(d.Lightning[index])
                        set d.Lightning[index] = null
                    else
                        call BJDebugMsg("Tried to destroy a lightning that dont exist")
                    endif
                    set index = index + 1
                endloop
                set d.count = 0
                set index = 0
            else
                loop
                    exitwhen index >= d.count
                    call MoveLightningEx(d.Lightning[index],true,x,y,GetUnitFlyHeight(d.dummy)+50,GetUnitX(d.victims[index]),GetUnitY(d.victims[index]),GetUnitFlyHeight(d.victims[index])+50)
                    set index = index + 1
                endloop
                set index = 0
            endif
            
            
            //! check if the x & y cords isnt outside the mapbounds
            if MinX < x and MaxX > x and MinY < y and MaxY > y then
                call SetUnitX(d.dummy,x)
                call SetUnitY(d.dummy,y)
            endif
            
            //! if .5 sec have gone since the last lightning's we make new ones
            if d.lightningtime >= .5 then
                set g = NewGroup()
            
                call GroupEnumUnitsInRange(g,x,y,500,Filter(function Data.filter))
                
                set d.count = 0
                
                loop
                    set victim = FirstOfGroup(g)
                    exitwhen victim == null or index >= MaximumTargets
                    call GroupRemoveUnit(g,victim)
                    set d.victims[index] = null
                    set d.victims[index] = victim
                    set d.Lightning[index] = AddLightningEx("FORK",true,x,y,GetUnitFlyHeight(d.dummy)+50,GetUnitX(victim),GetUnitY(victim),GetUnitFlyHeight(victim)+50)
                    call UnitDamageTarget(d.caster,victim,100.,false,false,ATTACK_TYPE_MAGIC,null,null)
                    call DestroyEffect(AddSpecialEffectTarget(ESFX,victim,AttachPoint))
                    set index = index + 1
                endloop
                
                set d.count = index
                set d.lightningtime = 0.
                call ReleaseGroup(g)
            endif
        else
            set g = NewGroup()
            
            call GroupEnumUnitsInRange(g,x,y,500,Filter(function Data.filter))
            call DestroyEffect(AddSpecialEffect(GSFX,x,y))
            
            //! dmg units where the orb blew up
            loop
                set victim = FirstOfGroup(g)
                exitwhen victim == null
                call GroupRemoveUnit(g,victim)
                call UnitDamageTarget(d.caster,victim,100.,false,false,ATTACK_TYPE_MAGIC,null,null)
            endloop
            
            call ReleaseGroup(g)
            
            call d.destroy()
        endif
        
        set d.time = d.time + .035
        set d.lightningtime = d.lightningtime + .035
        set g = null
        
    endmethod
    
    static method filter takes nothing returns boolean
        local Data d = GetCSData(GetExpiredTimer())
        local unit f = GetFilterUnit()
        local boolean ok = GetWidgetLife(f) > .405 and not IsUnitType(f,UNIT_TYPE_STRUCTURE) and not IsUnitType(f,UNIT_TYPE_MAGIC_IMMUNE) and IsUnitEnemy(f,GetOwningPlayer(d.caster))
        set f = null
        return ok
    endmethod
    
    method onDestroy takes nothing returns nothing
        local integer index = 0
        
        //! destroys the lightning    
        loop
            exitwhen index >= .count
            if .Lightning[index] != null then
                call DestroyLightning(.Lightning[index])
                set .Lightning[index] = null
            else
                call BJDebugMsg("Tried to destroy a lightning that dont exist")
            endif
            set index = index + 1
        endloop
        
        call KillUnit(.dummy)
        
        call ReleaseTimer(.t)
    endmethod
endstruct

private function PreLoad takes nothing returns nothing
    call Preload(GSFX)
    call Preload(ESFX)
    call RemoveUnit(CreateUnit(Player(15),Dum_id,0,0,0))
endfunction

private function onend takes nothing returns boolean
    local Data d
    local unit u = GetTriggerUnit()

    if IsUnitInGroup(u,OrbofZeus) and activeTable.exists(u) then
        set d = activeTable[u]
        set d.dmg = SetDamage(d.size)
        call ReleaseTimer(d.t)
        set d.t = NewTimer()
        call SetCSData(d.t,d)
        call TimerStart(d.t,.035,true,function Data.Move)
        //! remove the caster from the group
        call GroupRemoveUnit(OrbofZeus,u)
        //! flush the caster's table
        call activeTable.flush(d.caster)
    endif

    set u = null
    return false
endfunction
    
private function conds takes nothing returns boolean
    local Data d
    
    if GetSpellAbilityId() == Abil_id then
        set d = Data.create()
        //! set a table to the caster
        set activeTable[d.caster] = d
        //! add the caster to a group for "caster"
        call GroupAddUnit(OrbofZeus,d.caster)
    endif
    return false
endfunction

private function Init takes nothing returns nothing
    local trigger t =CreateTrigger()
    local integer index = 0

    loop
        call TriggerRegisterPlayerUnitEvent(t,Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t,Condition( function conds ) )

    set t = CreateTrigger()
    set index = 0

    loop
        call TriggerRegisterPlayerUnitEvent(t,Player(index),EVENT_PLAYER_UNIT_SPELL_ENDCAST,null)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t,Condition(function onend))
    
    //! this spell use table to get rid of dynamic triggers
    set activeTable = Table.create()
    call PreLoad()
    
    set t = null
endfunction

endscope
07-16-2008, 09:56 PM#2
Vexorian
Don't use //! for comments, you are already using vJass and in vjass //! is for preprocessors.

You should initialize the struct's members (they do not begin at 0.0 automatically)