• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Spell Crashes game

Status
Not open for further replies.
Level 7
Joined
Apr 18, 2010
Messages
102
I dont know the reason, but it appears that the game crashes when this spell is used.
Code:
scope UnlimitedBladeWorks

    globals                    
        private constant integer ABILITY_ID = 'ubwe' //spell Id
        private constant real FPS = 0.0312500
      
        //Spell Constants
        private constant real RADIUS = 800 //radius of the reality marble
        private constant real CASTTIME = 0.5 //delay before the formation of RM
        private constant real FORMTIME = 1.0 //formation time of reality marble
        private constant real DURATION = 8 //duration of spell
      
        //Spell Visuals
        private constant string ANIMATION = "Spell Three" //caster animation when the spell is casted
        private constant real ANIMATIONSPEED = 150 //animation speed of caster
        private constant string CASTINGSOUND = "war3mapImported\\EMY_NP.mp3"
      
        private constant string FIREFX = "Doodads\\Cinematic\\TownBurningFireEmitter\\TownBurningFireEmitter.mdl" //sfx of the RM border
        private constant real FIREFXSIZE = 1.25 //size of Fireborder
        private constant real FIREFXSPIN = 6 //degrees of spin of fire (rate depends of FPS)
        private constant integer FIREFXCOUNT = 60 //number of firefx
      
        private constant string SWORDFX = "war3mapImported\\EmiyaSword.mdl" //sfx of swords
        private constant real SWORDFXSIZE = 1.25 //size of swords
        private constant integer SWORDFXPITCH = 60 //pitch of swords
        private constant real SWORDFXCOUNT = 1.75
        private constant real SWORDFXINC = .25
      
        private constant string GEAR1FX = "war3mapImported\\Gear2.mdl"
        private constant string GEAR2FX = "war3mapImported\\Gear3.mdl"
        private constant integer GEARCOUNT = 12
  
          
      
    endglobals
  
    //Function made by Blade.dk; Search for [url=http://www.wc3campaigns.com]wc3campaigns.com[/url] for more info 
    private function CopyGroup takes group g returns group
        set bj_groupAddGroupDest = CreateGroup()
        call ForGroup(g, function GroupAddGroupEnum)
        return bj_groupAddGroupDest
    endfunction
  
    private struct MySpell
  
        private unit    caster
        private real     duration
        private real     formtime
        private real     casttime
        private real    firefxspeed
        private real     swordfxcount
        private real     radius
        private real     angle
        private group     realitymarblegroup
        private group    copygroup
        private group     firegroup
        private real    ubwX
        private real    ubwY
        private real     fireangleinc
        private real     gearangle
        private integer stage
      
          
        private static method onPeriodic takes nothing returns nothing
            local timer tmr = GetExpiredTimer()
            local integer g
            local unit u
            local real X1
            local real Y1
            local real X2
            local real Y2
            local real fireangle
            local real gearsize
            local real gearZ
            local integer gearvar
         
            local thistype this = GetTimerData(tmr)
          
            // Your spell code. For example.
            if this.stage == 1 then
                if this.casttime > 0 then
                    if GetWidgetLife(this.caster) >= 0.405 then
                        set this.casttime = this.casttime - FPS
                    else
                    set this.stage = 0
                    endif
                else
                set this.stage = 2
                set this.ubwX = GetUnitX(this.caster)
                set this.ubwY = GetUnitY(this.caster)
                set g = FIREFXCOUNT
                loop
                    exitwhen g <= 0
                    set u = GetRecycledDummy(ubwX, ubwY, 0, this.angle)
                    call AddSpecialEffectTarget(FIREFX,u,"origin")
                    set this.angle = this.angle + fireangleinc
                    call GroupAddUnit(this.realitymarblegroup,u)
                    call GroupAddUnit(this.firegroup,u)
                    call SetUnitScale(u, FIREFXSIZE, 1, 1)
                    set g = g - 1
                endloop
                endif
            endif
              
            if this.stage == 2 then
                if this.formtime > 0 then
                    set this.copygroup = CopyGroup(this.firegroup)
                    set this.radius = this.radius + this.firefxspeed
                    loop
                        set u = FirstOfGroup(this.copygroup)
                        exitwhen u == null
                        set X1 = GetUnitX(u)
                        set Y1 = GetUnitY(u)
                        set fireangle = GetUnitFacing(u)
                        set X2 = X1 + this.firefxspeed * Cos( Deg2Rad (fireangle))
                        set Y2 = Y1 + this.firefxspeed * Sin( Deg2Rad (fireangle))
                        call SetUnitX(u, X2)
                        call SetUnitY(u, Y2)
                        call SetUnitFacing(u, fireangle + FIREFXSPIN)
                        call GroupRemoveUnit(this.copygroup, u)
                    endloop
                      
                    set g = R2I(this.swordfxcount)
                    loop
                        exitwhen g == 0
                        set X2 = this.ubwX + GetRandomReal( -1 * this.radius, this.radius ) * Cos(GetRandomReal(0,360))
                        set Y2 = this.ubwY + GetRandomReal( -1 * this.radius, this.radius ) * Sin(GetRandomReal(0,360))
                        set u = GetRecycledDummy(X2, Y2, 0, GetRandomReal(0,360))
                        call AddSpecialEffectTarget(SWORDFX,u,"origin")
                        call GroupAddUnit(this.realitymarblegroup,u)
                        call SetUnitScale(u, SWORDFXSIZE, 1, 1)
                        call SetUnitAnimationByIndex(u, SWORDFXPITCH)
                        set g = g - 1
                    endloop
                    set this.swordfxcount = this.swordfxcount + SWORDFXINC
                  
                    set this.formtime = this.formtime - FPS
                  
                else
                    set this.stage = 3
                    set this.angle = GetRandomReal(0,360)
                    set g = GEARCOUNT
                    loop
                        exitwhen g == 0
                        set X2 = this.ubwX + (this.radius + 25)*Cos(this.angle)
                        set Y2 = this.ubwY + (this.radius + 25)*Sin(this.angle)
                        set this.angle = this.angle + this.gearangle
                        set gearsize = GetRandomReal(2.25,3.25)
                        set gearZ = GetRandomReal(125,225)
                        set u = GetRecycledDummy(X2, Y2, gearZ, this.angle)
                        set gearvar = GetRandomInt(1,2)
                        if gearvar == 1 then
                            call AddSpecialEffectTarget(GEAR1FX,u,"origin")
                        else
                            call AddSpecialEffectTarget(GEAR2FX,u,"origin")
                        endif
                        call GroupAddUnit(this.realitymarblegroup,u)
                        call SetUnitScale(u, gearsize, 1, 1)
                        set g = g - 1
                    endloop
                endif
            endif
          
            if this.stage == 3    then  
                if this.duration > 0 then
                    set this.duration = this.duration - FPS
                    //apply border control
                else
                set this.stage = 0  
                endif
            endif
          
            //deallocation
            if this.stage == 0 then
                call this.destroy()
                call ReleaseTimer(tmr)
                call PauseUnit(this.caster, false)
                loop
                    set u = FirstOfGroup(this.realitymarblegroup)
                    exitwhen u == null
                    call DummyAddRecycleTimer(u,0.5)  
                endloop
            endif
          
            set tmr = null
        endmethod
                   
        private static method onEffect takes nothing returns nothing
          
            local thistype this = thistype.create()// Creates a unique index "this".
          
            //initializing spell variables
            set this.caster = GetTriggerUnit()
            set this.duration = DURATION
            set this.casttime = CASTTIME
            set this.formtime = FORMTIME
            set this.firefxspeed = (RADIUS / (FORMTIME / (1/FPS)))
            set this.radius = 0
            set this.angle = GetRandomReal(0,360)
            set this.swordfxcount = SWORDFXCOUNT
            set this.fireangleinc = 360 / I2R(FIREFXCOUNT)
            set this.gearangle = 360 / I2R(GEARCOUNT)
          
            //start casting
            //creating groups
            set this.realitymarblegroup = CreateGroup()
            set this.copygroup = CreateGroup()
            set this.firegroup = CreateGroup()
          
            //spell core
            set this.stage = 1
            call PauseUnit(this.caster, true)
            call SetUnitAnimation(this.caster, ANIMATION)
            call SetUnitTimeScale(this.caster, ANIMATIONSPEED)
            call AttachSoundUnit(this.caster, CASTINGSOUND, 127, 9, 2000, false, true, 1500, 3000)
          
            //add caster to Casting group here
            //add caster to not moving group here
            //add caster to not walking group here
          
      
            call TimerStart(NewTimerEx(this), FPS, true, function thistype.onPeriodic)
        endmethod  
      
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABILITY_ID, function thistype.onEffect)
        endmethod
  
    endstruct

