• 🏆 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] Rain

Status
Not open for further replies.
Level 8
Joined
Jul 28, 2008
Messages
211
I'm making a rain (blizard) like spell for a map. Here's the code:

JASS:
scope Rain initializer Init 

globals

    private constant integer SPELL_ID = 'A003'
    private constant integer DUMMY_ID = 'hpea'
    private constant real PERIOD = 0.05
    private constant real AOE = 500.
    private constant real FALL = 1000.
    
    private timer TIMER = CreateTimer()
    private group G = CreateGroup()
    
endglobals

private function NumberOfDummies takes integer lvl returns integer
    return lvl * 6 + 14
endfunction

private struct Rain

    unit caster
    unit array dummy [50]
    integer lvl
    real hight
    boolean fall
    real speed
    
    static integer Total = 0
    static Rain array ar
    
    static method Loop takes nothing returns nothing
        local Rain r
        local integer i = 0
        local integer ii = 0
        loop
            exitwhen i >= Rain.Total
            set r = Rain.ar[i]
            if r.hight > 0 then
                loop
                    exitwhen ii >= NumberOfDummies(r.lvl)
                    call SetUnitFlyHeight(r.dummy[ii], r.hight, 9999.)
                    call BJDebugMsg(I2S(GetHandleId(r.dummy[ii])))
                    set ii = ii + 1
                endloop
                if r.hight >= FALL then
                    set r.fall = true
                    call BJDebugMsg("Fall")
                    set r.hight = FALL - 0.01
                endif
                if r.fall == true then
                    set r.hight = r.hight - 20 - r.speed
                    set r.speed = r.speed + 0.6
                else
                    set r.hight = r.hight + 20 + r.speed
                endif
            else
                loop
                    exitwhen ii >= NumberOfDummies(r.lvl)
                    call RemoveUnit(r.dummy[ii])
                    set ii = ii + 1
                endloop
                //Damage
                call BJDebugMsg("Remove")
                call r.destroy()
                set Rain.Total = Rain.Total - 1
                set Rain.ar[i] = Rain.ar[Rain.Total]
                set i = i - 1
            endif
            set i = i + 1
        endloop
        if Rain.Total == 0 then
            call PauseTimer(TIMER)
        endif
    endmethod
    
    static method Start takes unit caster returns nothing
        local Rain r = Rain.allocate()
        local integer i = 0
        local real x 
        local real y 
        set r.caster = caster
        set r.hight = 1
        set r.speed = 0
        set r.fall = false
        set r.lvl = GetUnitAbilityLevel(caster, SPELL_ID)
        loop
            exitwhen i >= NumberOfDummies(r.lvl)
            set x = GetUnitX(caster) + GetRandomReal(50., AOE) * Cos(GetRandomReal(0., 360.) * bj_DEGTORAD)
            set y = GetUnitY(caster) + GetRandomReal(50., AOE) * Sin(GetRandomReal(0., 360.) * bj_DEGTORAD)
            set r.dummy[i] = CreateUnit(GetOwningPlayer(caster), DUMMY_ID, x, y, 0.)
            call UnitAddAbility(r.dummy[i], 'Amrf')
            set i = i + 1
        endloop
        set Rain.ar[Rain.Total] = r
        if Rain.Total == 0 then
            call TimerStart(TIMER, PERIOD, true, function Rain.Loop)
        endif
        set Rain.Total = Rain.Total + 1
    endmethod

endstruct

private function Cond takes nothing returns boolean
    return true
endfunction

private function Act takes nothing returns nothing
    call Rain.Start(GetTriggerUnit())
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))
    call TriggerAddAction(t, function Act)
endfunction

endscope

Now, it works, but there are 2 things that don't. First, when I use my dummy unit (I used a peasant here), the unit just won't fly. I removed locust from the dummy, and it's selection circle goes up while it doesn't. How do I fix this?
Second, when I cast the spell once and then again while the first one is still active, both will appear, but the second spell units won't fly untill the first spell ends. The hight variable WILL increase, and the units will get the fly hight they should have had but only when the first spell ends. When the first one ends, units from the second one just warp to the position they should have been at. So it works, but they won't start flying untill the first one's done. Why does this happen?

Thanks in advance.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
What do you want to do with integer ii?

Do you expect it to be at 0 only at the top of the function, or within the loop? Usually with a loop within another loop you want to set a variable like ii back to zero before entering the nested loop. I recommend you change:

JASS:
exitwhen i >= Rain.Total
set r = Rain.ar[i]

to

JASS:
exitwhen i >= Rain.Total
set r = Rain.ar[i]
set ii = 0

And because spelling is an essential quality of a programmer, the word is 'height', not 'hight' ;)
 
Status
Not open for further replies.
Top