• 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.

[JASS] ranged "cleaving attack"; what now?

Status
Not open for further replies.
Level 3
Joined
Jan 7, 2010
Messages
37
Hi!

I'm trying to get "cleaving attack" work with ranged attacks.
I use this armor detection system: http://www.wc3c.net/showthread.php?t=105849
This is the first time I use JASS, so I'm not sure how to handle these problems:


  1. How do I figure out if the damaged unit was attacked by a melee/ranged attack
    OR
    How do I figure out if the attack type was not spell/magic/chaos...
  2. will this be MUI? what do I need to change?

The code is working so far, spreading damage the way it should. The problem with #1 is, this will trigger with EVERY attack and spell. It should trigger only when using the "normal" attack.

This is the code I got so far:

JASS:
scope CleaveSplash initializer Init
globals
    private trigger TRG = CreateTrigger()
    boolean already_cleaved = false         // this shall prevent the "UnitIsDamaged" event to be called infinite by "call UnitDamageTarget" 
endglobals

private function PreloadUnits takes nothing returns boolean
    call TriggerRegisterUnitEvent(TRG, GetFilterUnit(), EVENT_UNIT_DAMAGED)
    return true
endfunction

private function RunConditions takes nothing returns boolean
    return (GetUnitAbilityLevel(GetEventDamageSource(),'ANca') > 0) and (already_cleaved == false)
endfunction