endscope
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,016
You absolutely do not need to use I2R, that's just pointless. Any operation that involves an integer and a real outputs a real; the only case where you might need to 'convert' in some way is doing integer division where you want the output to be a real. 3/2 = 1 in integer division, not 1.5.
 
Please use [code=jass][/code] tags to post JASS code, and update first post code instead of posting new ones. : )

JASS:
loop
    set u = FirstOfGroup(this.realitymarblegroup)
    exitwhen u == null
    call DummyAddRecycleTimer(u,0.5) 
endloop
^No units removed from group. => probably infinite loop

Some notes:
  • set this.copygroup = CopyGroup(this.firegroup) here happens an object leak, because your group is already created, but CopyGroup() does again create a new group, too.
  • There should be an extra destroy() method, where all things are releases etc, and also member vars of this are nulled.
made things simpler, still crashes tho.. for some reason, unit creation doesnt happen as well??
When does it crash? What does not work? Does something even work? Which units are not being created, none at all? etc..
Have not tested the map (can't now), but I believe you're on a level where you know such things could help others and yourself. :)
 
Level 7
Joined
Apr 18, 2010
Messages
102
Please use [code=jass][/code] tags to post JASS code, and update first post code instead of posting new ones. : )

JASS:
loop
    set u = FirstOfGroup(this.realitymarblegroup)
    exitwhen u == null
    call DummyAddRecycleTimer(u,0.5)
endloop
^No units removed from group. => probably infinite loop

Some notes:
  • set this.copygroup = CopyGroup(this.firegroup) here happens an object leak, because your group is already created, but CopyGroup() does again create a new group, too.
  • There should be an extra destroy() method, where all things are releases etc, and also member vars of this are nulled.

When does it crash? What does not work? Does something even work? Which units are not being created, none at all? etc..
Have not tested the map (can't now), but I believe you're on a level where you know such things could help others and yourself. :)


Edited, the game doesnt crash now, however no units are still being created....

I did put some debugging message a while ago, it turns out that the spell fires up to Stage = 2 and beyond, its just that no creation of units take place.

