HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

I have a problem with this JASS script:

12-30-2007, 01:34 PM#1
redscores
It is supposed to create a chain lightning which arcs 4 times between enemys and set them on fire for 10 seconds, deals 25 damage per second. But it arcs not. I am fairly new at such complicated JASS spells.

-Single Target.
-Non Channeled.
-Damage Over Time.
-4 times Bouncing

Collapse JASS:
scope FireChain

globals 
    constant integer FRCH_AbillID = 'A000'
    constant string FRCH_lightningModel = "AFOD" // The model path of the lightning
    real FRCH_damageUnCalculated = 25 // The Damage done, gets multiplied with the level
    integer FRCH_BurnDur = 10 // Duration of the Burn
endglobals


function Trig_Fire_Chain_Conditions takes nothing returns boolean
    if ( GetSpellAbilityId() == FRCH_AbillID ) then
        return true
    endif
    return false
endfunction

function Chain takes real X1, real Y1, real X2, real Y2 returns lightning
     local lightning lightning1 = AddLightning(FRCH_lightningModel, true, X1, Y1, X2, Y2)
     return lightning1
endfunction

function ChainDamage takes unit target, unit caster returns nothing
     local effect FireBurn = AddSpecialEffectTarget("Abilities\\Spells\\Other\\ImmolationRed\\ImmolationRedDamage", target, "chest")
     local integer FireInteger = 1
     loop
         exitwhen FireInteger >= FRCH_BurnDur
         call UnitDamageTarget (caster, target, FRCH_damageUnCalculated*GetUnitAbilityLevel(caster, FRCH_AbillID), false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
         set FireInteger = FireInteger + 1
         call PolledWait(1.00)
     endloop
     call DestroyEffect(FireBurn)
     return
endfunction

function KeepOrNoKeep takes unit target2, player Cowner returns boolean
     if ( IsUnitType(target2, UNIT_TYPE_STRUCTURE) == false ) and ( IsUnitType(target2, UNIT_TYPE_MAGIC_IMMUNE) == false ) and ( IsUnitAliveBJ(target2) == true ) and ( IsUnitEnemy(target2, Cowner) == true ) and target2 != null then
         return true
     endif
     return false
endfunction

function Trig_Fire_Chain_Actions takes nothing returns nothing
    local unit caster = GetSpellAbilityUnit()
    local unit target = GetSpellTargetUnit()
    local unit target2
    local real X1 = GetUnitX(caster)
    local real Y1 = GetUnitY(caster)
    local real X2 = GetUnitX(target)
    local real Y2 = GetUnitY(target)
    local lightning lightningFC = Chain(X1, Y1, X2, Y2)
    local player Cowner = GetOwningPlayer(caster)
    local integer arcs = 3 //number of arcs after the first jump
    local location locationFC = Location(X2,Y2)
    local group DamagedUnits
    call ChainDamage(target, caster)
    call PolledWait(0.25)
    call DestroyLightning(lightningFC)
    set DamagedUnits = GetUnitsInRangeOfLocAll(400, locationFC)
    call RemoveLocation(locationFC)
    set arcs = arcs - 1
    set X1 = GetUnitX(target)
    set Y1 = GetUnitY(target)
    set X2 = GetUnitX(target2)
    set Y2 = GetUnitY(target2)
    set locationFC = Location(X2,Y2)
    set target2 = GroupPickRandomUnit(DamagedUnits)
    if KeepOrNoKeep(target2, Cowner) == false then
        call RemoveLocation(locationFC)
        call GroupClear(DamagedUnits)
        set caster = null
        set target = null
        set target2 = null
        call DestroyGroup(DamagedUnits)
    endif
    call ChainDamage(target2, caster)
    set lightningFC = Chain(X1, Y1, X2, Y2)
    call PolledWait(0.25)
    call DestroyLightning(lightningFC)
    call RemoveLocation(locationFC)
    set DamagedUnits = GetUnitsInRangeOfLocAll(400, locationFC)
    loop 
        exitwhen arcs == 0
        set target = target2
        set target2 = null
        set X1 = GetUnitX(target)
        set Y1 = GetUnitY(target)
        set X2 = GetUnitX(target2)
        set Y2 = GetUnitY(target2)
        set locationFC = Location(X2,Y2)
        set target2 = GroupPickRandomUnit(DamagedUnits)
        if KeepOrNoKeep(target2, Cowner) == false then
            call RemoveLocation(locationFC)
            call GroupClear(DamagedUnits)
            set caster = null
            set target = null
            set target2 = null
            call DestroyGroup(DamagedUnits)
        endif
        call ChainDamage(target2, caster)
        set lightningFC = Chain(X1, Y1, X2, Y2)
        set arcs = arcs - 1
        call GroupClear(DamagedUnits)
        call PolledWait(0.25)
        
        call RemoveLocation(locationFC)
        call DestroyLightning(lightningFC)
    endloop
    call RemoveLocation(locationFC)
    call GroupClear(DamagedUnits)
    set caster = null
    set target = null
    set target2 = null
    call DestroyGroup(DamagedUnits)
    
endfunction

//===========================================================================
function InitTrig_FireChain takes nothing returns nothing
    set gg_trg_FireChain = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_FireChain, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_FireChain, Condition( function Trig_Fire_Chain_Conditions ) )
    call TriggerAddAction( gg_trg_FireChain, function Trig_Fire_Chain_Actions )
endfunction

