• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Ability Doesn't Work...

Status
Not open for further replies.
Level 12
Joined
Feb 23, 2007
Messages
1,030
JASS:
function GraveCallingSpell takes nothing returns boolean
    return GetSpellAbilityId() == 'A01X'
endfunction

function GraveCallingFilter takes nothing returns boolean
    return IsUnitType(GetFilterUnit(), UNIT_TYPE_ANCIENT)==false and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)==false and GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE)>.4
endfunction

function GraveCallingTimer takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer p = GetHandleInt(t,"p")
local integer lvl = GetHandleInt(t,"lvl")
local integer c = GetHandleInt(t,"c")
local integer z = GetHandleInt(t,"z")
local unit array u
local integer a
local real x1
local real y1
local real x2
local real y2
local real d
call SetHandleInt(t,"z",z+1)

loop
    exitwhen a>c
    set u[a] = GetHandleUnit(t,"unit"+I2S(a))
    if GetUnitState(u[a], UNIT_STATE_LIFE)<.4 and GetUnitTypeId(u[a]) != Zombie1() and GetUnitTypeId(u[a]) != Zombie2() and GetUnitTypeId(u[a]) != Zombie3() and GetUnitTypeId(u[a]) != Zombie4() and GetUnitTypeId(u[a]) != Zombie5() then
        if lvl == 1 then
            set u[a] = CreateUnit(Player(p),Zombie1(),GetUnitX(u[a]),GetUnitY(u[a]),270)
        elseif lvl == 2 then
            set u[a] = CreateUnit(Player(p),Zombie2(),GetUnitX(u[a]),GetUnitY(u[a]),270)
        elseif lvl == 3 then
            set u[a] = CreateUnit(Player(p),Zombie3(),GetUnitX(u[a]),GetUnitY(u[a]),270)
        elseif lvl == 4 then
            set u[a] = CreateUnit(Player(p),Zombie4(),GetUnitX(u[a]),GetUnitY(u[a]),270)
        elseif lvl == 5 then
            set u[a] = CreateUnit(Player(p),Zombie5(),GetUnitX(u[a]),GetUnitY(u[a]),270)
        endif
        call UnitAddAbility(u[a],'A01Y')
        call SetHandleHandle(t,"unit"+I2S(a),u[a])
    endif
    set x1 = x1+GetUnitX(u[a])
    set y1 = y1+GetUnitY(u[a])
    set a = a+1
endloop
set a = 0

set x2 = x1/c
set y2 = y1/c

loop
    exitwhen a>c
    set x1 = GetUnitX(u[a])
    set y1 = GetUnitY(u[a])
    call SetUnitAbilityLevel(u[a],'A01Y',IMaxBJ(R2I(SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)))/50,20))
    set a = a+1
endloop
set a = 0

if z == 6 then
call DisplayTextToPlayer(Player(p),0,0,"THIS SUCKS AT LIFE")
call DestroyLightning(GetHandleLightning(t,"l0"))
    loop
        exitwhen a>c
        call DestroyLightning(GetHandleLightning(t,"l"+I2S(a)))
        set a = a+1
    endloop
elseif z == 200 then
call DisplayTextToPlayer(Player(p),0,0,"THIS SUCKS AT LIFE")
    loop
        exitwhen a>c
        call UnitRemoveAbilityBJ('A01Y',u[a])
        set u[a] = null
        set a = a+1
    endloop
    call FlushHandleLocals(t)
    call PauseTimer(t)
    call DestroyTimer(t)
endif

set t = null
endfunction

function GraveCallingActions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit w = GetSpellTargetUnit()
local real x = GetUnitX(w)
local real y = GetUnitY(w)
local group g = CreateGroup()
local timer t = CreateTimer()
local integer c = 1
local unit q
local lightning l

call GroupEnumUnitsInRange(g, x, y, 500, Condition(function GraveCallingFilter))
call SetHandleHandle(t,"unit0",t)
call SetHandleHandle(t,"effect0",AddLightning("DRAL",true,GetUnitX(u),GetUnitY(u),GetUnitX(w),GetUnitY(w)))