Code:
scope UnlimitedBladeWorks 
    globals 
        private constant integer ABILITY_ID = 'ubwe'
        private constant real FPS = 0.03125
        private group copy
        private constant real UBW_DURATION = 8.0 //seconds
        private constant real UBW_FORMTIME = 1.0 //seconds
        private constant real UBW_CASTTIME = 0.5 //seconds
        private constant real UBW_RADIUS = 800
        private constant string FIRE_SFX = "Doodads\\Cinematic\\TownBurningFireEmitter\\TownBurningFireEmitter"
        private constant real FIRE_SIZE = 1.25
        private constant integer FIRE_COUNT = 60
        private constant real FIRE_ANGLE = 6
       
       
    endglobals
   
    private struct UnlimitedBladeWorks 
   
        private unit        caster
        private real        duration
        private real         casttime
        private integer        stage
        private location     UBWlocation
        private real         formtime
        private real         angle
        private group         firefxgroup
        private group        ubwgroup
        private effect        sfx
        private real         radius
        private real        firefxspeed
        private real         fireangle
       
           
        private static method onPeriodic takes nothing returns nothing
            local timer tmr = GetExpiredTimer()
            local thistype this = GetTimerData(tmr)
            local unit u
            local real x1
            local real y1
            local real z1
            local real x2
            local real y2
            local real facing
            local integer s
            // Your spell code. For example.
           
            if this.stage == 1 then
                if this.casttime <= 0 then
                    set this.stage = 2
                    set this.UBWlocation = GetUnitLoc(this.caster)
                    set x1 = GetLocationX(this.UBWlocation)
                    set y1 = GetLocationY(this.UBWlocation)
                    set z1 = GetLocationZ(this.UBWlocation)
                    set s = FIRE_COUNT
                    loop
                        exitwhen s == 0
                        set s = s - 1
                        set this.angle = this.angle + fireangle
                        set u = GetRecycledDummy(x1,y1,z1,this.angle)
                        set this.sfx = AddSpecialEffectTarget(FIRE_SFX,u,"origin")
                        call SetUnitScalePercent(u, FIRE_SIZE, FIRE_SIZE, FIRE_SIZE)
                        call GroupAddUnit(this.firefxgroup,u)
                        call GroupAddUnit(this.ubwgroup, u)
                    endloop
                       
                else
                    if GetWidgetLife(this.caster) >= 0.405 then
                        set this.casttime = this.casttime - FPS
                    else
                        set this.stage = 0
                    endif
                endif
            endif
       
            if this.stage == 2 then
                if this.formtime > 0 then
                    set this.formtime = this.formtime - FPS
                    set copy = this.firefxgroup
                    loop
                        set u = FirstOfGroup(copy)
                        exitwhen u == null
                        set x1 = GetUnitX(u)
                        set y1 = GetUnitY(u)
                        set facing = GetUnitFacing(u)
                        set x2 = x1 + this.firefxspeed*CosBJ(facing)
                        set y2 = y1 + this.firefxspeed*SinBJ(facing)
                        call SetUnitX(u,x2)
                        call SetUnitY(u,y2)
                        call GroupRemoveUnit(copy,u)
                        set u = null
                    endloop   
                    //create swords
                else
                set this.stage = 3
                //create gears
                endif
            endif
           
            if this.stage == 3 then
                if this.duration > 0 then
                set this.duration = this.duration - FPS
                //apply border control
                endif
                set this.stage = 0
            endif
           
            if this.stage == 0 then   
                //destroy trigger not yet complete
                call this.destroy()
                call ReleaseTimer(tmr)
                loop
                    set u = FirstOfGroup(this.ubwgroup)
                    exitwhen u == null
                    call DummyAddRecycleTimer(u, 0.5)
                    call DestroyEffect(this.sfx)
                    call GroupRemoveUnit(this.ubwgroup,u)
                endloop   
            endif
           
            set tmr = null
        endmethod
                     
        private static method onEffect takes nothing returns nothing
            local thistype this = thistype.create()
           
            set this.caster = GetTriggerUnit()
            set this.duration = UBW_DURATION
            set this.formtime = UBW_FORMTIME
            set this.casttime = UBW_CASTTIME
            set this.radius = 0
            set this.firefxspeed = UBW_RADIUS / (UBW_FORMTIME / (1 / FPS))
            set this.angle = GetRandomReal(0,360)
            set this.fireangle = 360 / FIRE_COUNT
           
            call IssueImmediateOrder(this.caster, "stop")
            call PauseUnit(this.caster, true)
           
            set this.stage = 1
           
           
            call TimerStart(NewTimerEx(this), FPS, true, function thistype.onPeriodic) 
        endmethod   
        private static method onInit takes nothing returns nothing
            call RegisterSpellEffectEvent(ABILITY_ID, function thistype.onEffect)
        endmethod
    endstruct
endscope
 

Attachments

  • UBW vjass test3.w3x
    842.1 KB · Views: 16
Level 7
Joined
Apr 18, 2010
Messages
102
Rewrote the entire code, reread the tutorial for dynamic indexing in jass.. heres the result.


received_393939987937277.gif


