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

Damage Detector (Version 0.1)

This bundle is marked as useful / simple. Simplicity is bliss, low effort and/or may contain minor bugs.
This Damage Detector (or Detection) system will help you keep track of damage events in your map.

PROS:
1. Can distinguish how a damage was dealt (was it by an ATTACK or by a SPELL)
2. You will be able to turn on/off a damage detection for a unit
3. You can now hide the damage dealt w/ out hiding it to other triggers that relies on this system (This is dedicated for Spells/Items that calls a damage function when a damage event occurs/detected)
4. Retrieves 5 infos (Damage Amount, Damage Victim, Damage Source, Damage Method(ATTACK or SPELL), Check if the damage is hidden)

CONS:
1. If you want this system to distinguish the Damage Method (ATTACK or SPELL) you must
use its DD_DamageTarget function for your spells (or the damage events you want to be detected as a spell...)
2. The trigger recycle system destroys triggers so you cannot attach datas on to them...
3. You must manually register/unregister (by using the DD_DetectDamageFor function) a
unit in your map (Sorry but I did this so you can personalize filtering units yourself to save space for your map)

REQUIREMENTS:
1. UMSWE

CREDITS:
1. Weep

JASS:
library DamageDetector initializer DD_Init requires HandleWizard
//===========================================================================
// Damage Detector by Alain.Mark
//
// -How to Use-
//  DD_DetectDamageFor(unit U, boolean Yes)
//  -This will enable/disable the damage detection for "U".
//
//  DD_UseDetector(trigger TRG)
//  -This will include "TRG" to the list of triggers that are fired everytime
//   a damage event is detected or in other words use this if you want "TRG"
//   to use this system.
//
//  DD_SkipThis(trigger TRG, integer times)
//  -This will make "DD_RunQueue" skip "TRG" for "times" times. This function 
//   has special applications (prevent chain damage).
// 
//  DD_DamageTarget(unit Source, unit Target, real Damage, boolean Hide)
//  -This will cause "Source" to deal "Damage" to "Target". The damage will
//   be hidden if "Hide" is equal to true.
//
//  DD_GetDamageAmount()
//  -This will return the amount of damage dealt
//
//  DD_GetDamageVictim()
//  -This will return the damaged unit
//
//  DD_GetDamageSource
//  -This will return the damaging unit
//
//  DD_GetDamageMethod()
//  -This will return the damage method depending on the condtion. Use
//   DD_DM_ATTACK to check if the damage was dealt by an attack on the other
//   hand use DD_DM_SPELL to check if the damage was dealt by a spell.
//
//  NOTE: DD_DM_ATTACK is returned if the damage was NOT done using the the
//  DD_DamageTarget function. DD_DamageTarget will always have a DD_DM_SPELL
//  damage method. In other words if you want this system to distinguish if
//  damage is dealt by an attack or by a spell, DEAL DAMAGE BY USING THE
//  DD_DAMAGETARGET FUNCTION.
//
// -Credits- (Please give credits to the people below)
//  Weep (I used his GDD system as a base)
//
//===========================================================================
 globals // Obtainable informations are marked with //* at the end
	integer DD_Instances            =-1 
	integer DD_Held_Count           =-1
	integer DD_Detector_Users_Count =-1
	integer DD_Free_Triggers        =-1
    integer DD_HELD                 ='held'
    integer DD_DM_ATTACK            ='attk' //Put a random value here
    integer DD_DM_SPELL             ='spll' //Put a random value here
    integer DD_HIDDEN               ='hddn' //Put a random value here
	integer array DD_Free_Trigger_ID
    integer array DD_Skips
    integer array DD_Damage_Method
    boolean array DD_Hidden_Damage
	real array DD_Damage_Amount
	unit array DD_Damage_Victim
	unit array DD_Damage_Source
	trigger array DD_Trigger
	trigger array DD_Detector_User
 endglobals

//=========================================================================== 
 function DD_SkipThis takes trigger TRG, integer times returns nothing
    local integer ID=GetHandleData(TRG,"DD_Detector_Users_ID")
    set DD_Skips[ID]=times
 endfunction
 
//===========================================================================  
 function DD_RunQueue takes nothing returns nothing
    local integer nloops=0
	local integer nloopsmax=DD_Detector_Users_Count
    loop
		exitwhen nloops>nloopsmax
        if(DD_Skips[nloops]==0)then
            call TriggerExecute(DD_Detector_User[nloops])
        else
           set DD_Skips[nloops]=DD_Skips[nloops]-1
        endif
		set nloops=nloops+1
	endloop
	set DD_Instances=DD_Instances-1
 endfunction