loop
    exitwhen c>5 or q==null
    set q = FirstOfGroup(g)
    set l = AddLightning("DRAL",true,GetUnitX(w),GetUnitY(w),GetUnitX(q),GetUnitY(q))
    call SetHandleHandle(t,"l"+I2S(c),l)
    call SetHandleHandle(t,"unit"+I2S(c),q)
    set w = q
    call GroupRemoveUnit(g,q)
    set c = c+1
endloop

call SetHandleInt(t,"p",GetPlayerId(GetOwningPlayer(u)))
call SetHandleInt(t,"lvl",GetUnitAbilityLevel(u,'A01X'))
call SetHandleInt(t,"c",c)
call SetHandleInt(t,"z",0)
call TimerStart(t,0.04,true, function GraveCallingTimer)

call DestroyGroup(g)
set u = null
set t = null
set g = null
set q = null
set w = null
set l = null
endfunction

//===========================================================================
function InitTrig_Grave_Calling takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function GraveCallingSpell))
    call TriggerAddAction(t, function GraveCallingActions)
endfunction

The lightnings are created, but never destroyed.
The slow ability 'A01Y' never gets added...
The whole thing just doesn't seem to work!
It seems that the structs are not being attached at all.
I added in THIS SUX AT LIFE to help me debug.

Please help me :O
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
It's really pointless to debug that; lightnings and LHV do not go well together. Same with other handles, but to a far lesser extent. Even if there is a specific problem found, it will still chaotically bug.

You really should either be using a struct or a timer stack (depending whether or not you want to use vJass) to solve this.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
JASS:
scope ASpell
private struct TheStruct
    //stuff in the struct
endstruct

globals
    private TheStruct array darr
    private integer max
    private timer T = CreateTimer()
endglobals

private function Loop takes nothing returns nothing
    local integer i = 0
    local TheStruct dat
    loop
        exitwhen i == max
        set dat = darr[i]
        //do spell stuff
        if <YOU WANT TO DEALLOCATE> then
            set max = max - 1
            set darr[i] = darr[max]
            if max == 0 then
                call PauseTimer(T)
            endif
        else
            set i = i + 1
        endif
        //More spell stuff
    endloop
endfunction

private function Actions takes nothing returns nothing
    local TheStruct dat = TheStruct.create()
    //initialize the struct... set the values to what you need
    set darr[max] = dat
    if max == 0 then
        call TimerStart(T,<interval>,true,function Loop)
    endif
    set max = max + 1
endfunction
endscope

All you really need to do is fill in the comments.
 
Level 12
Joined
Feb 23, 2007
Messages
1,030
I rewrote this whole damn spell twice and it still never worked -_-

I've seen lots of spells that use structs and lightning and they work perfectly fine. Why wouldn't mine?

I somewhat understand what you posted. It's like a really generic spell template. Please don't tell me that thing is MUI because it changes the array number every time it is cast...

Also, scope doesn't seem to work for me. It still keeps giving me messages of I have other functions with the same name.

*EDIT* NM i got scope working.. I guess everything must be a private function inside it.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
I've seen lots of spells that use structs and lightning and they work perfectly fine. Why wouldn't mine?
You aren't using structs.

I somewhat understand what you posted. It's like a really generic spell template. Please don't tell me that thing is MUI because it changes the array number every time it is cast...
Yes, it's MUI. Read it again.
 
Level 12
Joined
Feb 23, 2007
Messages
1,030
JASS:
scope Enslave
private constant function Zombie1 takes nothing returns integer
    return 'n003'
endfunction

private constant function Zombie2 takes nothing returns integer
    return 'n004'
endfunction

private constant function Zombie3 takes nothing returns integer
    return 'n005'
endfunction

private constant function Zombie4 takes nothing returns integer
    return 'n006'
endfunction

private constant function Zombie5 takes nothing returns integer
    return 'n007'
endfunction

