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

[vJASS] Group clearing unexpectedly

Status
Not open for further replies.
Level 13
Joined
Jul 26, 2008
Messages
1,009
TimerUtils
GroupUtils
xe
AutoIndex


Alright I have this spell that's suppose to link units in a group together. Those who are linked share damage, like Spirit Link except it's amplified to cause more damage.

It goes through the first firing of the timer and recognizes everything, but when it goes through the repeat of the timer it seems to have completely cleared the group.

It's odd to me, but perhaps someone else will know what's happening. This is a MultiUser spell or at least should be.

JASS:
scope Malvoodoo initializer InitTrig_Tormented_Chains

globals
    private constant integer SPELLID        = 'MaVo'
    private constant integer BUFFID         = 'BMaV'
    private constant integer DUMMYID        = 'DMaV'
    private constant real TICK              = 0.5
    private trigger array EVENT
    private real DAMAGE
endglobals

private struct Data

    unit c
    real dur
    timer tim
    static integer counted
    static unit u
    static group g

    static method Timer takes nothing returns nothing
     local thistype this = GetTimerData(GetExpiredTimer())
     local integer lvl = GetUnitAbilityLevel(.c, SPELLID)
     local unit u
     local group g = thistype.g
        set .dur = .dur + TICK
        loop
            set u = FirstOfGroup(g)
        exitwhen u == null
            if IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitAbilityLevel(u, BUFFID) < 1 then
                call DestroyTrigger(EVENT[GetUnitId(u)])
                set EVENT[GetUnitId(u)] = null
                call GroupRemoveUnit(thistype.g, u)
            endif
            call GroupRemoveUnit(g, u)
        endloop
        if .dur >= 5+1*lvl then
            loop
                set u = FirstOfGroup(thistype.g)
            exitwhen u == null
                call UnitRemoveAbility(u, BUFFID)
                call GroupRemoveUnit(thistype.g, u)
                call DestroyTrigger(EVENT[GetUnitId(u)])
                set EVENT[GetUnitId(u)] = null
            endloop

            call ReleaseGroup(thistype.g)
            call ReleaseTimer(.tim)
            call .destroy()
        endif
        call ReleaseGroup(g)
    endmethod

    static method GroupDamage takes nothing returns nothing
     local unit e = GetEnumUnit()
        if GetWidgetLife(e) > DAMAGE then
            call SetWidgetLife(e, GetWidgetLife(e) - DAMAGE)
        endif
     set e = null
    endmethod

    static method Conditions takes nothing returns boolean
     local integer lvl = GetUnitAbilityLevel(thistype.u, SPELLID)
        set DAMAGE = (lvl*0.05+0.05)*GetEventDamage()
        call ForGroup(thistype.g, function thistype.GroupDamage )
     return false
    endmethod

    static method GroupEm takes nothing returns boolean
     local xecast d = xecast.createBasicA(DUMMYID, OrderId("slow"), GetOwningPlayer(thistype.u))
     local unit f = GetFilterUnit()
        if IsUnitEnemy(f, GetOwningPlayer(thistype.u)) and not(IsUnitType(f, UNIT_TYPE_STRUCTURE)) and not( IsUnitType(f, UNIT_TYPE_DEAD )) and thistype.counted < 6 then
            call d.castOnTarget(f)
            call d.destroy()
            set EVENT[GetUnitId(f)] = CreateTrigger()
                call TriggerRegisterUnitEvent( EVENT[GetUnitId(f)], f, EVENT_UNIT_DAMAGED )
                call TriggerAddCondition( EVENT[GetUnitId(f)], function thistype.Conditions )
            set thistype.counted = thistype.counted + 1
         return true
        endif
     set f = null
     return false
    endmethod
    
    static method create takes unit c, real x, real y returns thistype
     local thistype this = thistype.allocate()
     local integer lvl = GetUnitAbilityLevel(c, SPELLID)
        set .tim = NewTimer()
        set .c = c
        set thistype.u = c
        set .dur = 0
        set thistype.g = NewGroup()
        set thistype.counted = 0
        call GroupEnumUnitsInArea(thistype.g, x, y, 280+20*lvl, Filter(function thistype.GroupEm))
        call SetTimerData(.tim,this)
        call TimerStart(.tim, TICK, true, function thistype.Timer)
     return this
    endmethod

endstruct

private function Conditions takes nothing returns boolean
    if GetSpellAbilityId() == SPELLID then
        call Data.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
    endif
 return false
endfunction

//===========================================================================
public function InitTrig_Tormented_Chains takes nothing returns nothing
 local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( t, function Conditions )
endfunction

endscope
 
Last edited:
Level 13
Joined
Mar 16, 2008
Messages
941
local group g = thistype.g
JASS:
if IsUnitType(u, UNIT_TYPE_DEAD) or GetUnitAbilityLevel(u, BUFFID) < 1 then
                call DestroyTrigger(EVENT[GetUnitId(u)])
                set EVENT[GetUnitId(u)] = null
                call GroupRemoveUnit(thistype.g, u)
            endif
            call GroupRemoveUnit(g, u)
I think you intended to copy this group for a temporary loop-through. Either realy copy the group or use the ForGroup-Function.
 
Status
Not open for further replies.
Top