• 🏆 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!

[Solved] Unidentified Crash

Status
Not open for further replies.
Level 10
Joined
Jun 17, 2014
Messages
236
Hello hive, i've here again and ask for help again........

why i here is because my snippet is crashed when duration < 0 or when destroyed(?).
i dont see a problem on static method periodic or on method onDestroy.

i dont see anything wrong with my script.
been on eye for 1 hour and still crashed.

example :
ZS.onPoint(...) with 5 sec duration
after 5 second, the game crashed (not responding) and exit.

JASS:
library ZS/*
                            S.Effect Manager
                          Created By userid907
            http://www.hiveworkshop.com/members/userid907.238703/
                   Note : THIS LIBRARY REQUIRES NOTHING
        This System allow you to create special effect on unit or point with height/z
                          and custom scale also with duration
  
        How to Import :
            1.Import "war3mapImported\DUMMY" from this map to your map if you don't have it.
            2.Copy Dummy unit from object manager to your map if you don't have dummy unit
            3.Set DUMMYID on globals to your Dummy object id
            4.See test trigger on Demo trigger folder on this map to know how to use
    [-----]
    [-API-]
    [-----]
    struct ZS
        static method onUnit takes string efxmodel,unit target,real z,real scale,real duration returns thistype
            - Create special effect on unit (follow unit)
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        static method onPoint takes string efxmodel,real x1,real y1,real z,real scale,real duration returns thistype
            - Create special effect on a fixed coordinate/point (x,y)
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        static method onUnitF takes string efxmodel,real x1,real y1,real z,real scale,real duration,real face returns thistype
            - Same as onUnit but the effect has fixed facing when created
            ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        static method onPointF takes string efxmodel,real x1,real y1,real z,real scale,real duration returns thistype
            - Same as onPoint but the effect has fixed facing when created
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        method destroy takes nothing returns nothing
            - Destroy the effect instantly.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ############################################################################################################
        ############################################################################################################
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        */
        /*
        *******************************
        *[ AVAILABLE METHOD OPERATOR ]*
        *[      FOR YOUR OWN USE     ]*
        *******************************
        method operator target takes nothing returns unit
        method operator target= takes unit newtarget returns nothing
        method operator facing= takes real angle returns nothing
        method operator facing takes nothing returns real
        method operator pitch= takes real angle returns nothing
        method operator pitch takes nothing returns real
        method operator x= takes real val returns nothing
        method operator x takes nothing returns real
        method operator y= takes real val returns nothing
        method operator y takes nothing returns real
        method operator z= takes real val returns nothing
        method operator z takes nothing returns real
        method operator alpha takes nothing returns integer
        method operator red takes nothing returns integer
        method operator green takes nothing returns integer
        method operator blue takes nothing returns integer
        method setColor takes integer a, integer r, integer g, integer b returns nothing
        method operator scale= takes real val returns nothing
        method operator scale takes nothing returns real
        method operator model= takes string sfx returns nothing
        method operator model takes nothing returns string
        method operator owner= takes player pk returns nothing
        method operator owner takes nothing returns player
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ############################################################################################################
        ############################################################################################################
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        method playAnimByIndex takes integer index returns nothing
            - set effect specific animation by index
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        method playAnim takes string anim returns nothing
            - set effect specific animation
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        method changeToPoint takes real newX,real newY,real newZ returns nothing
            - set an effect to a point, mean the effect will not follow the unit target again.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        method changeToUnit takes unit target returns nothing
            - set an effect to an unit, mean the effect will follow unit target.
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
       ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    endstruct
  
*/
// CONFIGURATION
    globals
        private constant integer DUMMYID =  'dumi' // set the dummy unit here
        // NOTE : DON'T FORGET TO IMPORT "war3mapImported\DUMMY.mdx" ON THIS MAP TO YOUR MAP
        private constant player DUMMYOWNER = Player(15) // the owner of DUMMYID unit
        private constant real FPS = 0.03125 // higher value = worth fps, weird effect move, lower value = worst fps, great effect move
        private constant boolean TESTMODE = false // IF TRUE THE DEBUG MESSAGE WILL COME OUT
        private constant boolean TESTMODELOOP = false
    endglobals