private function Run takes nothing returns nothing
    //local real    f = GetFullDamage(d, a)
    //local real    r = GetReducedDamage(f, a)
    
    local unit      target = GetTriggerUnit()               // attacked unit
    local location  loc = GetUnitLoc(target)                                     // position of attacked unit, from where the AE will be applied
    local unit      attacker = GetEventDamageSource()                // attacking unit
    local integer   ab_lvl = GetUnitAbilityLevel(attacker,'ANca')  // the ability level of the attacking unit; the higher, the more dmg is spread
    local real      d = GetEventDamage()                    // used for GetFullDamage()
    local real      a = GetUnitArmor(target)                     // used for GetFullDamage, T is used to calculate armor
    local real      dmg = GetFullDamage(d,a)                // FULL damage or  REDUCED damage to spread nearby??
    local real      cleave_dmg
    local group     enemies = CreateGroup()                 // ALL units around the attacked unit (allies included)
    local real      aoe = 200.                              // Area of effect
    local unit      temp_unit                               // temp unit used in the loop
    local integer   i = 0                                   // loop integer
    
    // damage code here ---------------------------->
    call GroupEnumUnitsInRangeOfLoc(enemies, loc, aoe, null)    // pickes all units in "aoe" range of "target" unit
    call GroupRemoveUnit(enemies,attacker)                      // removes the "attacker", so he won't harm himself
    
    set cleave_dmg = ((I2R(ab_lvl)*25 + 5)/100)*dmg     // recalculates the spread dmg, based on the ability level [1: 30%; 2: 55%; 3: 80%]
    
    set already_cleaved = true
    
    loop
        set temp_unit = FirstOfGroup(enemies)
        exitwhen temp_unit == null
        
        call UnitDamageTarget(attacker, temp_unit, cleave_dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        call GroupRemoveUnit(enemies, temp_unit)
    endloop   
    
    set already_cleaved = false
    // damage code end ---------------------------->
    
    
    call BJDebugMsg("------------------------")
    call BJDebugMsg("Damage spread: "+R2S(cleave_dmg))
    //call BJDebugMsg("Base Damage:   "+R2S(f))
    //call BJDebugMsg("Calc'd Damage: "+R2S(r))
    
    
    // -------------- Leaks    
    call RemoveLocation(loc)
    call DestroyGroup(enemies)

    
        // null
    set loc = null
    set target = null
    set temp_unit = null
    set attacker = null
    set enemies = null

    
endfunction

private function Init takes nothing returns nothing
    local rect r = GetWorldBounds()
    local group g = CreateGroup()
 
    call GroupEnumUnitsInRect(g, r, Condition(function PreloadUnits))
    call TriggerAddCondition(TRG, Condition(function RunConditions))
    call TriggerAddAction(TRG, function Run)
    
    call RemoveRect(r)
    call DestroyGroup(g)
    set g = null
    set r = null
endfunction
endscope
 
Level 21
Joined
Mar 27, 2012
Messages
3,232
Hi!

I'm trying to get "cleaving attack" work with ranged attacks.
I use this armor detection system: http://www.wc3c.net/showthread.php?t=105849
This is the first time I use JASS, so I'm not sure how to handle these problems:


  1. How do I figure out if the damaged unit was attacked by a melee/ranged attack
    OR
    How do I figure out if the attack type was not spell/magic/chaos...
  2. will this be MUI? what do I need to change?

The code is working so far, spreading damage the way it should. The problem with #1 is, this will trigger with EVERY attack and spell. It should trigger only when using the "normal" attack.

This is the code I got so far:

JASS:
scope CleaveSplash initializer Init
globals
    private trigger TRG = CreateTrigger()
    boolean already_cleaved = false         // this shall prevent the "UnitIsDamaged" event to be called infinite by "call UnitDamageTarget" 
endglobals

private function PreloadUnits takes nothing returns boolean
    call TriggerRegisterUnitEvent(TRG, GetFilterUnit(), EVENT_UNIT_DAMAGED)
    return true
endfunction

private function RunConditions takes nothing returns boolean
    return (GetUnitAbilityLevel(GetEventDamageSource(),'ANca') > 0) and (already_cleaved == false)
endfunction

private function Run takes nothing returns nothing
    //local real    f = GetFullDamage(d, a)
    //local real    r = GetReducedDamage(f, a)
    
    local unit      target = GetTriggerUnit()               // attacked unit
    local location  loc = GetUnitLoc(target)                                     // position of attacked unit, from where the AE will be applied
    local unit      attacker = GetEventDamageSource()                // attacking unit
    local integer   ab_lvl = GetUnitAbilityLevel(attacker,'ANca')  // the ability level of the attacking unit; the higher, the more dmg is spread
    local real      d = GetEventDamage()                    // used for GetFullDamage()
    local real      a = GetUnitArmor(target)                     // used for GetFullDamage, T is used to calculate armor
    local real      dmg = GetFullDamage(d,a)                // FULL damage or  REDUCED damage to spread nearby??
    local real      cleave_dmg
    local group     enemies = CreateGroup()                 // ALL units around the attacked unit (allies included)
    local real      aoe = 200.                              // Area of effect
    local unit      temp_unit                               // temp unit used in the loop
    local integer   i = 0                                   // loop integer
    
    // damage code here ---------------------------->
    call GroupEnumUnitsInRangeOfLoc(enemies, loc, aoe, null)    // pickes all units in "aoe" range of "target" unit
    call GroupRemoveUnit(enemies,attacker)                      // removes the "attacker", so he won't harm himself
    
    set cleave_dmg = ((I2R(ab_lvl)*25 + 5)/100)*dmg     // recalculates the spread dmg, based on the ability level [1: 30%; 2: 55%; 3: 80%]
    
    set already_cleaved = true
    
    loop
        set temp_unit = FirstOfGroup(enemies)
        exitwhen temp_unit == null
        
        call UnitDamageTarget(attacker, temp_unit, cleave_dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null)
        call GroupRemoveUnit(enemies, temp_unit)
    endloop   
    
    set already_cleaved = false
    // damage code end ---------------------------->
    
    
    call BJDebugMsg("------------------------")
    call BJDebugMsg("Damage spread: "+R2S(cleave_dmg))
    //call BJDebugMsg("Base Damage:   "+R2S(f))
    //call BJDebugMsg("Calc'd Damage: "+R2S(r))
    
    
    // -------------- Leaks    
    call RemoveLocation(loc)
    call DestroyGroup(enemies)

    
        // null
    set loc = null
    set target = null
    set temp_unit = null
    set attacker = null
    set enemies = null

    
endfunction

private function Init takes nothing returns nothing
    local rect r = GetWorldBounds()
    local group g = CreateGroup()
 
    call GroupEnumUnitsInRect(g, r, Condition(function PreloadUnits))
    call TriggerAddCondition(TRG, Condition(function RunConditions))
    call TriggerAddAction(TRG, function Run)
    
    call RemoveRect(r)
    call DestroyGroup(g)
    set g = null
    set r = null
endfunction
endscope

There is no direct way of checking whether an attack is ranged. You could check the distance, but that will mess up a lot.

I'd use a sort of tagging system. Create an invisible ability and give it to all ranged units. That way you will know if the attack is ranged too. (By checking whether the unit has that ability)

looking_for_help made a system(Physical Damage Detection) that can check whether a unit is damaged by magic/spell damage or normal attacks.
Why do you need to check armor anyway? If you use the same attacktype for dealing damage than the unit does, then it will go through the armor reduction as it should. If you use chaos, then it isn't reduced(except by armor points).
 
Level 3
Joined
Jan 7, 2010
Messages
37
The problem is not to check if it was a ranged attack, but a "normal attack" (!= spell).

The armor part is for later purposes needed. Also I'm not yet sure whether the spread dmg shall be based on the full dmg, or the reduced dmg.

I will check out the system you mentioned!

Thanks!
 
Level 3
Joined
Jan 7, 2010
Messages
37
umm as Xonok said looking_for_help made a system(Physical Damage Detection) that can check whether a unit is damaged by magic/spell damage or normal attacks.

Also u shouldnt use locations when coding with Jass / vJass.
Use reals instead and get the units x and y values.

Thanks for the tip!
 
Level 7
Joined
Jan 22, 2013
Messages
293
Thanks for the tip!

Like to give you another tip.

Even after the unit takes damage and you run it back to the person who shot it. there are some other issues with a damage system you must know about.

bounce attacks.
splash
line damage
Homing arrows and you attemping to grab the angle of person who shot the projectile to caculate the angle in which the cleave attack gets directed from.


you see a projectile takes time to travel. you have free roam to move before it hits. the problem with cleave attack is that cleave attacks damage spread is based on the angle you are facing. if you can move around before it hits a unit then you can only register the amgle when it hits a unit (due to damage system). if you end up with a bounce unit:ogre_datass: the trigger will work on all bounces. same with splash and line damage. my solution to your problem here id to re-structure the way you are thinking about your spell. If you want cleave to work on a ranged unit you must store his angle every time he shoots. good luck with that. you should stick with an aoe spell. (this spell is possible but you will always have bugs and glitches with it even if it is coded perfect) systems dont allow it.
 
Status
Not open for further replies.
Top