//=========================================================================== 
 function DD_Queue takes nothing returns nothing
	set DD_Instances=DD_Instances+1
	set DD_Damage_Amount[DD_Instances]=GetEventDamage()
	set DD_Damage_Victim[DD_Instances]=GetTriggerUnit()
	set DD_Damage_Source[DD_Instances]=GetEventDamageSource()
    if(GetHandleData(DD_Damage_Source[DD_Instances],"DD_Damage_Method")!=DD_DM_SPELL)then
        set DD_Damage_Method[DD_Instances]=DD_DM_ATTACK
    else
        set DD_Damage_Method[DD_Instances]=DD_DM_SPELL
    endif
    if(GetHandleData(DD_Damage_Source[DD_Instances],"DD_Damage_Hidden")!=DD_HIDDEN)then
        set DD_Hidden_Damage[DD_Instances]=false
    else
        set DD_Hidden_Damage[DD_Instances]=true
    endif
	call DD_RunQueue()
 endfunction

//===========================================================================
//! textmacro Multiple takes NAME, RETURN_TYPE
 function DD_GetDamage$NAME$ takes nothing returns $RETURN_TYPE$
    return DD_Damage_$NAME$[DD_Instances]
 endfunction
//! endtextmacro

//! runtextmacro Multiple("Amount","real")
//! runtextmacro Multiple("Victim","unit")
//! runtextmacro Multiple("Source","unit")
//! runtextmacro Multiple("Method","integer")

//===========================================================================
 function DD_IsDamageHidden takes nothing returns boolean
    return DD_Hidden_Damage[DD_Instances]
 endfunction
 
//=========================================================================== 
 function DD_CreateTriggerFor takes unit U returns nothing
    local integer ID
    if(DD_Free_Triggers>=0)then
        set ID=DD_Free_Trigger_ID[DD_Free_Triggers]
        set DD_Free_Triggers=DD_Free_Triggers-1
	else
	    set DD_Held_Count=DD_Held_Count+1
		if(DD_Held_Count==8190)then
			call BJDebugMsg("|cffff0000WARNING: <YOUR MESSAGE HERE> its impossible for a real game to reach this anyway...")
            return
		else
		    set ID=DD_Held_Count
		    set DD_Trigger[ID]=CreateTrigger()
		endif
	endif
    call TriggerRegisterUnitEvent(DD_Trigger[ID],U,EVENT_UNIT_DAMAGED)
	call TriggerAddAction(DD_Trigger[ID],function DD_Queue)
	call SetHandleData(U,"DD_Recovery_ID",ID)
 endfunction
 
//===========================================================================
 function DD_DestroyTriggerFor takes unit U returns nothing
    local integer ID=GetHandleData(U,"DD_Recovery_ID")
	set DD_Free_Triggers=DD_Free_Triggers+1
	set DD_Free_Trigger_ID[DD_Free_Triggers]=ID
    call DestroyTrigger(DD_Trigger[ID])
    set DD_Trigger[ID]=CreateTrigger()
 endfunction

//=========================================================================== 
 function DD_DetectDamageFor takes unit U, boolean Yes returns nothing
   	if(Yes==true)then
        if(GetHandleData(U,"DD_Safety_Tag")==DD_HELD)then
            call BJDebugMsg("|cffff0000WARNING:|r Holding a unit twice is dangerous and might result to a crash!")
            return
        else
            call DD_CreateTriggerFor(U)
            call SetHandleData(U,"DD_Safety_Tag",DD_HELD)
        endif
   	else
      	call DD_DestroyTriggerFor(U)
        call FlushHandleData(U,"DD_Safety_TAG")
   	endif
 endfunction
 
//===========================================================================
 function DD_UseDetector takes trigger TRG returns nothing
    set DD_Detector_Users_Count=DD_Detector_Users_Count+1
	set DD_Detector_User[DD_Detector_Users_Count]=TRG
    call SetHandleData(TRG,"DD_Detector_Users_ID",DD_Detector_Users_Count)
 endfunction

