• 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] Fireball Spell

Status
Not open for further replies.
Level 4
Joined
Jul 14, 2007
Messages
59
I'm very new to JASS and I'm trying to create a classical fireball spell: A ball moves forward, and explodes when it hits the first unit in range. However, the ball simply moves forward, and detonates at the end of the path, even if there was an enemy in its way.

I'm sure there is a more efficient way to do this spell, but the only way I know how is this: Make a dummy, move it forward, each time it moves, check how many enemies are in 100 range, if there is at least 1 enemy unit, then explode.

Also, I'm not sure what memory leaks need to be fixed, but that is less important than the actual spell.

JASS:
function Trig_Fireball_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A001'
endfunction

function Fireball_CopyGroup takes group g returns group
    set bj_groupAddGroupDest = CreateGroup()
    call ForGroup(g, function GroupAddGroupEnum)
    return bj_groupAddGroupDest
endfunction

function Fireball_Filter takes nothing returns boolean
    return IsPlayerEnemy(GetOwningPlayer(GetHandleUnit(GetExpiredTimer(), "caster")), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)
endfunction

function FireballMove takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local real damage = 100.0
    local group g = CreateGroup()
    local group n
    local boolexpr b = Condition(function Fireball_Filter)
    local unit caster = GetHandleUnit(t, "caster")
    local unit dummy = GetHandleUnit(t, "dummy")
    local unit f
    local integer steps = GetHandleInt(t, "steps")
    local integer i = 0
    local real angle = GetHandleReal(t, "angle")
    local real cx = GetHandleReal(t, "cx")
    local real cy = GetHandleReal(t, "cy")
    local real x = cx + 15.0 * I2R(steps) * Cos(angle)
    local real y = cy + 15.0 * I2R(steps) * Sin(angle)
    //call UnitDamageTarget(caster, target, damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
    call SetUnitX(dummy, x)
    call SetUnitY(dummy, y)
    call GroupEnumUnitsInRange(g, x, y, 100, b)
    loop
        set f = FirstOfGroup(g)
        exitwhen f == null
        set i = i + 1
        call GroupRemoveUnit(g, f)
    endloop
    if ( i >= 1 ) then
        set i = 0
        call GroupEnumUnitsInRange(g, x, y, 250, b)
        set n = Fireball_CopyGroup(g)
        loop
            set f = FirstOfGroup(n)
            exitwhen f == null
            call UnitDamageTarget(caster, f, damage, true, false, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_MAGIC, null)
            call GroupRemoveUnit(n, f)
        endloop
        call KillUnit(dummy)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        return
    elseif ( steps >= 81 ) then
        call KillUnit(dummy)
        call FlushHandleLocals(t)
        call DestroyTimer(t)
        return
    endif
    call SetHandleInt(t, "steps", steps+1)
endfunction

function Trig_Fireball_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    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 unit dummy = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 'h001', cx, cy, angle)
    local timer t = CreateTimer()
    call SetHandleInt(t, "steps", 0)
    call SetHandleReal(t, "angle", angle)
    call SetHandleReal(t, "cx", cx)
    call SetHandleReal(t, "cy", cy)
    call SetHandleHandle(t, "caster", caster)
    call SetHandleHandle(t, "dummy", dummy)
    call TimerStart(t, .025, true, function FireballMove)
endfunction

//===========================================================================
function InitTrig_Fireball takes nothing returns nothing
    set gg_trg_Fireball = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Fireball, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Fireball, Condition( function Trig_Fireball_Conditions ) )
    call TriggerAddAction( gg_trg_Fireball, function Trig_Fireball_Actions )
endfunction
 
Level 4
Joined
Jul 14, 2007
Messages
59
Well, part of the problem is that I don't know how to fix all the leaks, also, it makes the code easier to understand.

After a bit of testing, I found out that the group g never gets a FirstUnit, so the filter is probably messed up. But I don't see anything wrong with that either.

Edit: Is there another way to make this spell? This code is just so long for such a simple effect.
 
Level 16
Joined
Mar 3, 2006
Messages
1,564
Edit: Is there another way to make this spell? This code is just so long for such a simple effect.

There is a similarity between this spell and the spell I requested, the difference is that my Fireball will explode at the target point not when it find an enemy in its way. However, if you wish, try the topic Exploding Fireball Spell, you will find a map by Ciebron attached there its written in vJASS so don't touch anything unless you have the JASS NewGenPack.
 
Status
Not open for further replies.
Top