• 🏆 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] Banefire Spell

Status
Not open for further replies.
Level 4
Joined
Jul 14, 2007
Messages
59
I'm trying to get this spell to work, the only problem is that the dummy unit won't fire the spell. I think it has something to do with call IssuePointOrderById(dummy, S2I("shockwave"), tx, ty), because that's the only part the debug hasn't worked on.

The spell is supposed to shoot shockwaves repeatedly at target point.

Also, exactly where should I fix leaks? I'm not very experienced with JASS, and I don't want my map to lag.

JASS:
function Trig_Banefire_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A004'
endfunction

function BanefireExpire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer level = GetHandleInt(t, "level")
    local unit caster = GetHandleUnit(t, "caster")
    local integer steps = GetHandleInt(t, "steps")
    local real angle = GetHandleReal(t, "angle")
    local real cx = GetHandleReal(t, "cx")
    local real cy = GetHandleReal(t, "cy")
    local real tx = GetHandleReal(t, "tx")
    local real ty = GetHandleReal(t, "ty")
    local unit dummy = CreateUnit(GetOwningPlayer(caster), 'h000', cx, cy, angle)
    call UnitAddAbilityBJ('A005', dummy)
    call SetUnitAbilityLevelSwapped('A005', dummy, level)
    call UnitApplyTimedLifeBJ(2.00, 'BTLF', dummy)
    call IssuePointOrderById(dummy, S2I("shockwave"), tx, ty)
    if ( steps <= 1 ) then
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        return
    endif
    call SetHandleInt(t, "steps", steps-1)
endfunction

function Trig_Banefire_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local integer level = GetUnitAbilityLevelSwapped('A004', caster)
    local real cx = GetUnitX(caster)
    local real cy = GetUnitY(caster)
    local real tx = GetLocationX(GetSpellTargetLoc())
    local real ty = GetLocationY(GetSpellTargetLoc())
    local real angle = Atan2(ty - GetUnitY(caster), tx - GetUnitX(caster))
    local timer t = CreateTimer()
    call SetHandleInt(t, "level", level)
    call SetHandleInt(t, "steps", 20)
    call SetHandleReal(t, "angle", angle)
    call SetHandleReal(t, "cx", cx)
    call SetHandleReal(t, "cy", cy)
    call SetHandleReal(t, "tx", tx)
    call SetHandleReal(t, "ty", ty)
    call SetHandleHandle(t, "caster", caster)
    call TimerStart(t, .2, true, function BanefireExpire)
    set caster = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Banefire takes nothing returns nothing
    set gg_trg_Banefire = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Banefire, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Banefire, Condition( function Trig_Banefire_Conditions ) )
    call TriggerAddAction( gg_trg_Banefire, function Trig_Banefire_Actions )
endfunction
 
Level 7
Joined
Oct 14, 2008
Messages
340
Make sure your shockwave based spell is not a hero ability, has no techtree requirements, has 99999999 cast range, and 0 mana cost. I don't see a lot wrong here it should work, but you do use a few unnecessary BJ's in the BaneFireExpire function
 
Level 14
Joined
Nov 23, 2008
Messages
187
The problem is here:
JASS:
call IssuePointOrderById(dummy, S2I("shockwave"), tx, ty)

S2I("shockwave") would convert numeric string to integer. But "shockwave" string contains no numeric symbols, so the result would be 0. 0 is equal to no order.

To convert order string to order id, you should use OrderId function:
JASS:
call IssuePointOrderById(dummy, OrderId("shockwave"), tx, ty)

Also, you can use ConvOrder tool (by Blade.dk) to get order id from order string and vice versa, e.g., "shockwave" order id is 852125, so you can write:
JASS:
call IssuePointOrderById(dummy, 852125, tx, ty)

>> EDIT <<

About the code...

1. GetSpellTargetLoc() returns the location, which have to be deleted after use.

JASS:
function Trig_Banefire_Actions takes nothing returns nothing
    // . . .
    local location loc = GetSpellTargetLoc()
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    // . . .
    call RemoveLocation(loc)
    set loc = null
endfunction

2. Most of handle variables have to be nullified (for preventing leakage).
3. There's no need to allocate local variable, if its value is used only once.

