• 🏆 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!

[JASS] Hydra Lightning BUGS.

Status
Not open for further replies.
Level 21
Joined
Aug 9, 2006
Messages
2,384
This Spell works completely right, beside sometimes one of the lightnings is moved to the middle of the map or something.

JASS:
scope HydraLightning initializer Init

private struct Data
    unit caster
    unit target
    player owner
    group forked
    real x
    real y
    real x1
    real y1
    real array xa[3]
    real array ya[3]
    unit array targets[3]
    lightning array forkedlightnings[6]
    effect array lightningeffect[5]
    real dur = 0.00
    integer numberof
    integer calc
    timer time
    method onDestroy takes nothing returns nothing
            call ReleaseTimer(.time)
    endmethod
endstruct

globals
    private integer SPELL_ID = 'A008'
endglobals

private function HydraLightningCond takes nothing returns boolean
    return GetSpellAbilityId() == SPELL_ID
endfunction

private constant function Damage takes nothing returns real
    return 75.00
endfunction

private constant function BaseAgiRed takes nothing returns integer
    return 2
endfunction

private function PreLoad takes nothing returns nothing
    call Preload("Abilities\\Weapons\\Bolt\\BoltImpact.mdl")
    call Preload("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl")
endfunction

private function HydraLightningLoop takes nothing returns nothing
    local Data kd = GetCSData(GetExpiredTimer())
    local integer i = 0
    local integer count2 = 0

    if (kd.dur <= 1.00) then
        if (GetWidgetLife(kd.caster) > 0.405 and kd.caster != null) then
            set kd.x = GetUnitX(kd.caster)
            set kd.y = GetUnitY(kd.caster)
        endif
        if (GetWidgetLife(kd.target) > 0.405 and kd.target != null) then
            set kd.x1 = GetUnitX(kd.target)
            set kd.y1 = GetUnitY(kd.target)
        endif
        call MoveLightningEx(kd.forkedlightnings[5], true, kd.x, kd.y, 125, kd.x1, kd.y1, 75)
        loop
            exitwhen count2 == kd.numberof
            if (GetWidgetLife(kd.targets[count2]) > 0.405 and kd.targets[count2] != null) then
                set kd.xa[count2] = GetUnitX(kd.targets[count2])
                set kd.ya[count2] = GetUnitY(kd.targets[count2])
            endif
            call MoveLightningEx(kd.forkedlightnings[count2], true, kd.x1, kd.y1, 125, kd.xa[count2], kd.ya[count2], 75)
            set count2 = count2 + 1
        endloop
    else
        set count2 = 0
        call DestroyLightning(kd.forkedlightnings[5])
        set kd.forkedlightnings[5] = null
           loop
            exitwhen count2 == (kd.numberof + 1)
            call DestroyLightning(kd.forkedlightnings[count2])
            set kd.forkedlightnings[count2] = null
            set count2 = count2 + 1
        endloop
        if (kd.dur >= 10.00) then
            set count2 = 0
            if IsUnitType(kd.target, UNIT_TYPE_HERO) == true then
                call DestroyEffect(kd.lightningeffect[4])
                call SetHeroAgi(kd.target, GetHeroAgi(kd.target, true) + kd.calc, false)
            endif
            loop
                exitwhen count2 == kd.numberof
                if IsUnitType(kd.targets[count2], UNIT_TYPE_HERO) == true then
                    call SetHeroAgi(kd.targets[count2], GetHeroAgi(kd.targets[count2], true) + kd.calc, false)
                    call DestroyEffect(kd.lightningeffect[count2])
                endif
                set count2 = count2 + 1
            endloop
            set kd.target = null
            set kd.owner = null
            set kd.targets[0] = null
            set kd.targets[1] = null
            set kd.targets[2] = null
            set kd.caster = null
            call kd.destroy()
        endif
            
    endif
    set kd.dur = kd.dur + 0.03
endfunction