//===========================================================================
 function DD_DamageTargetEx takes unit Source, unit Target, real Damage, attacktype Atk_type, damagetype Dmg_type, boolean Hide returns nothing
    call SetHandleData(Source,"DD_Damage_Method",DD_DM_SPELL)
    if(Hide==true)then
        call SetHandleData(Source,"DD_Damage_Hidden",DD_HIDDEN)
    endif
    call UnitDamageTarget(Source,Target,Damage,false,false,Atk_type,Dmg_type,WEAPON_TYPE_WHOKNOWS)
 endfunction

//=========================================================================== 
 function DD_DamageTarget takes unit Source, unit Target, real Damage, boolean Hide returns nothing
    call DD_DamageTargetEx(Source,Target,Damage,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,Hide)
 endfunction
 
//===========================================================================
 function DD_UseDetectorBulk takes nothing returns nothing
    //use this if you want to include triggers in bulk within one function call.
    call DD_UseDetector(gg_trg_Detect_Attack_Damage) //testmap only
    call DD_UseDetector(gg_trg_Detect_Spell_Damage) //testmap only
    call DD_UseDetector(gg_trg_Voltage_Wand) //testmap only
 endfunction
 
//=========================================================================== 
 function DD_Init takes nothing returns nothing
    call TimerStart(CreateTimer(),0.01,false,function DD_UseDetectorBulk)
 endfunction

//=========================================================================== 
endlibrary

Keywords:
system,damage detection,a damage detection system that can distinguish an attack or spell,damage detector,Alain.Mark, shield,orb effects
Contents

Just another Warcraft III map (Map)

Reviews
11:29, 4th May 2011 Bribe: You used prefixes while you should have used private What is HandleWizard? You didn't link to it This would be better if it had used a Unit Indexing system or the Table library You use multiple triggers to execute...

Moderator

M

Moderator

11:29, 4th May 2011
Bribe:

  1. You used prefixes while you should have used private
  2. What is HandleWizard? You didn't link to it
  3. This would be better if it had used a Unit Indexing system or the Table library
  4. You use multiple triggers to execute, when it could have used one trigger with multiple actions or, even better, conditions
  5. This could have just been 1, 2, 3, 4:
    JASS:
        integer DD_HELD                 ='held'
        integer DD_DM_ATTACK            ='attk' //Put a random value here
        integer DD_DM_SPELL             ='spll' //Put a random value here
        integer DD_HIDDEN               ='hddn' //Put a random value here
  6. It doesn't detect spell or attack differences with in-game damage
  7. Take advantage of the "constant" keyword
  8. Bad variable naming makes it hard to read your code (local variables and parameters, should never start with an uppercase letter)
  9. Safety checks should be only active while running in debug mode
  10. You integrated the testmap components with your library system, making it very diffult to figure out what to import and what to not import
  11. Been done by others with much better results.

Permanently rejected because of all of the above. Please see Nestharus' DamageEvent for a very developed implementation.
 
please post triggers...

Is this an implementation of Weep's DDS or a copy of it?

and what does this do that cannot be done using Weep's DDS or the DamageEvent libraries?

anyway, basing from the desc, the detection of whether the damage is ATTACK or SPELL is more like detecting if its ATTACK or trigger-dealt... which forces the player to use the predefined damaging method for all spells, which is bad (as you said, it was a cons...)... so basically, it doesn't actually distinguish spell damage, but rather, ATTACK or TRIGGER-DEALT... [on that point, the damage event extension by Nestharus is better to use]
 
Level 7
Joined
Apr 27, 2011
Messages
272
TO ADIKTUZ: I do not like calling a damage function everytime too...

DEFENSE MECHANISM ACTIVATE!:
BUT blizzard's native spells are dusty, limited, and maybe not leak-free. Thats why I did not bother making a way to detect the damage they deal. (but now Im thinking of a less harder way to detect the damage dealt by native blizzard spells)

I also found the damage event extension of Nestharus but I find it complicated for basic vJASSers like me...
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Really. But the code can be improved and become very useful.

er, no it can't

http://www.hiveworkshop.com/forums/jass-functions-413/extension-advanced-damage-event-187241/

lol... even if it's improved, the best it can be is what I just linked..

this has already been done, and it's been done better.

The lib I just linked actually takes advantage of how the wc3 engine distributes buffs on to units on different attack types to solve unit explosion bug for DDS libs similar to AdvDamageEvent (it can detect artillery type attacks as they act differently from all other attacks). There's still research going on for detecting whether an attack was ranged or melee.
 
Top