JASS:
function BanefireExpire takes nothing returns nothing
    local timer   t     = GetExpiredTimer()
    local integer steps = GetHandleInt(t, "steps")
    local unit    dummy = CreateUnit(GetOwningPlayer(GetHandleUnit(t, "caster")), 'h000', GetHandleReal(t, "cx"), GetHandleReal(t, "cy"), GetHandleReal(t, "angle"))

    call UnitAddAbility     (dummy, 'A005')
    call SetUnitAbilityLevel(dummy, 'A005', GetHandleInt(t, "level"))
    call UnitApplyTimedLife (dummy, 'BTLF', 2.)
    call IssuePointOrderById(dummy, 852125, GetHandleReal(t, "tx"), GetHandleReal(t, "ty"))
    set dummy = null

    call SetHandleInt(t, "steps", steps - 1)
    if steps <= 1 then
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    endif
    set t = null
endfunction

function Trig_Banefire_Actions takes nothing returns nothing
    local unit caster  = GetTriggerUnit()
    local location loc = GetSpellTargetLoc()
    local real cx = GetUnitX(caster)
    local real cy = GetUnitY(caster)
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    local timer t = CreateTimer()

    call SetHandleInt   (t, "level", GetUnitAbilityLevel(caster, 'A004'))
    call SetHandleInt   (t, "steps", 20)
    call SetHandleReal  (t, "angle", Atan2(ty - cy, tx - cx))
    call SetHandleReal  (t, "cx", cx)
    call SetHandleReal  (t, "cy", cy)
    call SetHandleReal  (t, "tx", tx)
    call SetHandleReal  (t, "ty", ty)
    call SetHandleHandle(t, "caster", caster)
    call TimerStart     (t, .2, true, function BanefireExpire)

    call RemoveLocation(loc)
    set loc    = null
    set caster = null
    set t      = null
endfunction
 
Level 4
Joined
Jul 14, 2007
Messages
59
Still the same thing; the dummy gets the ability and the level is set, but it just won't cast it.

New code: (are there any leaks in this?)

JASS:
function Trig_Banefire_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A004'
endfunction

function BanefireExpire takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer steps = GetHandleInt(t, "steps")
    local unit dummy = CreateUnit(GetOwningPlayer(GetHandleUnit(t, "caster")), 'h000', GetHandleReal(t, "cx"), GetHandleReal(t, "cy"), GetHandleReal(t, "angle"))
    call UnitAddAbility (dummy, 'A005')
    call SetUnitAbilityLevel(dummy, 'A005', GetHandleInt(t, "level"))
    call UnitApplyTimedLife (dummy, 'BTLF', 2.)
    call IssuePointOrderById(dummy, 852125, GetHandleReal(t, "tx"), GetHandleReal(t, "ty"))
    set dummy = null
    call SetHandleInt(t, "steps", steps - 1)
    if steps <= 1 then
        call FlushHandleLocals(t)
        call DestroyTimer(t)
    endif
    set t = null
endfunction

function Trig_Banefire_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local location loc = GetSpellTargetLoc()
    local real cx = GetUnitX(caster)
    local real cy = GetUnitY(caster)
    local real tx = GetLocationX(loc)
    local real ty = GetLocationY(loc)
    local timer t = CreateTimer()

    call SetHandleInt (t, "level", GetUnitAbilityLevel(caster, 'A004'))
    call SetHandleInt (t, "steps", 20)
    call SetHandleReal (t, "angle", Atan2(ty - cy, tx - cx))
    call SetHandleReal (t, "cx", cx)
    call SetHandleReal (t, "cy", cy)
    call SetHandleReal (t, "tx", tx)
    call SetHandleReal (t, "ty", ty)
    call SetHandleHandle(t, "caster", caster)
    call TimerStart (t, .2, true, function BanefireExpire)
    call RemoveLocation(loc)
    set loc = null
    set caster = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Banefire takes nothing returns nothing
    set gg_trg_Banefire = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Banefire, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Banefire, Condition( function Trig_Banefire_Conditions ) )
    call TriggerAddAction( gg_trg_Banefire, function Trig_Banefire_Actions )
endfunction
 
Level 14
Joined
Nov 23, 2008
Messages
187
Make sure your ability fits the following:
Make sure your shockwave based spell:
1. Is not a hero ability;
2. Has no techtree requirements;
3. Has 99999 cast range;
4. Has 0 mana cost.
5. Has 0 cooldown.
6. Has some visual effect (maybe, you just don't see it).
7. Really based on a shockwave (lol).

And your dummy unit configured properly:
1. Health and mana = 99999.
2. Movement speed = 522.
3. Turn rate = 1.
4. Has a locust ('Aloc') ability.

Code is ok.
 
Status
Not open for further replies.
Top