HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

How to determine qualities of damage events?

02-20-2009, 03:16 AM#1
fX_
1) IsDamageEventAttack
2) IsDamageEventRanged(attack)
3) DamageEventAttackType
4) DamageEventWeaponType
5) DamageEventDamageType

???

Collapse JASS:
private function ValidateDamageEvent takes nothing returns boolean
        local boolean BOOL

        set bj_DamagingUnit = GetEventDamageSource()
        set bj_DamagedUnit = GetTriggerUnit()
        set bj_EventDamageAmount = GetEventDamage()
        set bj_EventDamageAttack = ???
        set bj_EventDamageRanged = ???
        set bj_EventDamageAttackType = ???
        set bj_EventDamageDamageType = ???
        set bj_EventDamageWeaponType = ???

        set BOOL = IsValidDamageEvent() 
        if BOOL == false then
            set bj_DamagingUnit = null
            set bj_DamagedUnit = null
            set bj_EventDamageAmount = 0.00
            set bj_EventDamageAttack = false
            set bj_EventDamageRanged = false
            set bj_EventDamageAttackType = null
            set bj_EventDamageDamageType = null
            set bj_EventDamageWeaponType = null
        endif

        return BOOL
    endfunction

Currently, I am considering

Collapse JASS:
library DamageEvent initializer Init requires UnitTypeAttackDamageData
Collapse JASS:
library UnitTypeAttackDamageData

    globals
        private constant integer RECORD_MAX_INSTANCES = 8190
    endglobals

    function RegisterUnitTypeAttackDamageData takes integer unitId, boolean ranged, attacktype at, damagetype dt, weapontype wt returns boolean
        return UTDD.Create(unitId, ranged, at, dt, wt)
    endfunction

    struct UTDD[RECORD_MAX_INSTANCES]

        private integer intUnitId
        public boolean boolRanged
        public attacktype at
        public weapontype wt
        public damagetype dt

        public static method Create takes integer unitId, boolean ranged, attacktype at, weapontype wt, damagetype dt returns boolean
            if unitId != 0 and at != null and dt != null and wt != null and UTDD.intCountInst < RECORD_MAX_INSTANCES and UTDD.Get(unitId) == 0 then
                set UTDD.Inst[UTDD.intCountInst] = UTDD.allocate()
                set UTDD.Inst[UTDD.intCountInst].intUnitId = unitId
                set UTDD.Inst[UTDD.intCountInst].boolRanged = ranged
                set UTDD.Inst[UTDD.intCountInst].at = at
                set UTDD.Inst[UTDD.intCountInst].dt = dt
                set UTDD.Inst[UTDD.intCountInst].wt = wt

                set UTDD.intCountInst = UTDD.intCountInst + 1

                return true
            endif

            return false
        endmethod

        private static UTDD array Inst[RECORD_MAX_INSTANCES]
        private static integer intCountInst = 0

        public static method Get takes integer unitId returns UTDD
            local integer INT_Index = 0

            loop
                exitwhen INT_Index == UTDD.intCountInst
                if UTDD.Inst[INT_Index].intUnitId == unitId then
                    return UTDD.Inst[INT_Index]
                endif
                set INT_Index = INT_Index + 1
            endloop

            return 0
        endmethod

    endstruct

endlibrary

But this is like some extra chore for the main action of the script (and it requires registration for every relevant unit type...).

This, with some UnitDamageTargetEx()-like function (like that from Rising_Dusk's 'Intuitive Damage Detection System').

These two account for damage dealt by attack and by triggers; I have yet to determine how to evaluate damage dealt by spells.
(but spell damage <==>
Collapse JASS:
UnitDamageTarget(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage(), false, false, null, DAMAGE_TYPE_MAGIC, null)
, I think. If this is true, then I will only need to differentiate between damage-by-attack and damage-by-spells.)
...these two are very... 'on-the-side' and 'indirect', I'd prefer a more 'natural' way to do this. Is there any other way?
02-20-2009, 03:19 AM#2
Bobo_The_Kodo
1) you cant
2) you cant
3) you cant
4) you cant
5) you cant

Try using IDDS or something to keep track yourself.
02-20-2009, 03:22 AM#3
xombie
Actually, detecting if it is from a range is possible.

Collapse JASS:
IsUnitType(GetEventDamageSource(), UNIT_TYPE_RANGED_ATTACKER)

