• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Dispersion ability also damages building. How to fix?

Level 14
Joined
Jul 19, 2007
Messages
772
I imported an ability from a Dota Spellpack that was named "Dispersion" and it damages all enemy units around the hero with the Dispersion ability when it takes damage but the problem is that it also seems to damage buildings... I only want it to damage organic units...
JASS:
//TESH.scrollpos=21
//TESH.alwaysfold=0
scope Dispersion initializer Init

globals
    private constant integer AbilId = 'A0KK'
    
    private boolexpr B
    private real R
    private unit U
endglobals

private function Filt takes nothing returns boolean    
    local unit targ = GetFilterUnit()
    
    if IsUnitVisible(targ,GetOwningPlayer(GetTriggerUnit())) and IsUnitEnemy(targ,GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(targ)>.405 then
        if DBU(U,targ)<=300. then
            call UnitDamageTargetEx(GetTriggerUnit(), targ,R, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_SPELL, false)
        else
            call UnitDamageTargetEx(GetTriggerUnit(), targ,R*(1-DBU(U,targ)/1000.), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_SPELL, false)
        endif
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayDamage.mdl",targ,"chest"))
    endif
    
    set targ = null
    return false
endfunction
private function Effects takes nothing returns boolean
    local unit u=GetTriggerUnit()
    local real r=GetEventDamage()
    local group g

    if r>.1 and r<3000. then
        set g=NewGroup()
        set R=r*(0.04*GetUnitAbilityLevel(u,AbilId)+.06)
        //call Echo(R2S(GetEventDamage())+" : "+R2S(R))
        call ShieldUnit(u,R,r)
        //call SetWidgetLife(u,GetWidgetLife(u)+R)
        set U = u
        call GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),1000.,B)
        call ReleaseGroup(g)
    endif
    
    set u = null
    return false
endfunction
private function Actions takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerRegisterUnitEvent(t,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
    call TriggerAddCondition(t,Condition(function Effects))
endfunction
private function Conds takes nothing returns boolean
    if GetOwningPlayer(GetTriggerUnit())!=Player(15) and GetLearnedSkill()==AbilId and GetUnitAbilityLevel(GetTriggerUnit(),AbilId)==1 and not IsUnitIllusion(GetTriggerUnit()) then
        call Actions()
    endif
    return false
endfunction
private function Init takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_HERO_SKILL)
    call TriggerAddCondition(t,Condition(function Conds))
    set B = Condition(function Filt)
endfunction

endscope
 

Uncle