JASS:
scope UnlimitedBladeWorks initializer Init
    //===first Vjass spell xD =============================
    //================ USES DYNAMIC INDEXING =============//
    //https://www.hiveworkshop.com/threads/vjass-dynamic-indexing-tutorial.245956/
  
  
    globals
        private timer period = CreateTimer()
        private constant real fps = 1.0 / 32.0
        private integer dindex = -1
    endglobals
  
    /*==================================================
    =======================SETUP========================
    ==================================================*/
    globals
        private integer SPELLID = 'Eubw'
      
        //spell constants
        private real CASTTIME = 0.25
        private real FORMTIME = 1.25
        private real DURATION = 12.0
        private real RADIUS = 1200.0
      
        //spell visuals
      
        private integer FIRESFXCOUNT = 60
        private real SWORDSFXCOUNT = 1.25
        private real SWORDSFXINC = 0.15
        private integer GEARFXCOUNT = 24
        private real FIRESFXSIZE = 1.75
        private real SWORDFXSIZE = 2.00
        private real FIREFXSPIN = 11.0
        private real SWORDFXHEIGHT = -65.0
  
        private string SWORDSFX = "war3mapImported\\EmiyaUbwSword.mdx"
        private string FIRETRAILSFX = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
        private string FIRESFX = "war3mapImported\\UbwFire.mdx"
        private string SWORDSFXSPAWN = "Abilities\\Weapons\\RedDragonBreath\\RedDragonMissile.mdl"
    endglobals
  
  
        //spell visuals continuation
        private function GEARSFX takes nothing returns string
            local integer random
            set random = GetRandomInt(1,2)
            if random == 1 then
                return "war3mapImported\\Gear2.mdx"
            else
                return "war3mapImported\\Gear3.mdx"
            endif
        endfunction
  
        private function ANGLEPERFIRE takes integer a returns real
            return 360.0 / a
        endfunction
      
        private function GEARSFXHEIGHT takes real size returns real
            return GetRandomReal(50.0, 150.) + 25.*size
        endfunction
      
        private function GEARSFXSIZE takes nothing returns real
            return GetRandomReal(1.5, 3.)
        endfunction
      
        private function ANGLEPERGEAR takes integer a returns real
            return 360.0 / a
        endfunction
      
        private function FIREFXSPEED  takes real aoe, real formtime returns real
            return aoe / (formtime / fps)
        endfunction
  
  
    /*==================================================
    =====================END SETUP========================
    ==================================================*/
  
        private struct tempDat
            unit caster
            integer stage
            real casttime
            real formtime
            real speed
            real ubwx
            real ubwy
            real duration
            location ubwpoint
            group ubwdummygroup
            real swordcount
            real swordspawnaoe
            group swordgroup
          
            method destroy takes nothing returns nothing
                //wash leaks
                if dindex == -1 then
                    call PauseTimer(period)
                endif
                call this.deallocate()
            endmethod
        endstruct
      
    globals
        private tempDat array data
    endglobals
  
  
    private function FireSpreadSpin takes group g, location l, real speed returns nothing
        local unit fire
        local location fireloc
        local real angle
        local real x2
        local real y2
        local group copy = CreateGroup()
        call GroupAddGroup(g, copy)
        loop
            set fire = FirstOfGroup(copy)
            exitwhen fire == null
            set fireloc = GetUnitLoc(fire)
            set angle = AngleBetweenPoints(l, fireloc)
            set x2 = GetLocationX(l) + speed*Cos( Deg2Rad(angle + FIREFXSPIN) )
            set y2 = GetLocationY(l) + speed*Sin( Deg2Rad(angle + FIREFXSPIN) )
            call SetUnitX(fire, x2)
            call SetUnitY(fire, y2)
          
            call RemoveLocation(fireloc)
            set fireloc = null
            call GroupRemoveUnit(copy, fire)
            set fire = null
        endloop
        call DestroyGroup(copy)
        set copy = null
    endfunction
  
    private function SFXDestroy takes nothing returns nothing
  
        local unit sfx = GetEnumUnit()
      
        call DestroySFX(sfx)
        call DummyAddRecycleTimer(sfx, 0.7) //recycles dummy
      
        set sfx = null //removing leaks
      
    endfunction
    private function ubwtargets takes nothing returns boolean
        local unit pick = GetFilterUnit()
        local boolean b = true
        if    GetWidgetLife(pick) < 0.405 then
            set b = false
        endif
        return b
    endfunction
  
    private function bordercontrol takes group g, location p, real r, real up, real down returns nothing
    local unit u
    local location t
    local real d
    local real a
    local real x
    local real y
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        set t = GetUnitLoc(u)
        set d = DistanceBetweenPoints(p, t)
        set a = Deg2Rad( AngleBetweenPoints(p, t) )
        if d < r then  
                if d > r - up then
                set x = GetLocationX(p) + (r - up)* Cos(a)
                set y = GetLocationY(p) + (r - up)* Sin(a)
                call SetUnitX(u, x)
                call SetUnitY(u, y)
                endif
              
        else
                if d < r + down then
                set x = GetLocationX(p) + (r + down)*Cos(a)
                set y = GetLocationY(p) + (r + down)*Sin(a)
                call SetUnitX(u, x)
                call SetUnitY(u, y)
                endif
        endif
        call GroupRemoveUnit(g, u)
        call RemoveLocation(t)
        set t = null
        set u = null
      
    endloop
  
    endfunction
  
    private function periodic takes nothing returns nothing
        local tempDat this
        local integer i = 0  //loops through instances
        local integer looper
        local real angle
        local unit dummy
        local real x
        local real y
        local real size
        local group g
      
        loop
            exitwhen i>dindex
            set this = data[i]
          
          
            //spell core
          
            if this.stage == 1 then
                if this.casttime > 0 then
                    set this.casttime = this.casttime - fps
                    else
                    if GetWidgetLife(this.caster) >= 0.405 then
                      
                        //restoring player control
                        call PauseUnit(this.caster, false                      //
                        call GroupRemoveUnit(CannotMove, this.caster)            //
                        call GroupRemoveUnit(CannotWalk, this.caster)            // For keyboard movement system
                        call GroupRemoveUnit(CannotTurn, this.caster)            //
                        set this.stage = 2  //sets spells stage
                        set this.ubwx = GetUnitX(this.caster) //sets spell loc
                        set this.ubwy = GetUnitY(this.caster) //sets spell loc
                        set this.ubwpoint = GetUnitLoc(this.caster) //sets ubw loc
                      
                        //CREATING FIRE SFX
                        set looper = 0
                        set angle = GetRandomReal(0, 360)
                        loop
                            exitwhen looper >= FIRESFXCOUNT
                            set looper = looper + 1
                            set angle = angle + ANGLEPERFIRE(FIRESFXCOUNT) //sets angle of firesfx
                            set x = this.ubwx + 5 * Cos( Deg2Rad (angle) ) //adds offset, for spinning effect
                            set y = this.ubwy + 5 * Sin( Deg2Rad (angle) )
                          
                            set dummy = GetRecycledDummy(x,y,0.0, angle) //dummy recycler by flux
                            call CreateSFX( dummy, FIRESFX, FIRETRAILSFX) //self made system for sfx
                          
                            call GroupAddUnit(this.ubwdummygroup, dummy) //adds firesfx to group
                            call SetUnitScale(dummy, FIRESFXSIZE, 1, 1)
                      
                        endloop  
                    else
                        set this.stage = 0
                    endif
                endif  
          
            else
          
                if this.stage == 2 then
                    if this.formtime > 0 then
                        set this.formtime = this.formtime - fps      
                        set this.swordspawnaoe = this.swordspawnaoe + this.speed
                        call FireSpreadSpin(this.ubwdummygroup,this.ubwpoint,this.swordspawnaoe)   //moves fire and spins
                        set looper = 0
                        set this.swordcount = this.swordcount + SWORDSFXINC   //creating swords, forms as fire boundary expands
                        loop
                            exitwhen looper >= R2I(this.swordcount)
                            set looper = looper + 1
                            set angle = Deg2Rad(GetRandomReal(0, 360))
                            set x = this.ubwx + (this.swordspawnaoe + GetRandomReal(-125, 125) )*Cos(angle)
                            set y = this.ubwy + (this.swordspawnaoe + GetRandomReal(-125, 125) )*Sin(angle)
                          
                            set dummy = GetRecycledDummy(x,y, SWORDFXHEIGHT , Rad2Deg(angle))
                            call CreateSFX(dummy, SWORDSFX, "")
                          
                            call GroupAddUnit(this.swordgroup, dummy)
                            call SetUnitScale(dummy, SWORDFXSIZE, 1, 1)
                            //call SetUnitTimeScale(dummy, 99)
                      
                        endloop
                  
                    else
                        set this.stage = 3
                      
                        //creating Gears
                        set looper = 0
                        set angle = GetRandomReal(0, 360)
                        loop
                            exitwhen looper >= GEARFXCOUNT
                            set looper = looper + 1
                            set angle = angle + ANGLEPERGEAR(GEARFXCOUNT)
                            set x = this.ubwx + RADIUS * Cos ( Deg2Rad (angle) )
                            set y = this.ubwy + RADIUS * Sin ( Deg2Rad (angle) )
                          
                            set size = GEARSFXSIZE()
                          
                            set dummy = GetRecycledDummy(x,y, GEARSFXHEIGHT(size) , angle) //uses DummyRecycler by flux
                            call CreateSFX(dummy, GEARSFX() , "") //self made sfx system
                            call SetUnitScale(dummy, size, 1, 1 )
                            call SetUnitTimeScale(dummy, 0.5)
                            call GroupAddUnit(this.swordgroup, dummy)
                        endloop
                        //add sword rain ability here
                    endif
                else
                    if this.stage == 3 then
                        if this.duration > 0 and GetWidgetLife(this.caster) >= 0.405 then
                            set this.duration = this.duration - fps
                            set g = CreateGroup()                                                                //creates border group
                            call GroupEnumUnitsInRange(g, this.ubwx, this.ubwy, RADIUS, function ubwtargets)  //traps units inside boundary field
                            call bordercontrol(g, this.ubwpoint, RADIUS, 115, 75)
                            call DestroyGroup(g)
                            set g = null
                        else
                            set this.stage = 0
                        endif
                    endif
                endif
                if this.stage == 0 then
                    //Ending Spell
                    call ForGroup(this.ubwdummygroup, function SFXDestroy)
                    call ForGroup(this.swordgroup, function SFXDestroy)
                    call RemoveLocation(this.ubwpoint)
                    set this.ubwpoint = null
                    set this.caster = null
                    call DestroyGroup(this.ubwdummygroup)
                    set this.ubwdummygroup = null
                    call DestroyGroup(this.swordgroup)
                    set this.swordgroup = null
                    //Destroying Instance
                    set data[i] = data[dindex]
                    set i = i - 1
                    set dindex = dindex - 1
                    call this.destroy()
                endif
            endif
        set i = i + 1
        endloop
    endfunction
  
    private function Cond takes nothing returns boolean
        local tempDat this
        if GetSpellAbilityId() == SPELLID then
            //instantiating
            set this = tempDat.create()
            //setup variables
            set this.caster = GetTriggerUnit()
            set this.casttime = CASTTIME
            set this.formtime = FORMTIME
            set this.duration = DURATION
            set this.stage = 1
            set this.speed = FIREFXSPEED( RADIUS, FORMTIME )
            set this.swordcount = SWORDSFXCOUNT
            set this.swordspawnaoe = 0
            //spell start
            call AttachSoundUnit(this.caster, "war3mapImported\\EMY_NP.mp3", 127, 9, 2000, false, true, 1500, 3000)
            call StopSound( GetLastPlayedSound(), true, true)
            call PauseUnit(this.caster, true)
            call IssueImmediateOrder(this.caster, "stop")
            call SetUnitAnimation(this.caster, "Spell Three")
            //for movement trigger
            call GroupAddUnit(CannotMove, this.caster)          //
            call GroupAddUnit(CannotWalk, this.caster)         // For keyboard movement
            call GroupAddUnit(CannotTurn, this.caster)         //
            call GroupRemoveUnit(IsWalking, this.caster)       //
            //creating groups
            set this.ubwdummygroup = CreateGroup()
            set this.swordgroup = CreateGroup()
            //increasing Loop
            set dindex = dindex + 1
            set data[dindex] = this
            if dindex == 0 then
                call TimerStart(period, fps, true, function periodic)
            endif
        endif
        return false
    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 Cond ))
        set t = null
      
    endfunction
      
      