I'm not sure if its RANGED or RANGED_ATTACKER or something else similar.
02-20-2009, 04:04 AM#4
Bobo_The_Kodo
That just checks if the attacker doesn't have "Normal" missile type; it does not check if it was from a range or not
02-20-2009, 04:11 AM#5
fX_
Quote:
1) you cant
2) you cant
3) you cant
4) you cant
5) you cant

FFS

edit:
IsUnitType(blablabla) suggestion should work if it is what I think it is.
Here, I am only determining if the attack is ranged, not if it was projected from a range (and the latter can be ascertained by distance-between-points evaluation with a comparison to the damager's collision size - the latter can be determined by a GetUnitCollisionSize() script archived somewhere).

edit2:
After some judgement, I think that the damagetype for all attacks is DAMAGE_TYPE_NORMAL; I find no implication of ACID/FIRE/other-damage-types to attacks; and that damage attribute which corresponds to Siege/Pierce/Magic/Hero/Normal/Chaos is attacktype...
Is this correct?

Thus far:
First, UnitDamageEx() by Rising_Dusk:
Collapse JASS:
function UnitDamageTargetEx takes boolean monitor, unit source, unit target, real amount, attacktype at, damagetype dt, weapontype wt returns boolean
        local boolean BOOL_Successful

        if source != null and target != null and dt != null then
            set gBOOL_Monitor = monitor
            if gBOOL_Monitor then
                set bj_EventDamageAttack = attack
                set bj_EventDamageRanged = ranged
                set bj_EventDamageAttackType = at
                set bj_EventDamageDamageType = dt
                set bj_EventDamageWeaponType = wt
            endif
            set BOOL_Successful = UnitDamageTarget(source, target, amount, attack, ranged, at, dt, wt)
            if gBOOL_Monitor and BOOL_Successful == false then
                set bj_EventDamageAttack = false
                set bj_EventDamageRanged = false
                set bj_EventDamageAttackType = null
                set bj_EventDamageDamageType = null
                set bj_EventDamageWeaponType = null
            endif
            set gBOOL_Monitor = true

            return BOOL_Successful
        endif

        return false
    endfunction

Collapse JASS:
private function ValidateDamageEvent takes nothing returns boolean
        local boolean BOOL

        if gBOOL_Monitor then
            set bj_DamagingUnit = GetEventDamageSource()
            set bj_DamagedUnit = GetTriggerUnit()
            set bj_EventDamageAmount = GetEventDamage()
            // (bj_EventDamageDamageType != null) <==> (Damage is dealt by script.)
            //      - by functions of UnitDamageTargetEx().
            // In this case, the damage is dealt either by attack or by spell.
            if bj_EventDamageDamageType == null then
                set bj_EventDamageAttack = ???
                //If damage is dealt by attack, then its ranged quality is
                //either 'false' - if the attacker is a melee unit - or 'true'
                //- if the attacker is a ranged unit; and its damagetype is
                //definitely normal by hardcoded WC3.
                //Else, if it is not dealt by attack, and is, therefore, by-spell,
                //then its ranged quality is definitely 'false'; and its attacktype and
                //damagetype are both 'null'.
                if bj_EventDamageAttack then
                    set bj_EventDamageRanged = IsUnitType(bj_DamagingUnit, UNIT_TYPE_RANGED_ATTACKER)
                    set bj_EventDamageAttackType = ???
                    set bj_EventDamageDamageType = DAMAGE_TYPE_NORMAL
                    set bj_EventDamageWeaponType = ???
                else
                    set bj_EventDamageRanged = false
                    set bj_EventDamageAttackType = null
                    set bj_EventDamageDamageType = ???
                    set bj_EventDamageWeaponType = null
                endif
            endif
            set BOOL = IsValidDamageEvent()
            if BOOL == false then
                set bj_DamagingUnit = null
                set bj_DamagedUnit = null
                set bj_EventDamageAmount = 0.00
                set bj_EventDamageAttack = false
                set bj_EventDamageRanged = false
                set bj_EventDamageAttackType = null
                set bj_EventDamageDamageType = null
                set bj_EventDamageWeaponType = null
            endif

            return BOOL
        endif

        return false
    endfunction
02-20-2009, 08:45 AM#6
DioD
Data Based system cannot be public, no one will fill DB for 100 units.
02-20-2009, 09:05 AM#7
fX_
Yes, I considered that, but I have not thought of anything any other way. Suggested alternatives?
02-20-2009, 11:10 AM#8
Bobo_The_Kodo
Yes, normal attacks always have DAMAGE_TYPE_NORMAL; it means that the damage is reduced by the target's armor
02-20-2009, 12:32 PM#9
DioD
Write SLK script, there is one with Jass Helper as sample, but you need text output.
02-20-2009, 01:45 PM#10
fX_
I don't know anything about SLK. Is there a tutorial about it somewhere?
02-20-2009, 02:25 PM#11
xombie
Check out the JassHelperManual.
02-20-2009, 02:49 PM#12
Rising_Dusk
Quote:
Originally Posted by fX_
First, UnitDamageEx() by Rising_Dusk:
Sweet mother of God, I didn't write that.

Really, the only effects of damage type that matter are:
  • Considers armor in the damage.
  • Ignores spell damage resistance.
  • Considers ethereal in the damage.
For those, all you need to know is:
  • DAMAGE_TYPE_NORMAL considers armor, DAMAGE_TYPE_UNIVERSAL doesn't.
  • DAMAGE_TYPE_UNIVERSAL ignores spell resistance. (You can easily trigger spell resistance anyways, so no big deal)
  • Ethereal depends more on ATTACK_TYPE than DAMAGE_TYPE, so there is no combination of DTs and ATs that can 100% damage anything.
Refer here for more information (and what those other DTs and ATs do) if you really care. It really shouldn't matter for your purposes, though, you can generally accomplish whatever you want with NORMAL and UNIVERSAL.
02-21-2009, 09:44 AM#13
fX_
The practicality of such a script that you have in mind, is, I think, only about damage-dealing. But I want this script to be able to describe a damage event by its attributes - source, target, amount, isAttack, isRanged, attacktype, damagetype, and even weapontype - whatever their use may be:

Making the ground around the damaged unit shake if the attacktype of the damage imparted to it is ATTACK_TYPE_SIEGE, for example.

I intend for this script to manage the triggering of damage events - by facilitating it by simplifying the process (to only TriggerRegisterDamageEvent()) and by providing the attributes of damage events (mentioned above, which, as stated, may come to whatever use - whatever this use may be is irrelevant).

Here is the critical part as it is now, with problems commented:
Collapse JASS:
    private function ValidateDamageEvent takes nothing returns boolean
        local boolean BOOL_Valid

        if gBOOL_Monitor then
            set bj_DamagingUnit = GetEventDamageSource()
            set bj_DamagedUnit = GetTriggerUnit()
            set bj_EventDamageAmount = GetEventDamage()
            if bj_EventDamageAttackType == null then
                set bj_EventDamageAttack = false // IsEventDamageAttack() or IsEventDamageSpell() == false
                if bj_EventDamageAttack then
                    set bj_EventDamageRanged = IsUnitType(bj_DamagingUnit, UNIT_TYPE_RANGED_ATTACKER)
                    set bj_EventDamageAttackType = null //GetUnitAttackType(bj_DamagingUnit) - Some unit-type data index reference.
                    set bj_EventDamageDamageType = DAMAGE_TYPE_NORMAL
                    set bj_EventDamageWeaponType = null //GetUnitWeaponType(bj_DamagingUnit) - Some unit-type data index reference.
                else
                    set bj_EventDamageRanged = false
                    set bj_EventDamageAttackType = ATTACK_TYPE_NORMAL
                    set bj_EventDamageDamageType = DAMAGE_TYPE_MAGIC
                    set bj_EventDamageWeaponType = null
                endif
            endif

            set BOOL_Valid = IsDamageEventValid()

            if BOOL_Valid == false then
                set bj_DamagingUnit = GetEventDamageSource()
                set bj_DamagedUnit = GetTriggerUnit()
                set bj_EventDamageAmount = GetEventDamage()
                set bj_EventDamageAttack = false
                set bj_EventDamageRanged = false
                set bj_EventDamageAttackType = null
                set bj_EventDamageDamageType = null
                set bj_EventDamageWeaponType = null
            endif

            return BOOL_Valid
        endif

        return false
    endfunction

Any solutions?
02-21-2009, 02:02 PM#14
Bobo_The_Kodo
You don't really need weapontype; it just tells wc what sound to play from the damage; Like metal light slash vs metal armor = x sound ..
02-22-2009, 02:27 AM#15
fX_
I know. It may be useful in some way - this is not a concern. The concern is to describe damage events.