private function Spell takes nothing returns boolean
    return GetSpellAbilityId() == 'A01W'
endfunction

private function Timer takes nothing returns nothing
local timer t = GetExpiredTimer()
local unit u = GetHandleUnit(t,"targ")
local integer p = GetHandleInt(t,"prev")
local integer lvl = GetHandleInt(t,"lvl")
local integer c = GetHandleInt(t,"c")+1
local lightning l = GetHandleLightning(t,"l")
local real x1 = GetHandleReal(t,"x")
local real y1 = GetHandleReal(t,"y")
local real x2 = GetUnitX(u)
local real y2 = GetUnitY(u)
call SetHandleInt(t,"c",c)

if SquareRoot((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))>1000 then
    call SetUnitX(u,x1)
    call SetUnitY(u,y1)
    call MoveLightning(l, true, x1, y1, x1, y1)
else
    call MoveLightning(l, true, x1, y1, x2, y2)
endif

if GetUnitState(u, UNIT_STATE_LIFE)<.4 then
    if lvl == 1 then
        call CreateUnit(GetOwningPlayer(u),Zombie1(),x2,y2,270)
    elseif lvl == 2 then
        call CreateUnit(GetOwningPlayer(u),Zombie2(),x2,y2,270)
    elseif lvl == 3 then
        call CreateUnit(GetOwningPlayer(u),Zombie3(),x2,y2,270)
    elseif lvl == 4 then
        call CreateUnit(GetOwningPlayer(u),Zombie4(),x2,y2,270)
    elseif lvl == 5 then
        call CreateUnit(GetOwningPlayer(u),Zombie5(),x2,y2,270)
    endif

    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Undead\\AnimateDead\\AnimateDeadTarget.mdl" ,x2,y2))
    call DestroyLightning(l)
    call FlushHandleLocals(t)
    call PauseTimer(t)
    call DestroyTimer(t)
endif

if c>375 then
    call DestroyLightning(l)
    call SetUnitOwner(u, Player(p), true)
    call FlushHandleLocals(t)
    call PauseTimer(t)
    call DestroyTimer(t)
endif

set t = null
set u = null
set l = null
endfunction

private function Actions takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit t = GetSpellTargetUnit()
local real x = GetUnitX(t)
local real y = GetUnitY(t)
local integer lvl = GetUnitAbilityLevel(u,'A01W')
local timer q = CreateTimer()
local lightning l = AddLightning("LEAS",true,x,y,x,y)

call SetHandleReal(q,"x",GetUnitX(t))
call SetHandleReal(q,"y",GetUnitY(t))
call SetHandleInt(q,"lvl",lvl)
call SetHandleHandle(q,"targ",t)
call SetHandleHandle(q,"l",l)
call SetHandleInt(q,"prev",GetPlayerId(GetOwningPlayer(t)))
call SetUnitOwner(t, GetOwningPlayer(u), true)
call TimerStart(q,0.04,true, function Timer)

set u = null
set t = null
set q = null
endfunction

//===========================================================================
function InitTrig_Enslave takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Spell))
    call TriggerAddAction(t, function Actions)
    set t = null
endfunction
endscope

Very strange I got this ability to work perfectly and not the other one... BTW what did you mean by DEALLOCATE?
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Very strange I got this ability to work perfectly and not the other one... BTW what did you mean by DEALLOCATE?
Regardless, lightnings and handles don't go well together. It's a well-known fact. It's not that they don't work, it's that they bug up a lot, even in the simplest of scenarios, in which debugging is easy.

Deallocate = Un-allocate = the opposite of allocation = not sure what else to say here.
 
Level 21
Joined
Aug 21, 2005
Messages
3,699
Perhaps he also needs to know what allocating means :p

So basically allocating means reserving part of your RAM memory for a variable. Allocating a struct would mean you reserve new memoryspace for your struct.

Since de-allocating is doing the opposite, you could free up memory space of an unused variable, allowing other variables to be allocated there.

If that makes any more sense.
 
Status
Not open for further replies.
Top