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

[JASS] Script error

Status
Not open for further replies.
The code below works completely fine as as intended but for some unknown reason, after I cast it for a large amount of time my wc3 crashes.. I'm thinking there might be some leaks that I hadn't clean so maybe someone can see what leaks there still are or some other problems that may cause the fatal error. Thanks!

JASS:
///////////////////////////////////////////////////
//             Aqua Crush
//            by: Adiktuz
///////////////////////////////////////////////////
scope AquaCrush initializer Aqua_Init

//configurables
globals
    private constant integer FLY = 'Amrf' //Rawcode of Medivh's raven form
    private constant integer DUMMY = 'h001' //Rawcode of the dummy unit(horizontal)
    private constant integer SPELL = 'A001' //Rawcode of the spell
    private constant real DAMAGE = .833 //Explosion damage per level (multiply this value by 12)
    private constant real DAMAGER = 4.17 //Impact damage per level (multiply this by 12)
    private constant real HEIGHT = 600 //The maximum height that units will be thrown up to
    private constant string WAVE = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveMissile.mdl" //The path to the wave effect
    private constant string WATER = "Objects\\Spawnmodels\\Naga\\NagaDeath\\NagaDeath.mdl" //The path to the explosion effect
    private constant real AOE = 150 //The radius of the spell
    private constant real RANGE = 500 //The distance of the waves from the target point
    private constant real SPEED = 20 //The rate at which the waves move
    private constant real LIFTSPEED = 20 //The rate at which units get thrown up/down
    private attacktype ATYPE = ATTACK_TYPE_MAGIC //The attack type of the spell
    private damagetype DTYPE = DAMAGE_TYPE_COLD //The damage type of the spell
    private boolean SE = false //If true, there will be an explosion effect
    private boolean TREE = true //If set to true, the explosion will also destroy destructibles: if you use the normal bridges make them invulnerable or the spell will also destroy them.
//End of configurables
    private integer array Data 
    private integer array Datax
    private integer Total = 0
    private integer Totalx = 0
    private timer t = CreateTimer()
    private timer tx = CreateTimer()
    private group Temp = CreateGroup()
endglobals

private struct AC
real x
real y
real distance
real facing
unit u
real height
effect wave
player owner
unit v
integer level
boolean direction = false


    static method create takes real x, real y, player p, real facing, integer level returns AC
        local AC dat = AC.allocate()
        set Data[Total] = dat
        set dat.x = x - RANGE*Cos(facing*bj_DEGTORAD)
        set dat.y = y - RANGE*Sin(facing*bj_DEGTORAD)
        set dat.u = CreateUnit(p, DUMMY, dat.x, dat.y, facing)
        set dat.distance = RANGE
        set dat.owner = p
        set dat.level = level
        set dat.facing = facing*bj_DEGTORAD
        set dat.wave = AddSpecialEffectTarget(WAVE, dat.u, "chest")
        if Total == 0 then
            call TimerStart(t, .03, true, function AC.move)
        endif
        set Total = Total + 1
        set p = null
        return dat
    endmethod
    
    method onDestroy takes nothing returns nothing
        local rect r = Rect(this.x - AOE, this.y - AOE, this.x + AOE, this.y + AOE)
        //if TREE then
            //call EnumDestructablesInRect(r, null, function Dest)
        //endif
        call DestroyEffect(this.wave)
        call KillUnit(this.u)
        set this.u = null
        set this.wave = null
        set this.owner = null
        set this.v = null
        call RemoveRect(r)
        set r = null
    endmethod
    
    static method move takes nothing returns nothing
        local AC dat
        local integer i = 0
        local unit u
        local unit x
        loop
            exitwhen i == Total
            set dat = Data[i]
            set dat.x = dat.x + SPEED*Cos(dat.facing)
            set dat.y = dat.y + SPEED*Sin(dat.facing)
            call SetUnitPosition(dat.u, dat.x, dat.y)
            set dat.distance = dat.distance - SPEED
            if dat.distance == 0 then
                call GroupEnumUnitsInRange(Temp, dat.x, dat.y, AOE, null)
                loop
                    set u = FirstOfGroup(Temp)
                    exitwhen u == null
                    if (IsPlayerEnemy(GetOwningPlayer(u), dat.owner) and GetWidgetLife(u) > .405) then
                        call AC.LiftStart(u,dat.u, dat.level)
                        call UnitDamageTarget(dat.u,u, dat.level*DAMAGE, false, false, ATYPE, DTYPE, WEAPON_TYPE_WHOKNOWS)
                    endif
                    call GroupRemoveUnit(Temp, u)
                endloop
                if SE then
                    call DestroyEffect(AddSpecialEffectTarget(WATER, dat.u, "origin"))
                endif
                call dat.destroy()
                set Total = Total - 1
                set Data[i] = Data[Total]
                set i = i - 1
            endif
            set i = i + 1
        endloop
        if Total == 0 then
            call PauseTimer(t)
        endif
        set x = null
        set u = null
    endmethod
    
    static method LiftStart takes unit u,unit x, integer level returns nothing
        local AC dat = AC.allocate()
        set dat.x = GetUnitX(u)
        set dat.y = GetUnitY(u)
        call UnitAddAbility(u, FLY)
        call UnitRemoveAbility(u, FLY)
        call SetUnitFlyHeight(u, 10.00, 0)
        set dat.v = u
        set dat.u = x
        set dat.level = level
        set Datax[Totalx] = dat
        if Totalx == 0 then
            call TimerStart(tx, .03, true, function AC.Lift)
        endif
        set Totalx = Totalx + 1
        set u = null
        set x = null
    endmethod
    
    static method Lift takes nothing returns nothing
        local AC dat
        local integer i = 0
        loop
            exitwhen i == Totalx
            set dat = Datax[i]
            if dat.direction then
                set dat.height = dat.height - LIFTSPEED
                call SetUnitPosition(dat.v,dat.x,dat.y)
                call SetUnitFlyHeight(dat.v,dat.height,0)
            else
                set dat.height = dat.height + LIFTSPEED
                call SetUnitPosition(dat.v,dat.x,dat.y)
                call SetUnitFlyHeight(dat.v,dat.height,0)
                if dat.height >= 600 then
                    set dat.direction = true
                endif
            endif
            if dat.height == 0 then
                call UnitDamageTarget(dat.u,dat.v, dat.level*DAMAGER, false, false, ATYPE, DTYPE, WEAPON_TYPE_WHOKNOWS)
                set dat.u = null
                set dat.v = null
                call dat.destroy()
                set Totalx = Totalx - 1
                set Datax[i] = Datax[Totalx]
                set i = i - 1
            endif
            set i = i + 1
        endloop
        if Totalx == 0 then
            call PauseTimer(tx)
        endif
    endmethod