// ENDCONFIGURATION
    struct ZS
        unit t_target
        real duration
        unit efx
        real t_x
        real t_y
        effect t_tef
        string t_sfx
        player t_p
        real t_fac
        real t_pitch
        real t_z
        real t_scale
        integer t_red
        integer t_green
        integer t_blue
        integer t_alpha
      
        static integer dindex
        static timer period
        static thistype array data
        method operator target takes nothing returns unit
            return t_target
        endmethod
        method operator target= takes unit newtarget returns nothing
            set t_target = newtarget
        endmethod
        method operator facing= takes real angle returns nothing
            if efx != null then
                set t_fac = angle
                call SetUnitFacing(efx,t_fac)
            endif
        endmethod
      
        method operator facing takes nothing returns real
            return t_fac
        endmethod
      
        method operator pitch= takes real angle returns nothing
            local integer i
            if efx != null then
                set i = R2I(angle + 90.5)
                set t_pitch = angle
                call SetUnitAnimationByIndex(efx, i)
            endif
        endmethod
      
        method operator pitch takes nothing returns real
            return t_pitch
        endmethod
      
        method operator x= takes real val returns nothing
            if efx != null then
                set t_x = val
                call SetUnitX(efx, val)
            endif
        endmethod
      
        method operator x takes nothing returns real
            return t_x
        endmethod
      
        method operator y= takes real val returns nothing
            if efx != null then
                set t_y = val
                call SetUnitY(efx, val)
            endif
        endmethod
      
        method operator y takes nothing returns real
            return t_y
        endmethod
      
        method operator z= takes real val returns nothing
            if efx != null then
                set t_z = val
                call SetUnitFlyHeight(efx, val, 0.)
            endif
        endmethod
      
        method operator z takes nothing returns real
            return t_z
        endmethod
      
        method operator alpha takes nothing returns integer
            return t_alpha
        endmethod
      
        method operator red takes nothing returns integer
            return t_red
        endmethod
      
        method operator blue takes nothing returns integer
            return t_blue
        endmethod
      
        method operator green takes nothing returns integer
            return t_green
        endmethod
      
        method setColor takes integer a, integer r, integer g, integer b returns nothing
            if efx != null then
                set t_alpha = a
                set t_red = r
                set t_green = g
                set t_blue = b
                call SetUnitVertexColor(efx, r, g, b, a)
            endif
        endmethod
      
        method operator scale= takes real val returns nothing
            if efx != null then
                set t_scale = val
                call SetUnitScale(efx, val, 0, 0)
            endif
        endmethod
      
        method operator scale takes nothing returns real
            return t_scale
        endmethod
      
        method operator model= takes string sfx returns nothing
            if efx != null then
                if t_tef != null then
                    call DestroyEffect(t_tef)
                endif
                set t_sfx = sfx
                set t_tef = AddSpecialEffectTarget(sfx, efx, "origin")
            endif
        endmethod
      
        method operator model takes nothing returns string
            return t_sfx
        endmethod
      
        method operator owner= takes player pk returns nothing
            if efx != null then
                set t_p = pk
                call SetUnitOwner(efx, pk, false)
            endif
        endmethod
      
        method operator owner takes nothing returns player
            return t_p
        endmethod
      
        method onDestroy takes nothing returns nothing
            //call BJDebugMsg("destroyed")
            call DestroyEffect(.t_tef)
            call KillUnit(.efx)
            set .t_target = null
            set .efx = null
            set .t_tef = null
      
            if dindex == -1 then
                call PauseTimer( period )
            endif
            call this.deallocate( )
        endmethod
        method destroy takes nothing returns nothing
            set this.duration = 0.
        endmethod
        method changeToPoint takes thistype d,real newX,real newY, real newZ returns nothing
            set this.t_target = null
            call SetUnitX(this.efx,newX)
            call SetUnitY(this.efx,newY)
            set this.t_x = newX
            set this.t_y = newY
            set this.t_z = newZ
        endmethod
        method changeToUnit takes unit target returns nothing
            set this.t_target = target
        endmethod
        method playAnim takes string anim returns nothing
            call SetUnitAnimation(this.efx,anim)
        endmethod
        method playAnimByIndex takes integer index returns nothing
            call SetUnitAnimationByIndex(this.efx,index)
        endmethod
        static method onUnit takes string efxmodel,unit targetx,real zx,real scalex,real duration returns thistype
            local thistype this
            set this = thistype.allocate( )
            set .t_target = targetx
            set .efx = CreateUnit(DUMMYOWNER,DUMMYID,GetUnitX(.t_target),GetUnitY(.t_target),0.)
            call SetUnitScale(.efx,scalex,scalex,scalex)
            set .t_scale = scalex
            set .t_tef = AddSpecialEffectTarget(efxmodel,.efx,"origin")
            call SetUnitFlyHeight(.efx,zx,99999999.)
            set .t_x = GetUnitX(.efx)
            set .t_y = GetUnitY(.efx)
            set .t_sfx = efxmodel
            set .t_fac = GetUnitFacing(.efx)
            set .t_z = zx
            set .t_p = GetOwningPlayer(.efx)
            if duration > 0.00 then
            set .duration = duration
            else
            set .duration = 99999999.
            endif
            if TESTMODE then
                call BJDebugMsg( "Created SFX with path : '" + efxmodel + "' with : " +GetUnitName(.t_target) +" as target and z =" + R2S(zx) )
            endif
            set dindex = dindex + 1
            set data[dindex] = this
            if dindex == 0 then
                call TimerStart( period, FPS, true, function thistype.periodic )
            endif
            return this
        endmethod
        static method onPoint takes string efxmodel,real x1,real y1,real z,real scale,real duration returns thistype
            local thistype this
            set this = thistype.allocate( )
            set .efx = CreateUnit(DUMMYOWNER,DUMMYID,x1,y1,0.)
            call SetUnitScale(.efx,scale,scale,scale)
            set .t_tef = AddSpecialEffectTarget(efxmodel,.efx,"origin")
            call SetUnitFlyHeight(.efx,z,99999999.)
            set .t_x = GetUnitX(.efx)
            set .t_y = GetUnitY(.efx)
            set .t_sfx = efxmodel
            set .t_scale = scale
            set .t_fac = GetUnitFacing(.efx)
            set .t_z = z
            set .t_p = GetOwningPlayer(.efx)
          
            if duration > 0.00 then
            set .duration = duration
            else
            set .duration = 99999999.
            endif
            if TESTMODE then
                call BJDebugMsg( "Created SFX with path : '" + efxmodel + "' at(" + R2S(x1) + "," + R2S(y1) + ") with z =" + R2S(z) )
            endif
            set dindex = dindex + 1
            set data[dindex] = this
            if dindex == 0 then
                call TimerStart( period, FPS, true, function thistype.periodic )
            endif
            return this
        endmethod
      
        static method periodic takes nothing returns nothing
            local integer i = 0
            local ZS this
            loop
                exitwhen i > dindex
                set this = data[i]
                set .duration = .duration - FPS
                if .t_target != null then
                    if not UnitAlive(.t_target) then
                        set data[i] = data[dindex]
                        set i = i - 1
                        set dindex = dindex - 1
                        call this.onDestroy()
                    endif
                    call SetUnitX(.efx,GetUnitX(.t_target))
                    call SetUnitY(.efx,GetUnitY(.t_target))
                    call SetUnitFlyHeight(.efx,.t_z,99999999.)
                    set .t_x = GetUnitX(.efx)
                    set .t_y = GetUnitY(.efx)
                    set .t_fac = GetUnitFacing(.efx)
                    set .t_z = GetUnitFlyHeight(.efx)
                    set .t_p = GetOwningPlayer(.efx)
                endif
                //call BJDebugMsg(R2S(.duration))
                if .duration <= 0 then
                    set data[i] = data[dindex]
                    set i = i - 1
                    set dindex = dindex - 1
                    //call BJDebugMsg("destroying...")
                    call this.onDestroy( )
                endif
                set i = i + 1
            endloop
        endmethod
        static method onUnitF takes string efxmodel,unit target,real z,real scale,real duration,real face returns thistype
            local thistype this
            set this = thistype.allocate( )
            set .t_target = target
            set .efx = CreateUnit(DUMMYOWNER,DUMMYID,GetUnitX(.t_target),GetUnitY(.t_target),face)
            call SetUnitScale(.efx,scale,scale,scale)
            set .t_scale = scale
            set .t_tef = AddSpecialEffectTarget(efxmodel,.efx,"origin")
            call SetUnitFlyHeight(.efx,z,99999999.)
            set .t_x = GetUnitX(.efx)
            set .t_y = GetUnitY(.efx)
            set .t_sfx = efxmodel
            set .t_fac = GetUnitFacing(.efx)
            set .t_z = z
            set .t_p = GetOwningPlayer(.efx)
            if duration > 0.00 then
            set .duration = duration
            else
            set .duration = 99999999.
            endif
            if TESTMODE then
                call BJDebugMsg( "Created SFX with path : '" + efxmodel + "' with : " +GetUnitName(.t_target) +" as target and z =" + R2S(z) )
            endif
            set dindex = dindex + 1
            set data[dindex] = this
            if dindex == 0 then
                call TimerStart( period, FPS, true, function thistype.periodic )
            endif
            return this
        endmethod
        static method onPointF takes string efxmodel,real x1,real y1,real z,real scale,real duration,real face returns thistype
            local thistype this
            set this = thistype.allocate( )
            set .efx = CreateUnit(DUMMYOWNER,DUMMYID,x1,y1,face)
            call SetUnitScale(.efx,scale,scale,scale)
            set .t_tef = AddSpecialEffectTarget(efxmodel,.efx,"origin")
            call SetUnitFlyHeight(.efx,z,99999999.)
            set .t_x = GetUnitX(.efx)
            set .t_y = GetUnitY(.efx)
            set .t_sfx = efxmodel
            set .t_fac = GetUnitFacing(.efx)
            set .t_z = z
            set .t_p = GetOwningPlayer(.efx)
            set .t_scale = scale
            if duration > 0.00 then
            set .duration = duration
            else
            set .duration = 99999999.
            endif
            if TESTMODE then
                call BJDebugMsg( "Created SFX with path : '" + efxmodel + "' at(" + R2S(x1) + "," + R2S(y1) + ") with z =" + R2S(z) )
            endif
            set dindex = dindex + 1
            set data[dindex] = this
            if dindex == 0 then
                call TimerStart( period, FPS, true, function thistype.periodic )
            endif
            return this
        endmethod
      
        static method onInit takes nothing returns nothing
            set dindex = -1
            set period = CreateTimer( )
        endmethod
    endstruct
