• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!
  • ✅ The POLL for Hive's Texturing Contest #34 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!
  • ✅ The POLL for Hive's Techtree Contest #20 is OPEN! Vote for the TOP 3 FACTIONS! 🔗Click here to cast your vote!

[Spell] I don't want knockback-effect to affect buildings or magic immunes.

Level 17
Joined
Jul 19, 2007
Messages
973
A little problem with a new JASS-triggered ability I imported to my map. It seems like the knockback-effect is affecting buildings and magic immune units too. How should I make in the script so it doesn't?

JASS:
//TESH.scrollpos=96
//TESH.alwaysfold=0
scope PrimalRoar initializer Init

globals
    private constant integer AbilId = 'A0RY'
    private constant integer DumId = 'n01Z'
    private constant integer DumAbilId = 'A0SK'
    
    private integer I
endglobals
private struct data
    unit u
    unit targ
    player p
    timer t
    group g
    real ang
    integer lvl
    integer count = 0
    real x
    real y
    real speed = 30.
    real dec = 30./17.
    
    method onDestroy takes nothing returns nothing
        call ReleaseGroup(.g)
        call ReleaseTimer(.t)
    endmethod
endstruct

private function Move takes nothing returns nothing
    local data d = I
    local unit targ = GetEnumUnit()
    local real x=GetUnitX(targ)
    local real y=GetUnitY(targ)
    local real a=bj_RADTODEG*Atan2(y-d.y,x-d.x)
    
    if Sin((a-d.ang)*bj_DEGTORAD)<0 then
        set x=x+d.speed*Cos((d.ang-90.)*bj_DEGTORAD)
        set y=y+d.speed*Sin((d.ang-90.)*bj_DEGTORAD)
        call SetUnitFacingTimed(targ,d.ang+90.,0.3)
    else
        set x=x+d.speed*Cos((d.ang+90.)*bj_DEGTORAD)
        set y=y+d.speed*Sin((d.ang+90.)*bj_DEGTORAD)
        call SetUnitFacingTimed(targ,d.ang-90.,0.3)
    endif
    call KillDesInArea( x, y, 150.)
    call SetUnitPosition(targ,x,y)
    call DestroyEffect(AddSpecialEffectTarget("Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl",targ,"origin"))
    
    set targ = null
endfunction
private function Effects takes nothing returns nothing
    local data d = GetTimerData(GetExpiredTimer())

    set d.count = d.count + 1
    if d.count>16 then
        call d.destroy()
    else
        set I = d
        call ForGroup(d.g,function Move)
        set d.speed = d.speed - d.dec
    endif
endfunction
private function Filt takes nothing returns boolean
    local data d = I
    local unit targ = GetFilterUnit()
    
    if d.targ!=targ and IsUnitEnemy(targ,d.p) and GetWidgetLife(targ)>.405 and not IsUnitInGroup(targ,d.g) then
        call GroupAddUnit(d.g,targ)
        call UnitDamageTargetEx(d.u, targ, d.lvl*100., ATTACK_TYPE_NORMAL, DAMAGE_TYPE_SPELL, false)
    endif    
    
    set targ = null
    return false