function HydraLightning takes nothing returns nothing
    local Data kd = Data.create()
    local integer count = 0
    local boolexpr D = null
    set kd.time = NewTimer()
    set kd.caster = GetTriggerUnit()
    set kd.owner = GetOwningPlayer(kd.caster)
    set kd.target = GetSpellTargetUnit()
    set kd.calc = BaseAgiRed()+BaseAgiRed()*GetUnitAbilityLevel(kd.caster, SPELL_ID)
    if IsUnitType(kd.target, UNIT_TYPE_HERO) == true then
        call SetHeroAgi(kd.target, GetHeroAgi(kd.target, true) - kd.calc, false)
        set kd.lightningeffect[4] = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl", kd.target, "origin" )
    endif
    set kd.x = GetUnitX(kd.caster)
    set kd.y = GetUnitY(kd.caster)
    set kd.x1 = GetUnitX(kd.target)
    set kd.y1 = GetUnitY(kd.target)
    call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\Bolt\\BoltImpact.mdl", kd.x1, kd.y1))
    call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", kd.x1, kd.y1))
    
    set kd.forkedlightnings[5] = AddLightningEx("DL", true, kd.x, kd.y, 125, kd.x1, kd.y1, 75)
    call UnitDamageTarget(kd.caster, kd.target, Damage()+(Damage()*GetUnitAbilityLevel(kd.caster, SPELL_ID)) , false, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
    set kd.forked = CreateGroup()
    call GroupEnumUnitsInRange(kd.forked, kd.x1, kd.y1, 400.00, D)
    loop
        set kd.targets[count] = FirstOfGroup(kd.forked)
        exitwhen (kd.targets[count] == null or count == 3)
        call GroupRemoveUnit(kd.forked, kd.targets[count])
        if GetWidgetLife(kd.targets[count]) > 0.405 and IsUnitType(kd.targets[count], UNIT_TYPE_STRUCTURE) == false and IsUnitType(kd.targets[count], UNIT_TYPE_MAGIC_IMMUNE) == false and IsUnitType(kd.targets[count], UNIT_TYPE_MECHANICAL) == false and IsUnitAlly(kd.targets[count], kd.owner) == false and kd.targets[count] != kd.target then
            set kd.xa[count] = GetUnitX(kd.targets[count])
            set kd.ya[count] = GetUnitY(kd.targets[count])
            if IsUnitType(kd.targets[count], UNIT_TYPE_HERO) == true then
                call SetHeroAgi(kd.targets[count], GetHeroAgi(kd.targets[count], true) - kd.calc, false)
                set kd.lightningeffect[count] = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\Purge\\PurgeBuffTarget.mdl", kd.targets[count], "origin" )
            endif
            call UnitDamageTarget(kd.caster, kd.targets[count], Damage()+(Damage()*GetUnitAbilityLevel(kd.caster, SPELL_ID)) , false, true, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS)
            call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\Bolt\\BoltImpact.mdl", kd.xa[count], kd.ya[count]))
            call DestroyEffect(AddSpecialEffect("Abilities\\Weapons\\FarseerMissile\\FarseerMissile.mdl", kd.xa[count], kd.ya[count]))
            
            set kd.forkedlightnings[count] = AddLightningEx("DL", true, kd.x1, kd.y1, 50, kd.xa[count], kd.ya[count], 50)
            set count = count + 1
            set kd.numberof = kd.numberof + 1
        endif
    endloop
    call DestroyGroup(kd.forked)
    
    call SetCSData(kd.time,kd)
    call TimerStart(kd.time, 0.03, true, function HydraLightningLoop)

endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local integer index = 0
    local trigger t = CreateTrigger()
    
    loop
        call TriggerRegisterPlayerUnitEvent(t, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    
    call TriggerAddCondition(t, Condition( function HydraLightningCond ) )
    call TriggerAddAction(t, function HydraLightning )
    
    call PreLoad()
endfunction

endscope
 
Last edited:
Level 12
Joined
Apr 27, 2008
Messages
1,228
set kd.xa[count2] = GetUnitX(kd.targets[count2])
set kd.ya[count2] = GetUnitY(kd.targets[count2])
Before you store those, check if target's life is more than 0.405 (is alive).
Do the same, anywhere you get an unit's x/y.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
Now it is buggy( I guess you know that already) - I see no lightnings appear(may be my fault).
But this:
JASS:
if (GetWidgetLife(kd.targets[count2]) > 0.405 and kd.targets[count2] != null) then
    set kd.xa[count2] = GetUnitX(kd.targets[count2])
    set kd.ya[count2] = GetUnitY(kd.targets[count2])
endif
call MoveLightningEx(kd.forkedlightnings[count2], true
Should look like this:
JASS:
if (GetWidgetLife(kd.targets[count2]) > 0.405 and kd.targets[count2] != null) then
    set kd.xa[count2] = GetUnitX(kd.targets[count2])
    set kd.ya[count2] = GetUnitY(kd.targets[count2])
    call MoveLightningEx(kd.forkedlightnings[count2], true)
else
    call DestroyLightning(kd.forkedlightnings[count2])
    set kd.forkedlightnings[count2]=null//you can do this either here on in the on destroy method(better in the method and not here
endif
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
JASS:
if (GetWidgetLife(kd.target) > 0.405 and kd.target != null) then
    set kd.x1 = GetUnitX(kd.target)
    set kd.y1 = GetUnitY(kd.target)
    call MoveLightningEx(kd.forkedlightnings[5], true, kd.x, kd.y, 125, kd.x1, kd.y1, 75)
    loop
        exitwhen count2 == kd.numberof
        if (GetWidgetLife(kd.targets[count2]) > 0.405 and kd.targets[count2] != null) then
            set kd.xa[count2] = GetUnitX(kd.targets[count2])
            set kd.ya[count2] = GetUnitY(kd.targets[count2])
            call MoveLightningEx(kd.forkedlightnings[count2], true, kd.x1, kd.y1, 125, kd.xa[count2], kd.ya[count2], 75)
        else
            call DestroyLightning(kd.forkedlightnings[count2])//here
            set kd.forkedlightnings[count2]=null//you can do this either here on in the on destroy method(better in the method and not here
        endif
        set count2 = count2 + 1
    endloop
else
    //here too
endif
This way no lightings from the center appeared(it is what I suggested in all my posts above ;) )
But when the unit on one end of the lightning, is dead(that is in either of the else-s) you have to do something with the lightings - depending whether it was the target of the ability or not, destroy one or all lightnings.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
JASS:
private function HydraLightningLoop takes nothing returns nothing
    local Data kd = GetAttachedStruct1(GetExpiredTimer())
    local integer i = 0
    local integer count2 = 0

    if (kd.dur <= 1.00) then
        if (GetWidgetLife(kd.caster) > 0.405 and kd.caster != null) then
            set kd.x = GetUnitX(kd.caster)
            set kd.y = GetUnitY(kd.caster)
        endif
        if (GetWidgetLife(kd.target) > 0.405 and kd.target != null) then
            set kd.x1 = GetUnitX(kd.target)
            set kd.y1 = GetUnitY(kd.target)
            call MoveLightningEx(kd.forkedlightnings[5], true, kd.x, kd.y, 125, kd.x1, kd.y1, 75)
        loop
            exitwhen count2 == kd.numberof
            if (GetWidgetLife(kd.targets[count2]) > 0.405 and kd.targets[count2] != null) then
                set kd.xa[count2] = GetUnitX(kd.targets[count2])
                set kd.ya[count2] = GetUnitY(kd.targets[count2])
                call MoveLightningEx(kd.forkedlightnings[count2], true, kd.x1, kd.y1, 125, kd.xa[count2], kd.ya[count2], 75)
            else
                call DestroyLightning(kd.forkedlightnings[count2])//here
                set kd.forkedlightnings[count2]=null//you can do this either here or in the on destroy method(better in the method and not here, for efficiency make sure you destroy the lightning only once)
            endif
            set count2 = count2 + 1
        endloop
        else
            //here too
        endif
    else
        set count2 = 0
        call DestroyLightning(kd.forkedlightnings[5])
        set kd.forkedlightnings[5] = null
           loop
            exitwhen count2 == (kd.numberof + 1)
            call DestroyLightning(kd.forkedlightnings[count2])
            set kd.forkedlightnings[count2] = null
            set count2 = count2 + 1
        endloop
        if (kd.dur >= 10.00) then
            set count2 = 0
            if IsUnitType(kd.target, UNIT_TYPE_HERO) == true then
                call DestroyEffect(kd.lightningeffect[4])
                call SetHeroAgi(kd.target, GetHeroAgi(kd.target, true) + kd.calc, false)
            endif
            loop
                exitwhen count2 == kd.numberof
                if IsUnitType(kd.targets[count2], UNIT_TYPE_HERO) == true then
                    call SetHeroAgi(kd.targets[count2], GetHeroAgi(kd.targets[count2], true) + kd.calc, false)
                    call DestroyEffect(kd.lightningeffect[count2])
                endif
                set count2 = count2 + 1
            endloop
            set kd.target = null
set kd.owner = null
            set kd.targets[0] = null
            set kd.targets[1] = null
            set kd.targets[2] = null
            set kd.caster = null
            call kd.destroy()
        endif

    endif
    set kd.dur = kd.dur + 0.03
endfunction
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
No, they will appear, as they are created in the action function of the trigger(but for 0.03).
As commented in the code, do what you want in the else part of both ifs.
 
Level 12
Joined
Apr 27, 2008
Messages
1,228
You are welcome.
P.s. If you look through all my 'code' posts, you will see that I put some sort of a comment next to the 'destroys' ;)
 
Status
Not open for further replies.
Top