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