endfunction
private function Actions takes nothing returns nothing
    local data d = data.create()
    local unit dum
    local real x
    local real y
    local real r = 50.
    local group g = NewGroup()
    
    set d.t=NewTimer()
    set d.u=GetTriggerUnit()
    set d.p = GetOwningPlayer(d.u)
    set d.targ=GetSpellTargetUnit()
    set d.lvl=GetUnitAbilityLevel(d.u,AbilId)
    set d.x = GetUnitX(d.u)
    set d.y = GetUnitY(d.u)
    set d.ang = bj_RADTODEG*Atan2(GetUnitY(d.targ)-d.y,GetUnitX(d.targ)-d.x)
    set d.g = NewGroup()

    call SetTimerData(d.t,d)
    call TimerStart(d.t,.025,true,function Effects)

    set I = d
    loop
        exitwhen r>500.
        
        set x = d.x+r*Cos(d.ang*bj_DEGTORAD)
        set y = d.y+r*Sin(d.ang*bj_DEGTORAD)
        call GroupEnumUnitsInRange(g,x,y,250.,Condition(function Filt))
        call GroupClear(g)
        set dum=CreateUnit(d.p,DumId,x,y,d.ang)
        call UnitApplyTimedLife(dum,'BTLF',1.)
        call UnitAddAbility(dum,DumAbilId)
        call SetUnitAbilityLevel(dum,DumAbilId,d.lvl)
        call IssueImmediateOrder(dum,"thunderclap")
        
        set r = r + 200.
    endloop
    call UnitDamageTargetEx(d.u, d.targ, 150.+d.lvl*50., ATTACK_TYPE_NORMAL, DAMAGE_TYPE_SPELL, false)
    call UnitDamageTargetEx(d.u, d.targ, d.lvl*100., ATTACK_TYPE_NORMAL, DAMAGE_TYPE_SPELL, false)

    set dum = null
    call ReleaseGroup(g)
endfunction

private function Conds takes nothing returns boolean
    if GetSpellAbilityId()==AbilId then
        call Actions()
    endif
    return false
endfunction
private function Init takes nothing returns nothing
    local trigger t=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t,Condition(function Conds))
    call PreloadAbil(DumAbilId)
endfunction

endscope
 
Replace the filter function:


Code:
private function Filt takes nothing returns boolean
    local data d = I
    local unit targ = GetFilterUnit()
  
    // checks to ignore Buildings and Magic Immune units
    if d.targ!=targ and IsUnitEnemy(targ,d.p) and GetWidgetLife(targ)>.405 and not IsUnitInGroup(targ,d.g) and not IsUnitType(targ, UNIT_TYPE_STRUCTURE) and not IsUnitType(targ, UNIT_TYPE_MAGIC_IMMUNE) then
        call GroupAddUnit(d.g,targ)
        call UnitDamageTargetEx(d.u, targ, d.lvl*100., ATTACK_TYPE_NORMAL, DAMAGE_TYPE_SPELL, false)
    endif 
  
    set targ = null
    return false
endfunction

! Note: If your map uses custom immunities, you may need to check for a specific buff or ability rawcode instead.
Also: Primary target (d.targ) is not filtered for now, the visual effects (thunderclap dummies) and the initial damage might still affect the primary target if it’s magic immune. To prevent casting the spell entirely on invalid targets, add this condition in the actions function:

Code:
if IsUnitType(d.targ, UNIT_TYPE_STRUCTURE) or IsUnitType(d.targ, UNIT_TYPE_MAGIC_IMMUNE) then
    call d.destroy()
    return
endif
 
Last edited:
Replace the filter function:


Code:
private function Filt takes nothing returns boolean
    local data d = I
    local unit targ = GetFilterUnit()
 
    // checks to ignore Buildings and Magic Immune units
    if d.targ!=targ and IsUnitEnemy(targ,d.p) and GetWidgetLife(targ)>.405 and not IsUnitInGroup(targ,d.g) and not IsUnitType(targ, UNIT_TYPE_STRUCTURE) and not IsUnitType(targ, UNIT_TYPE_MAGIC_IMMUNE) then
        call GroupAddUnit(d.g,targ)
        call UnitDamageTargetEx(d.u, targ, d.lvl*100., ATTACK_TYPE_NORMAL, DAMAGE_TYPE_SPELL, false)
    endif
 
    set targ = null
    return false
endfunction

! Note: If your map uses custom immunities, you may need to check for a specific buff or ability rawcode instead.
Also: Primary target (d.targ) is not filtered for now, the visual effects (thunderclap dummies) and the initial damage might still affect the primary target if it’s magic immune. To prevent casting the spell entirely on invalid targets, add this condition in the actions function:

Code:
if IsUnitType(d.targ, UNIT_TYPE_STRUCTURE) or IsUnitType(d.targ, UNIT_TYPE_MAGIC_IMMUNE) then
    call d.destroy()
    return
endif
It seems to be working now, thank you!
 
Back
Top