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

Filtering out dead units

Status
Not open for further replies.
Level 20
Joined
May 16, 2012
Messages
635
Hello again hivers. I was messing around with a missile system i just installed in my map, and to practice i decided to create a simple spell. Basically what the spell does is, it launches a missile to the targeted unit, and once the missile hits the target unit it splashes to 5 units nearby the target. The problem is that i've created a filtering if() statement to filter out units that are dead, so the splashed missiles always go to units that are alive, but somehow those units are still being picked by the filter. code below:

JASS:
scope MTest initializer Init

private struct Split extends xehomingmissile
    private unit source
    private unit target
   
    static method create takes unit source, unit target, real x, real y, real z returns Split
        local Split this = Split.allocate(x, y, z, target, 50.0)
       
        set this.source = source
        set this.target = target
        set this.fxpath = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
        set this.scale  = 0.5
       
        call this.launch(700.0, 0.35)

        return this
    endmethod
   
    method onHit takes nothing returns nothing
        call UnitDamageTarget(.source, .target, 250.0, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
    endmethod
endstruct

private struct Mtest extends xehomingmissile
    private unit caster
    private unit target
   
    static method create takes unit caster, unit target, real x, real y, real z returns Mtest
        local Mtest this = Mtest.allocate(x, y, z, target, 50.0)
       
        set this.caster = caster
        set this.target = target
        set this.fxpath = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile.mdl"
        set this.scale  = 0.5
       
        call this.launch(900.0, 0.15)

        return this
    endmethod
   
    method onHit takes nothing returns nothing
        local integer i = 0
        local unit u
        local group g = CreateGroup()
       
        call UnitDamageTarget(.caster, .target, 500.0, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_UNIVERSAL, null)
        call GroupEnumUnitsInRange(g, GetUnitX(.target), GetUnitY(.target), 1000.0, null)
        call GroupRemoveUnit(g, .target)
        loop
            set u = FirstOfGroup(g)
            exitwhen i > 4 or u == null
                call ArcingTextTag.create(("|cff32cd32" + "!"), u)
                if(IsUnitEnemy(u, GetOwningPlayer(.caster)) and UnitAlive(u) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)) then
                    call Split.create(.caster, u, GetUnitX(.target), GetUnitY(.target), 60.0)
                endif
                call GroupRemoveUnit(g, u)
                set i = i + 1
        endloop
        call DestroyGroup(g)
       
        set u = null
        set g = null
    endmethod
endstruct

private function Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local unit target = GetSpellTargetUnit()
    local Mtest m = Mtest.create(caster, target, GetUnitX(caster), GetUnitY(caster), 60.0)
   
    set caster = null
    set target = null
endfunction

private function Conditions takes nothing returns boolean
    if (GetSpellAbilityId() == 'A03Q') then
        call Actions()
    endif
    return false
endfunction
//===========================================================================
private function Init takes nothing returns nothing
    set gg_trg_MTest = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_MTest, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_MTest, Condition(function Conditions))
endfunction

As you can see, i'm doing:

JASS:
call GroupEnumUnitsInRange(g, GetUnitX(.target), GetUnitY(.target), 1000.0, null)
        call GroupRemoveUnit(g, .target)
        loop
            set u = FirstOfGroup(g)
            exitwhen i > 4 or u == null
                call ArcingTextTag.create(("|cff32cd32" + "!"), u)
                if(IsUnitEnemy(u, GetOwningPlayer(.caster)) and UnitAlive(u) and not IsUnitType(u, UNIT_TYPE_STRUCTURE)) then
                    call Split.create(.caster, u, GetUnitX(.target), GetUnitY(.target), 60.0)
                endif
                call GroupRemoveUnit(g, u)
                set i = i + 1
        endloop
        call DestroyGroup(g)
to filter all units within 1000 range, but the following problems are happening:

1º - if i cast the spell on certain units (units in the first line with the ! on top of their heads, see image) only 3 specifics units are picked instead of 5.
2.png

2º - if i cast the spell and there are dead units within the range, they are still getting picked, and i already tried to use multiple ways to check if the unit is alive (UnitAlive Native, IsUnitType(u, UNIT_TYPE_DEAD) == false, a Boolean array provided by a system wrote by bribe (Unit Event System) udg_IsUnitAlive), but none of those are actually making the spell work the way i wanted.

3.png

Cant figured out whats i'm doing wrong.
 
Level 39
Joined
Feb 27, 2007
Messages
5,023
Move the set i = i+1 to inside the if-block. You only want that counter to go up every time it successfully finds a target.

For what it's worth UNIT_TYPE_DEAD is no good for checking this stuff. You always want to either implement and use UnitAlive() or check GetWidgetLife(unit) > 0.405.
 
Level 20
Joined
May 16, 2012
Messages
635
Move the set i = i+1 to inside the if-block. You only want that counter to go up every time it successfully finds a target.

For what it's worth UNIT_TYPE_DEAD is no good for checking this stuff. You always want to either implement and use UnitAlive() or check GetWidgetLife(unit) > 0.405.

Believe it or not, but i figured it out in my sleep yesterday hahaha, but thx anyway.
 
Status
Not open for further replies.
Top