endstruct

function Aqua_Check takes nothing returns boolean
    return GetSpellAbilityId() == SPELL
endfunction

function Aqua_Start takes nothing returns nothing
    local integer i = 0
    local unit a = GetTriggerUnit()
    local real x = GetSpellTargetX()
    local real y = GetSpellTargetY()
    loop
        exitwhen i == 12
        call AC.create(x,y,GetOwningPlayer(a), i*(30), GetUnitAbilityLevel(a, SPELL))
        set i = i + 1
    endloop
    set a = null
endfunction

function Aqua_Init takes nothing returns nothing
    local trigger Aqua = CreateTrigger(  )
    call TriggerAddAction( Aqua, function Aqua_Start )
    call TriggerAddCondition(Aqua, function Aqua_Check)
    call TriggerRegisterAnyUnitEventBJ(Aqua, EVENT_PLAYER_UNIT_SPELL_EFFECT)
endfunction

endscope

BTW, is it okay to have 2 scopes with the same set of private globals?
 
Adiktuz said:
BTW, is it okay to have 2 scopes with the same set of private globals?

Yes, as long as the scopes are named differently.
You will get a syntax error if they aren't anyways.

Adiktuz said:
The code below works completely fine as as intended but for some unknown reason, after I cast it for a large amount of time my wc3 crashes.. I'm thinking there might be some leaks that I hadn't clean so maybe someone can see what leaks there still are or some other problems that may cause the fatal error. Thanks!

Well, you could be hitting the OP limit but that most likely wouldn't cause a fatal error.
The only other circumstances I could think of is that total is not getting recycled properly.

Are you sure it's the spell causing the problem? As in the game crashes once you cast it?
 
Yes, as long as the scopes are named differently.
You will get a syntax error if they aren't anyways.



Well, you could be hitting the OP limit but that most likely wouldn't cause a fatal error.
The only other circumstances I could think of is that total is not getting recycled properly.

Are you sure it's the spell causing the problem? As in the game crashes once you cast it?

what's the OP limit? it crashes when I spam it for some time. I'll post the map later so that you can try if it crashes in your pc.

SOLVED: I found that it only crashes when the dummies are created outside the map bounds....
 
Last edited:
Status
Not open for further replies.
Top