endlibrary

thank you....
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
Try changing this
JASS:
static method periodic takes nothing returns nothing
            local integer i = 0
            local ZS this
            loop
                exitwhen i > dindex
                // ...
                set i = i + 1
            endloop
        endmethod

to this

JASS:
static method periodic takes nothing returns nothing
            local integer i = 0
            local ZS this
            loop
                set i = i + 1
                // ...
                set exitwhen i == dindex
            endloop
        endmethod
 
Haven't read all code, but AGD, why? The exitwhen seems to be good at top, I guess, or?

onDestroy() -> destroy()

restructure the deindex part at periodic function, so you have only one code part for deindexing. At the moment it's a bit mixed up.

Something like "dindex" seems like a not fitting name, it makes it harder to read and understand. Also for example "periodic" for a timer name.
crashed when duration < 0
Where does it crash exactly?
 
Level 10
Joined
Jun 17, 2014
Messages
236
Try changing this
......

I can't test it on WE right now
and i see that not solving the problem.

on initializing, dindex is -1, and +1 when constructor called and data[dindex].

so your code(loop) will run like this (i think)
on construct :
dindex = 0
this = 1
data[dindex] = this

on loop
dindex| i | data (this) |
0 | 1 | null |

data is null because ++i makes data[i=1] and it's null or not measured.