endscope
12-30-2007, 04:34 PM#2
TaintedReality
Waits inside of loops often don't work. Use a timer instead. Although, a much better way to create this spell would be this:

Make a dummy spell that does nothing (as you probably have now). When the spell is cast, create a dummy unit that casts a 4-bounce chain lightning that deals 0.01 damage. Then, detect when units are damaged by the dummy, and when they are, set them on fire/do damage over time.

No need to make your own chain function when a much cleaner and more practical method already exists within War3.
12-30-2007, 04:48 PM#3
redscores
This spell is not created to make something useful, it is for me, so i can learn to make jass spells, but i need help a bit, i want it without dummys etc.
12-30-2007, 04:55 PM#4
TaintedReality
Quote:
Originally Posted by TaintedReality
Waits inside of loops often don't work. Use a timer instead.

Self-quoting = win!

But anyways, if you do want to code the whole chain lightning, you'll need to have a timer that controls when the lightning "jumps" to the next target. Waits in loops never seem to work, and when they do they're inaccurate.
12-30-2007, 05:05 PM#5
redscores
yeah i will try, but thats not the real problem, the damage is done, but the lightning arcs not, like written, the loop ChainDamage is just for the set on fire and damage, but i was speaking about the arc of the lightning, the jump. And for the big jump loop i cannot figure out a timer function, sorry.
12-30-2007, 06:00 PM#6
TaintedReality
The "big loop" controlling the jumps is what I was talking about too. Not sure what to tell you with the timer function, just attach all the info you need to a timer and have it run 4 times. Maybe someone will give you an example or outline or something.
12-30-2007, 06:05 PM#7
redscores
a outline would be cool. thanks hopeful in advance.^^

Here i tried to fix the damage/burn with a timer, kaTTanas handle vars are used:

Collapse JASS:
scope FireChain

globals 
    constant integer FRCH_AbillID = 'A000'
    constant string FRCH_lightningModel = "AFOD" // The model path of the lightning
    real FRCH_damageUnCalculated = 25 // The Damage done, gets multiplied with the level
    integer FRCH_BurnDur = 10 // Duration of the Burn
endglobals


function Trig_Fire_Chain_Conditions takes nothing returns boolean
    if ( GetSpellAbilityId() == FRCH_AbillID ) then
        return true
    endif
    return false
endfunction

function Chain takes real X1, real Y1, real X2, real Y2 returns nothing
     local lightning lightning1 = AddLightning(FRCH_lightningModel, true, X1, Y1, X2, Y2)
     call PolledWait(0.50)
     call DestroyLightning(lightning1)
endfunction

function DamageUnitFire takes nothing returns nothing
     local unit target
     local unit caster
     call GetHandleUnit(target, "target")
     call GetHandleUnit(caster, "caster")
     call UnitDamageTarget (caster, target, FRCH_damageUnCalculated*GetUnitAbilityLevel(caster, FRCH_AbillID), false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
     set target = null
     set caster = null
endfunction

function ChainDamage takes unit target, unit caster returns nothing
     local effect FireBurn = AddSpecialEffectTarget("Abilities\\Spells\\Other\\ImmolationRed\\ImmolationRedDamage", target, "head")
     local timer FireDamage = CreateTimer()
     
     call TimerStart(FireDamage, 1.00, true, function DamageUnitFire )
     call PolledWait(10.00)
     call DestroyTimer(FireDamage)
     call DestroyEffect(FireBurn)
     return
endfunction

function KeepOrNoKeep takes unit target2, player Cowner returns boolean
     if ( IsUnitType(target2, UNIT_TYPE_STRUCTURE) == false ) and ( IsUnitType(target2, UNIT_TYPE_MAGIC_IMMUNE) == false ) and ( IsUnitAliveBJ(target2) == true ) and ( IsUnitEnemy(target2, Cowner) == true ) and target2 != null then
         return true
     endif
     return false
endfunction

function Trig_Fire_Chain_Actions takes nothing returns nothing
    local unit caster
    local unit target
    local unit target2
    local real X1
    local real Y1
    local real X2
    local real Y2
    local player Cowner = GetOwningPlayer(caster)
    local integer arcs = 3 //number of arcs after the first jump
    local location locationFC
    local group DamagedUnits
    
    
    call SetHandleHandle(GetSpellTargetUnit(), "target", null)
    call SetHandleHandle(GetSpellAbilityUnit(), "caster", null)
    set caster = GetHandleUnit(caster, "caster")
    set target = GetHandleUnit(target, "target")
    set X1 = GetUnitX(caster)
    set Y1 = GetUnitY(caster)
    set X2 = GetUnitX(target)
    set Y2 = GetUnitY(target)
    set locationFC = Location(X2,Y2)
    call Chain(X1, Y1, X2, Y2)
    call ChainDamage(target, caster)
    call PolledWait(0.25)
    call RemoveLocation(locationFC)
    call GroupClear(DamagedUnits)
    set caster = null
    set target = null
    set target2 = null
    call DestroyGroup(DamagedUnits)
    call PolledWait(10.00)
    call FlushHandleLocals(target)
    call FlushHandleLocals(caster)
    
endfunction

//===========================================================================
function InitTrig_FireChain takes nothing returns nothing
    set gg_trg_FireChain = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_FireChain, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_FireChain, Condition( function Trig_Fire_Chain_Conditions ) )
    call TriggerAddAction( gg_trg_FireChain, function Trig_Fire_Chain_Actions )
endfunction

endscope


The Loop for the jumps is cut out. I will add him later. Any ideas why it won't work?