Warcraft Moderator
Level 65
Joined
Aug 10, 2018
Messages
6,668
Here's your Filter function that determines the targets and also deals the damage (normally a filter would just handle the targeting but this is fine):
vJASS:
private function Filt takes nothing returns boolean
    local unit targ = GetFilterUnit()
 
    if IsUnitVisible(targ,GetOwningPlayer(GetTriggerUnit())) and IsUnitEnemy(targ,GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(targ)>.405 then
        if DBU(U,targ)<=300. then
            call UnitDamageTargetEx(GetTriggerUnit(), targ,R, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_SPELL, false)
        else
            call UnitDamageTargetEx(GetTriggerUnit(), targ,R*(1-DBU(U,targ)/1000.), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_SPELL, false)
        endif
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayDamage.mdl",targ,"chest"))
    endif
 
    set targ = null
    return false
endfunction

A Filter in Jass code is the same thing as "Matching unit..." in GUI:
  • Set Variable TempGroup = (Units within 500.00 range of Point matching (Matching unit) is Visible Equal to True and (Matching unit) belongs to an enemy...

This is the exact line where you can see the code determining which units to target. You may notice some familiar sounding functions.
I know code seems intimidating at first but when you separate it and read it line by line it's pretty self explanatory:
vJASS:
if IsUnitVisible(targ,GetOwningPlayer(GetTriggerUnit())) and IsUnitEnemy(targ,GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(targ)>.405 then
Is the unit visible and is the unit an enemy and is the unit's life > .405 (is it alive?)


So all you have to do now is add another check to see if the unit is NOT a Structure to prevent those from being damaged. You can figure out how to write that by creating a GUI trigger that checks if a (Matching unit) is a Structure/Mechanical and then convert that to usable code. Then from there it shouldn't be too hard to figure out how to check if it's True/False or how to insert it into the existing code, it all follows an easy to understand pattern.
 
Last edited:
Level 14
Joined
Jul 19, 2007
Messages
772
Here's your Filter function that determines the targets and also deals the damage (normally a filter would just handle the targeting but this is fine):
vJASS:
private function Filt takes nothing returns boolean
    local unit targ = GetFilterUnit()
 
    if IsUnitVisible(targ,GetOwningPlayer(GetTriggerUnit())) and IsUnitEnemy(targ,GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(targ)>.405 then
        if DBU(U,targ)<=300. then
            call UnitDamageTargetEx(GetTriggerUnit(), targ,R, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_SPELL, false)
        else
            call UnitDamageTargetEx(GetTriggerUnit(), targ,R*(1-DBU(U,targ)/1000.), ATTACK_TYPE_CHAOS, DAMAGE_TYPE_SPELL, false)
        endif
        call DestroyEffect(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayDamage.mdl",targ,"chest"))
    endif
 
    set targ = null
    return false
endfunction

A Filter in Jass code is the same thing as "Matching unit..." in GUI:
  • Set Variable TempGroup = (Units within 500.00 range of Point matching (Matching unit) is Visible Equal to True and (Matching unit) belongs to an enemy...

This is the exact line where you can see the code determining which units to target. You may notice some familiar sounding functions.
I know code seems intimidating at first but when you separate it and read it line by line it's pretty self explanatory:
vJASS:
if IsUnitVisible(targ,GetOwningPlayer(GetTriggerUnit())) and IsUnitEnemy(targ,GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(targ)>.405 then
Is the unit visible and is the unit an enemy and is the unit's life > .405 (is it alive?)


So all you have to do now is add another check to see if the unit is NOT a Structure to prevent those from being damaged. You can figure out how to write that by creating a GUI trigger that checks if a (Matching unit) is a Structure/Mechanical and then convert that to usable code. Then from there it shouldn't be too hard to figure out how to check if it's True/False or how to insert it into the existing code, it all follows an easy to understand pattern.
I tried but I can't get it working because it gives error and I made it like this
JASS:
if IsUnitVisible(targ,GetOwningPlayer(GetTriggerUnit())) and IsUnitType(targ,GetOwningPlayer(GetTriggerUnit())) UNIT_TYPE_STRUCTURE) == false ) ) and IsUnitEnemy(targ,GetOwningPlayer(GetTriggerUnit())) and GetWidgetLife(targ)>.405 then
 

Uncle

Warcraft Moderator
Level 65
Joined
Aug 10, 2018
Messages
6,668
So look at the new code you've added:
vJASS:
IsUnitType(targ,GetOwningPlayer(GetTriggerUnit())) UNIT_TYPE_STRUCTURE) == false ) )

What is this doing in there?
vJASS:
GetOwningPlayer()
Why would you need to get the Player that owned the unit here? It's not "Is the unit a Structure OWNED by someone". It's simply: "Is the unit a Structure".


The function is called IsUnitType(). The parameters take a unit and a UNIT_TYPE:
vJASS:
IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false
So it's asking a simple question:

Is the unit (put your unit here) of a certain type (put your type here)?
 
Level 14
Joined
Jul 19, 2007
Messages
772
So look at the new code you've added:
vJASS:
IsUnitType(targ,GetOwningPlayer(GetTriggerUnit())) UNIT_TYPE_STRUCTURE) == false ) )

What is this doing in there?
vJASS:
GetOwningPlayer()
Why would you need to get the Player that owned the unit here? It's not "Is the unit a Structure OWNED by someone". It's simply: "Is the unit a Structure".


The function is called IsUnitType(). The parameters take a unit and a UNIT_TYPE:
vJASS:
IsUnitType(targ, UNIT_TYPE_STRUCTURE) == false
So it's asking a simple question:

Is the unit (put your unit here) of a certain type (put your type here)?
Oh I see. I didn't think about that... Thanks for help! 🙂
 
Top