//
my code :
on construct :
dindex = 0
this = 1
data[dindex] = this

on loop
dindex| i | data (this) |
0 | 0 | 1(from constructor) |
 
Level 10
Joined
Jun 17, 2014
Messages
236
onDestroy() -> destroy()
it's destroy() -> onDestroy()
actually destroy() is manual destroying.

restructure the deindex part at periodic function, so you have only one code part for deindexing. At the moment it's a bit mixed up.

how?, i don't understand

Something like "dindex" seems like a not fitting name, it makes it harder to read and understand. Also for example "periodic" for a timer name.

Sorry for bad JPAG

Where does it crash exactly?

I dont know where the crash exactly is, is it when onDestroy() or on the if .duration <= 0 then

EDIT : Sorry for double post
 
Ah, ok, I see. You should not redeclare it like this, and not giving .destroy an other sense.

Make all deindexing inside the .destroy() method, including deallocatate(). if onDestroy exists it will be called after the destroy() method, but you don't need it here. It may be only important when you use inheritance /extends feature.

So I would suggest to remove the onDestroy, and move everything into the destroy(). When calling destroy() everything will be covered there already, deallocate, deindexing, pasue timer.
 
Level 10
Joined
Jun 17, 2014
Messages
236
Ah, ok, I see. You should not redeclare it like this, and not giving .destroy an other sense.

Make all deindexing inside the .destroy() method, including deallocatate(). if onDestroy exists it will be called after the destroy() method, but you don't need it here. It may be only important when you use inheritance /extends feature.

So I would suggest to remove the onDestroy, and move everything into the destroy(). When calling destroy() everything will be covered there already, deallocate, deindexing, pasue timer.

aww.. yes..
that will solve the problem maybe

gonna try it later on WE

EDIT : thanks!, it's working
 
Last edited:
Level 7
Joined
Oct 19, 2015
Messages
286
Of course the whole thing crashed, you called .deallocate() from onDestroy which caused an infinite loop. A standard vJass deallocator will automatically call onDestroy if a method with that name is present. The call to onDestroy is done before double free protection, which enables the infinite loop to occur. This is another good reason to not use onDestroy ever again now that we are able to write custom destructors.
 
Status
Not open for further replies.
Top