endscope
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,016
So does that mean it works? What? You can and should remove the dependency on locations in lieu of using coordinates directly; things like DistanceBetweenPoints (and other BJ functions (things that show up in red)) are crutches and you should learn not to use them (google "distance between two points" or read the function to figure out how to replace it, for example). IMO TriggerRegister... is fine because it's just an init thing and it saves you the hassle of typing it all out.
JASS:
call AttachSoundUnit(this.caster, "war3mapImported\\EMY_NP.mp3", 127, 9, 2000, false, true, 1500, 3000)
call StopSound( GetLastPlayedSound(), true, true)
Unless the AttachSoundUnit function sets the bj_lastPlayedSound variable, that StopSound call will not function. Where is that function declared?
 
Level 7
Joined
Apr 18, 2010
Messages
102
So does that mean it works? What? You can and should remove the dependency on locations in lieu of using coordinates directly; things like DistanceBetweenPoints (and other BJ functions (things that show up in red)) are crutches and you should learn not to use them (google "distance between two points" or read the function to figure out how to replace it, for example). IMO TriggerRegister... is fine because it's just an init thing and it saves you the hassle of typing it all out.
JASS:
call AttachSoundUnit(this.caster, "war3mapImported\\EMY_NP.mp3", 127, 9, 2000, false, true, 1500, 3000)
call StopSound( GetLastPlayedSound(), true, true)
Unless the AttachSoundUnit function sets the bj_lastPlayedSound variable, that StopSound call will not function. Where is that function declared?


Yes the spell works now.. okay ill read up on the angle and distance between points

That attachsoundunit function was a snipet
Heres the source:

[Solved] - 3D Sound Attachment
 
Level 7
Joined
Apr 18, 2010
Messages
102
You need to use udg_lastCreatedSound instead of GetLastPlayedSound(), as per the function.
Yes the spell works now.. okay ill read up on the angle and distance between points

That attachsoundunit function was a snipet
Heres the source:

[Solved] - 3D Sound Attachment



UPDATE:
-Used this to get the distance and the angle between 2 points:

JASS:
set x2 = GetUnitX(u)
        set y2 = GetUnitY(u)
        set dx = x2 - x
        set dy = y2 - y
        set d = SquareRoot( dx*dx + dy*dy )
        set a = Atan2(dy, dx)

-Changed the 3D Sound attachment variable from udg_lastCreatedSound to AttachedSound... (just wanted to remove the udg_variable, so i used a global sound, inserted in the snippet's library)

-Created 1 group for all, 1 group used for copying for all the instances of the spell
JASS:
        private group all = CreateGroup()
        private group copy = CreateGroup()


Is there a function that can be used as a substitute for this?
JASS:
        call GroupAddGroup(g, copy)

JASS:
scope UnlimitedBladeWorks initializer Init
    //===first Vjass spell xD =============================
    //================ USES DYNAMIC INDEXING =============//
    //https://www.hiveworkshop.com/threads/vjass-dynamic-indexing-tutorial.245956/
   
   
    globals
        private timer period = CreateTimer()
        private constant real fps = 1.0 / 32.0
        private integer dindex = -1
        private group all = CreateGroup()
        private group copy = CreateGroup()
    endglobals
   
    /*==================================================
    =======================SETUP========================
    ==================================================*/
    globals
        private integer SPELLID = 'Eubw'
       
        //spell constants
        private real CASTTIME = 0.25
        private real FORMTIME = 1.25
        private real DURATION = 12.0
        private real RADIUS = 1200.0
       
        //spell visuals
       
        private integer FIRESFXCOUNT = 55
        private real SWORDSFXCOUNT = 1.25
        private real SWORDSFXINC = 0.12
        private integer GEARFXCOUNT = 24
        private real FIRESFXSIZE = 1.80
        private real SWORDFXSIZE = 2.00
        private real FIREFXSPIN = 7.5
        private real SWORDFXHEIGHT = -65.0
   
        private string SWORDSFX = "war3mapImported\\EmiyaUbwSword.mdx"
        private string FIRETRAILSFX = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
        private string FIRESFX = "war3mapImported\\UbwFire.mdx"
    endglobals
   
   
        //spell visuals continuation
        private function GEARSFX takes nothing returns string
            local integer random
            set random = GetRandomInt(1,2)
            if random == 1 then
                return "war3mapImported\\Gear2.mdx"
            else
                return "war3mapImported\\Gear3.mdx"
            endif
        endfunction
   
        private function ANGLEPERFIRE takes integer a returns real
            return 360.0 / a
        endfunction
       
        private function GEARSFXHEIGHT takes real size returns real
            return GetRandomReal(50.0, 150.) + 25.*size
        endfunction
       
        private function GEARSFXSIZE takes nothing returns real
            return GetRandomReal(1.5, 3.)
        endfunction
       
        private function ANGLEPERGEAR takes integer a returns real
            return 360.0 / a
        endfunction
       
        private function FIREFXSPEED  takes real aoe, real formtime returns real
            return aoe / (formtime / fps)
        endfunction
   
   
    /*==================================================
    =====================END SETUP========================
    ==================================================*/
   
        private struct tempDat
            unit caster
            integer stage
            real casttime
            real formtime
            real speed
            real ubwx
            real ubwy
            real duration
            group ubwdummygroup
            real swordcount
            real swordspawnaoe
            group swordgroup
           
            method destroy takes nothing returns nothing
                //wash leaks
                if dindex == -1 then
                    call PauseTimer(period)
                endif
                call this.deallocate()
            endmethod
        endstruct
       
    globals
        private tempDat array data
    endglobals
   
   
    private function FireSpreadSpin takes group g, real x, real y, real speed returns nothing
        local unit fire
        local real angle
        local real x2
        local real y2
        local real x3
        local real y3
       
        call GroupClear(copy)
        call GroupAddGroup(g, copy)
        loop
            set fire = FirstOfGroup(copy)
            exitwhen fire == null
            set x2 = GetUnitX(fire)
            set y2 = GetUnitY(fire)
            set angle = (Atan2(y2-y, x2-x)) + Deg2Rad (FIREFXSPIN)
            set x2 = x + speed*Cos(angle)
            set y2 = y + speed*Sin(angle)
            call SetUnitX(fire, x2)
            call SetUnitY(fire, y2)
           
            call GroupRemoveUnit(copy, fire)
            set fire = null
        endloop
    endfunction
   
    private function SFXDestroy takes nothing returns nothing
   
        local unit sfx = GetEnumUnit()
       
        call DestroySFX(sfx)
        call DummyAddRecycleTimer(sfx, 0.7) //recycles dummy
       
        set sfx = null //removing leaks
       
    endfunction
    private function ubwtargets takes nothing returns boolean
        local unit pick = GetFilterUnit()
        local boolean b = true
        if    GetWidgetLife(pick) < 0.405 then
            set b = false
        endif
        return b
    endfunction
   
    private function bordercontrol takes group g, real x, real y, real r, real up, real down returns nothing
    local unit u
    local real d
    local real a
    local real x2
    local real y2
    local real angle
    local real dx
    local real dy
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        set x2 = GetUnitX(u)
        set y2 = GetUnitY(u)
        set dx = x2 - x
        set dy = y2 - y
        set d = SquareRoot( dx*dx + dy*dy )
        set a = Atan2(dy, dx)
        if d < r then   
                if d > r - up then
                set x2 = x + (r - up)* Cos(a)
                set y2 = y + (r - up)* Sin(a)
                call SetUnitX(u, x2)
                call SetUnitY(u, y2)
                endif
               
        else
                if d < r + down then
                set x2 = x + (r + down)*Cos(a)
                set y2 = y + (r + down)*Sin(a)
                call SetUnitX(u, x2)
                call SetUnitY(u, y2)
                endif
        endif
        call GroupRemoveUnit(g, u)
        set u = null
       
    endloop
   
    endfunction
   
    private function periodic takes nothing returns nothing
        local tempDat this
        local integer i = 0  //loops through instances
        local integer looper
        local real angle
        local unit dummy
        local real x
        local real y
        local real size
       
        loop
            exitwhen i>dindex
            set this = data[i]
           
           
            //spell core
           
            if this.stage == 1 then
                if this.casttime > 0 then
                    set this.casttime = this.casttime - fps
                    else
                    if GetWidgetLife(this.caster) >= 0.405 then
                        //restoring player control
                        call PauseUnit(this.caster, false)                     //
                        call GroupRemoveUnit(CannotMove, this.caster)            //
                        call GroupRemoveUnit(CannotWalk, this.caster)            // For keyboard movement system
                        call GroupRemoveUnit(CannotTurn, this.caster)            //
                        set this.stage = 2  //sets spells stage
                        set this.ubwx = GetUnitX(this.caster) //sets spell loc
                        set this.ubwy = GetUnitY(this.caster) //sets spell loc                   
                        //CREATING FIRE SFX
                        set looper = 0 
                        set angle = GetRandomReal(0, 360)
                        loop
                            exitwhen looper >= FIRESFXCOUNT
                            set looper = looper + 1
                            set angle = angle + ANGLEPERFIRE(FIRESFXCOUNT) //sets angle of firesfx
                            set x = this.ubwx + 5 * Cos( Deg2Rad (angle) ) //adds offset, for spinning effect
                            set y = this.ubwy + 5 * Sin( Deg2Rad (angle) )
                            set dummy = GetRecycledDummy(x,y,0.0, angle) //dummy recycler by flux
                            call CreateSFX( dummy, FIRESFX, FIRETRAILSFX) //self made system for sfx
                            call GroupAddUnit(this.ubwdummygroup, dummy) //adds firesfx to group
                            call SetUnitScale(dummy, FIRESFXSIZE, 1, 1)
                       
                        endloop   
                    else
                        set this.stage = 0
                    endif
                endif   
           
            else 
           
                if this.stage == 2 then
                    if this.formtime > 0 then
                        set this.formtime = this.formtime - fps       
                        set this.swordspawnaoe = this.swordspawnaoe + this.speed
                        call FireSpreadSpin(this.ubwdummygroup,this.ubwx, this.ubwy,this.swordspawnaoe)   //moves fire and spins
                        set looper = 0
                        set this.swordcount = this.swordcount + SWORDSFXINC   //creating swords, forms as fire boundary expands
                        loop
                            exitwhen looper >= R2I(this.swordcount)
                            set looper = looper + 1
                            set angle = Deg2Rad(GetRandomReal(0, 360))
                            set x = this.ubwx + (this.swordspawnaoe + GetRandomReal(-125, -25) )*Cos(angle)
                            set y = this.ubwy + (this.swordspawnaoe + GetRandomReal(-125, -25) )*Sin(angle)
                           
                            set dummy = GetRecycledDummy(x,y, SWORDFXHEIGHT , Rad2Deg(angle))
                            call CreateSFX(dummy, SWORDSFX, "")
                           
                            call GroupAddUnit(this.swordgroup, dummy)
                            call SetUnitScale(dummy, SWORDFXSIZE, 1, 1)
                            //call SetUnitTimeScale(dummy, 99)
                       
                        endloop
                   
                    else
                        set this.stage = 3
                        //Add UBW ABILITIES HERE
                        //creating Gears
                        set looper = 0
                        set angle = GetRandomReal(0, 360)
                        loop
                            exitwhen looper >= GEARFXCOUNT
                            set looper = looper + 1
                            set angle = angle + ANGLEPERGEAR(GEARFXCOUNT)
                            set x = this.ubwx + RADIUS * Cos ( Deg2Rad (angle) )
                            set y = this.ubwy + RADIUS * Sin ( Deg2Rad (angle) )
                           
                            set size = GEARSFXSIZE()
                           
                            set dummy = GetRecycledDummy(x,y, GEARSFXHEIGHT(size) , angle) //uses DummyRecycler by flux
                            call CreateSFX(dummy, GEARSFX() , "") //self made sfx system
                            call SetUnitScale(dummy, size, 1, 1 )
                            call SetUnitTimeScale(dummy, 0.5)
                            call GroupAddUnit(this.swordgroup, dummy)
                        endloop
                   
                    endif
                else
                    if this.stage == 3 then
                        if this.duration > 0 and GetWidgetLife(this.caster) >= 0.405 then
                            set this.duration = this.duration - fps                                                                //creates border group
                            call GroupEnumUnitsInRange(all, this.ubwx, this.ubwy, RADIUS, function ubwtargets)  //traps units inside boundary field
                            call bordercontrol(all, this.ubwx, this.ubwy, RADIUS, 115, 75)
                        else
                            set this.stage = 0
                        endif
                    endif
                endif
                if this.stage == 0 then
                    //Ending Spell
                    call ForGroup(this.ubwdummygroup, function SFXDestroy)
                    call ForGroup(this.swordgroup, function SFXDestroy)
                    set this.caster = null
                    call DestroyGroup(this.ubwdummygroup)
                    set this.ubwdummygroup = null
                    call DestroyGroup(this.swordgroup)
                    set this.swordgroup = null
                    //Destroying Instance
                    set data[i] = data[dindex]
                    set i = i - 1
                    set dindex = dindex - 1
                    call this.destroy()
                endif
            endif
        set i = i + 1
        endloop
    endfunction
   
    private function Cond takes nothing returns boolean
        local tempDat this
        if GetSpellAbilityId() == SPELLID then
            //instantiating
            set this = tempDat.create()
            //setup variables
            set this.caster = GetTriggerUnit()
            set this.casttime = CASTTIME
            set this.formtime = FORMTIME
            set this.duration = DURATION
            set this.stage = 1
            set this.speed = FIREFXSPEED( RADIUS, FORMTIME )
            set this.swordcount = SWORDSFXCOUNT
            set this.swordspawnaoe = 0
            //spell start
            call AttachSoundUnit(this.caster, "war3mapImported\\EMY_NP.mp3", 127, 9, 2000, false, true, 1500, 3000)
            call KillSoundWhenDone( AttachedSound)
            call PauseUnit(this.caster, true)
            call IssueImmediateOrder(this.caster, "stop")
            call SetUnitAnimation(this.caster, "Spell Three")
            //for movement trigger
            call GroupAddUnit(CannotMove, this.caster)          //
            call GroupAddUnit(CannotWalk, this.caster)         // For keyboard movement
            call GroupAddUnit(CannotTurn, this.caster)         //
            call GroupRemoveUnit(IsWalking, this.caster)       //
            //creating groups
            set this.ubwdummygroup = CreateGroup()
            set this.swordgroup = CreateGroup()
            //increasing Loop
            set dindex = dindex + 1
            set data[dindex] = this
            if dindex == 0 then
                call TimerStart(period, fps, true, function periodic)
            endif
        endif
        return false
    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 Cond ))
        set t = null
       
    endfunction
       
       
endscope
 
Last edited:
Status
Not open for further replies.
Top