Name | Type | is_array | initial_value |
AbilityA | abilcode | No | |
AfterDamageEvent | real | No | |
AllowedElements | group | Yes | |
AOEDamageEvent | real | No | |
AOEDamageSource | unit | No | |
ARMOR_TYPE_ETHEREAL | integer | No | |
ARMOR_TYPE_FLESH | integer | No | |
ARMOR_TYPE_METAL | integer | No | |
ARMOR_TYPE_NONE | integer | No | |
ARMOR_TYPE_STONE | integer | No | |
ARMOR_TYPE_WOOD | integer | No | |
ArmorTypeDebugStr | string | Yes | |
ATTACK_TYPE_CHAOS | integer | No | |
ATTACK_TYPE_HERO | integer | No | |
ATTACK_TYPE_MAGIC | integer | No | |
ATTACK_TYPE_NORMAL | integer | No | |
ATTACK_TYPE_PIERCE | integer | No | |
ATTACK_TYPE_SIEGE | integer | No | |
ATTACK_TYPE_SPELLS | integer | No | |
AttackTypeDebugStr | string | Yes | |
BetOnPlayer | player | Yes | |
BettingUnit | unit | Yes | |
BetWinnersGroup | force | No | |
Binary | integer | No | |
BossLevelCounter | integer | No | |
BossLevelTierCounter | integer | No | |
BossSpawnType | trigger | Yes | |
BossSpawnTypeNumber | integer | No | |
CheckRange | real | No | |
ClassTypeA | string | No | |
ClassTypeB | string | No | |
CommonItems | itemcode | Yes | |
CommonItemsNumber | integer | No | |
CommonPermanents | itemcode | Yes | |
CommonPermanentsNumber | integer | No | |
CountCurrent | integer | No | |
CountHighest | integer | No | |
CountItemsOfType | integer | No | |
CountPlayer | player | No | |
CountPlayerNumber | integer | No | |
CountRound5 | integer | No | |
CountTouching | integer | No | |
CreepBuffTimer | timer | No | |
CreepBuffTimerWindow | timerdialog | No | |
CreepDifficultyMultiplier | integer | No | 1 |
CreepDifficultyReal | real | No | 1.00 |
CreepRound | integer | No | |
CreepRoundType | trigger | Yes | |
CreeproundTypeNumber | integer | No | 14 |
DAMAGE_TYPE_ACID | integer | No | |
DAMAGE_TYPE_COLD | integer | No | |
DAMAGE_TYPE_DEATH | integer | No | |
DAMAGE_TYPE_DEFENSIVE | integer | No | |
DAMAGE_TYPE_DEMOLITION | integer | No | |
DAMAGE_TYPE_DISEASE | integer | No | |
DAMAGE_TYPE_DIVINE | integer | No | |
DAMAGE_TYPE_ENHANCED | integer | No | |
DAMAGE_TYPE_FIRE | integer | No | |
DAMAGE_TYPE_FORCE | integer | No | |
DAMAGE_TYPE_LIGHTNING | integer | No | |
DAMAGE_TYPE_MAGIC | integer | No | |
DAMAGE_TYPE_MIND | integer | No | |
DAMAGE_TYPE_NORMAL | integer | No | |
DAMAGE_TYPE_PLANT | integer | No | |
DAMAGE_TYPE_POISON | integer | No | |
DAMAGE_TYPE_SHADOW_STRIKE | integer | No | |
DAMAGE_TYPE_SLOW_POISON | integer | No | |
DAMAGE_TYPE_SONIC | integer | No | |
DAMAGE_TYPE_SPIRIT_LINK | integer | No | |
DAMAGE_TYPE_UNIVERSAL | integer | No | |
DAMAGE_TYPE_UNKNOWN | integer | No | |
DamageEvent | real | No | |
DamageEventAmount | real | No | |
DamageEventAOE | integer | No | |
DamageEventAOEGroup | group | No | |
DamageEventArmorPierced | real | No | |
DamageEventArmorT | integer | No | |
DamageEventAttackT | integer | No | |
DamageEventDamageT | integer | No | |
DamageEventDefenseT | integer | No | |
DamageEventLevel | integer | No | |
DamageEventOverride | boolean | No | |
DamageEventPrevAmt | real | No | |
DamageEventSource | unit | No | |
DamageEventTarget | unit | No | |
DamageEventTrigger | trigger | No | |
DamageEventType | integer | No | |
DamageEventWeaponT | integer | No | |
DamageModifierEvent | real | No | |
DamageScalingUser | real | No | |
DamageScalingWC3 | real | No | |
DamageTypeBlocked | integer | No | |
DamageTypeCode | integer | No | |
DamageTypeCriticalStrike | integer | No | |
DamageTypeDebugStr | string | Yes | |
DamageTypeExplosive | integer | No | |
DamageTypeHeal | integer | No | |
DamageTypePure | integer | No | |
DamageTypePureExplosive | integer | No | |
DamageTypeReduced | integer | No | |
Day | integer | No | 0 |
DeathDifficulty | integer | No | 1 |
DeathLog | quest | No | |
DeathlogString | string | No | |
DeathMsgPoint | location | No | |
DeathText | string | Yes | |
DEFENSE_TYPE_DIVINE | integer | No | |
DEFENSE_TYPE_FORTIFIED | integer | No | |
DEFENSE_TYPE_HEAVY | integer | No | |
DEFENSE_TYPE_HERO | integer | No | |
DEFENSE_TYPE_LIGHT | integer | No | |
DEFENSE_TYPE_MEDIUM | integer | No | |
DEFENSE_TYPE_NORMAL | integer | No | |
DEFENSE_TYPE_UNARMORED | integer | No | |
DefenseTypeDebugStr | string | Yes | |
DuelInProgressRound | integer | No | |
DuelRound | integer | No | |
EnchantedBloodHealMod | real | No | |
EnhancedDamageTarget | unit | No | |
EquipIconsRarityType | hashtable | No | |
EventBOn | integer | No | |
EventCOn | integer | No | |
EventOriginPoint | location | No | |
EventTimerA | timer | No | |
EventTimerB | timer | No | |
EventTimerC | timer | No | |
EventType | trigger | Yes | |
EventTypeForTimer | string | No | |
EventTypeNumber | integer | No | |
FightRegion | rect | Yes | |
FinalRound | integer | No | |
FirstRound | integer | No | |
ForEachProjectile | integer | No | |
ForgedArtifactA | item | No | |
ForgedArtifactAType | itemcode | No | |
ForgedArtifactB | item | No | |
ForgedArtifactBType | itemcode | No | |
FortunaGold | integer | No | |
God | string | Yes | |
GroupA | group | No | |
GroupB | group | No | |
GroupChosen | force | No | |
GroupY | group | No | |
GroupZ | group | No | |
GuardToSpawnTypeInt | integer | No | |
GuardType | unitcode | Yes | |
GuardTypeNumber | integer | No | |
HasBlocked | integer | No | |
HasFinishedLevel | force | No | |
HealedUnit | unit | No | |
HealerUnit | unit | No | |
HelpString | string | Yes | |
HelpStringCurrentNumber | integer | No | |
HelpStringMax | integer | No | |
HelpStringText | texttag | No | |
HeroA | unit | No | |
HeroPicker | unit | Yes | |
HeroType | unitcode | Yes | |
HeroTypeNumber | integer | No | 13 |
HubText1 | texttag | No | |
HubText2 | texttag | No | |
InitialBuildingPoint | location | Yes | |
InstAbsolute | integer | No | |
InstanceCounter | integer | No | |
IntA | integer | No | |
IntB | integer | No | |
IntC | integer | No | |
IntD | integer | No | |
Integer_Inventory | integer | No | |
IntegerCountGodItems | integer | No | |
IntPlayerA | integer | No | |
IntPlayerB | integer | No | |
IntSummonCount | integer | No | |
IntToSummon | integer | No | |
IsBranded | integer | No | 0 |
IsDamageCode | boolean | No | |
IsDamageMelee | boolean | No | |
IsDamageRanged | boolean | No | |
IsDamageSpell | boolean | No | |
IsEnch | integer | No | 0 |
IsRare | integer | No | 0 |
IsTypeBuffed | integer | No | 0 |
IsUncommon | integer | No | 0 |
ItemA | item | No | |
ItemAbilityAgility | abilcode | Yes | |
ItemAbilityAgilityNumber | integer | No | 10 |
ItemAbilityArmor | abilcode | Yes | |
ItemAbilityAttackTypeBuff | abilcode | Yes | |
ItemAbilityBlock | abilcode | Yes | |
ItemAbilityBlockNumber | integer | No | 10 |
ItemAbilityBrand | abilcode | Yes | |
ItemAbilityBrandArt | abilcode | Yes | |
ItemAbilityBrandNumber | integer | No | 8 |
ItemAbilityDamage | abilcode | Yes | |
ItemAbilityDamageNumber10 | integer | No | 10 |
ItemAbilityEnch | abilcode | Yes | |
ItemAbilityEnchArt | abilcode | Yes | |
ItemAbilityEnchNumber | integer | No | 6 |
ItemAbilityIntelligence | abilcode | Yes | |
ItemAbilityIntelligenceNumber | integer | No | 10 |
ItemAbilityStrength | abilcode | Yes | |
ItemAbilityStrengthNumber | integer | No | 10 |
ItemAttackTypeBuffNumber | integer | No | 6 |
ItemAttackTypeName | abilcode | Yes | |
ItemAttackTypeNameNumber | integer | No | 6 |
ItemCount | integer | No | |
ItemTypeBuffNumber | integer | No | 3 |
ItemTypeBuffStat | trigger | Yes | |
ItemTypeCombine | itemcode | No | |
ItemTypeEquipmentNumber | integer | No | 6 |
ItemTypeEquipmentTrig | trigger | Yes | |
ItemTypeResult | itemcode | No | |
JailorType | trigger | Yes | |
JailorTypeNumber | integer | No | |
LethalDamageEvent | real | No | |
LethalDamageHP | real | No | |
LevelNumber | integer | No | 1 |
LevelText | texttag | No | |
Mark | unit | Yes | |
MeleeRound | integer | No | |
MeleeWinner | player | No | |
ModeAnkhCharges | integer | No | 8 |
ModeSetBinary | integer | No | 0 |
ModesTimer | timer | No | |
ModesTimerWindow | timerdialog | No | |
ModInt | integer | No | |
ModIntB | integer | No | |
ModIntY | integer | No | |
ModIntZ | integer | No | |
ModReal | real | No | |
ModRealB | real | No | |
ModUnit | unit | No | |
MonsterAbilityPrime | abilcode | Yes | |
MonsterAbilityPrimeNumber | integer | No | |
MonsterAbilityPrimeSet | integer | No | |
MonsterClass | abilcode | Yes | |
MonsterClassNumber | integer | No | |
MonsterClassSet | integer | No | |
NameClass | string | Yes | |
NameOfWorship | string | Yes | |
NameRace | string | Yes | |
NextDamageType | integer | No | |
NoProc | integer | No | |
Piety | integer | Yes | |
PlayerA | player | No | |
PlayerChannel | abilcode | Yes | |
PlayerClassTotalName | string | Yes | |
PlayerFaith | abilcode | Yes | |
PlayerHero | unit | Yes | UnitNull |
PlayerMeleeStrike | abilcode | Yes | |
PlayersAlive | force | No | |
PlayersInLevel | force | No | |
PlayersOutofLevel | force | No | |
PlayerSpell | abilcode | Yes | |
PlayerStatusBuffs | abilcode | Yes | |
PlayerThrow | abilcode | Yes | |
PlayerTrait | abilcode | Yes | |
PointA | location | No | |
PointB | location | No | |
PointC | location | No | |
PointD | location | No | |
PointE | location | No | |
PointGuardian | location | No | |
PointNagaZap | location | No | |
PointSummonMove | location | No | |
PotAmount | integer | No | |
PotDisplay | texttag | No | |
PotDisplayPoint | location | No | |
Pref1 | string | Yes | |
Pref2 | string | Yes | |
ProjIntA | integer | No | |
ProjIntB | integer | No | |
PVPForceEndTimer | timer | No | |
RandHeroType | unitcode | Yes | |
RandomGod | string | Yes | |
RandomGodNumber | integer | No | |
RangeBuildingTouching | real | No | 200.00 |
RarePermanenets | itemcode | Yes | |
RarePermanentsNumber | integer | No | |
RealA | real | No | |
RealHealAmount | real | No | |
RestartTimer | timer | No | |
RestRegion | rect | Yes | |
RestRound | integer | No | |
RewardFirst | integer | No | |
RockType | trigger | Yes | |
RockTypeNumber | integer | No | |
RoundEnd | integer | No | |
RoundStartTimer | timer | No | |
RoundStartWindpw | timerdialog | No | |
RoundWaitTimer | timer | No | |
RoundWaitWindow | timerdialog | No | |
SpawnType | trigger | Yes | |
SpawnTypeNumber | integer | No | |
StatScalingInt | integer | No | |
StringA | string | No | |
StringB | string | No | |
Suf1 | string | Yes | |
Suf2 | string | Yes | |
TempAGI | integer | Yes | |
TempArmor | real | Yes | |
TempAttackSpeed | real | Yes | |
TempClassA | string | No | |
TempClassB | string | No | |
TempDamage | integer | Yes | |
TempINT | integer | Yes | |
TempMoveSpeed | real | Yes | |
TempSTR | integer | Yes | |
TenLevelCounter | integer | No | |
TerrainPlaceRange | real | No | 300.00 |
TerrainType | terraintype | Yes | |
TerrainTypeNumber | integer | No | |
TextPointA | location | No | |
TextPointB | location | No | |
TimerZombie | timer | No | |
tooltipIntCalc | integer | No | |
TotalAbilities | integer | Yes | |
TotalPlayersInGame | force | No | |
TrapType | trigger | Yes | |
TrapTypeNumber | integer | No | |
TreeType | trigger | Yes | |
TreeTypeNumber | integer | No | |
TriesCheckNearby | integer | No | |
TrigGo | integer | No | |
UnitA | unit | No | |
UnitB | unit | No | |
UnitRandomromGroup | unit | No | |
UpdateTimer | timer | No | |
WallBuildTries | integer | No | |
WallCheckRange | real | No | 290.00 |
WallCheckTries | integer | No | |
WallPlaceRange | real | No | 120.00 |
WallSegmentWait | timer | No | |
WallTerrainType | terraintype | Yes | |
WallType | unitcode | Yes | |
WallTypeCurrentInt | integer | No | |
WallTypeNumber | integer | No | |
WEAPON_TYPE_AM_CHOP | integer | No | |
WEAPON_TYPE_CH_SLICE | integer | No | |
WEAPON_TYPE_CL_SLICE | integer | No | |
WEAPON_TYPE_CM_SLICE | integer | No | |
WEAPON_TYPE_MH_BASH | integer | No | |
WEAPON_TYPE_MH_CHOP | integer | No | |
WEAPON_TYPE_MH_SLICE | integer | No | |
WEAPON_TYPE_MH_STAB | integer | No | |
WEAPON_TYPE_ML_CHOP | integer | No | |
WEAPON_TYPE_ML_SLICE | integer | No | |
WEAPON_TYPE_MM_BASH | integer | No | |
WEAPON_TYPE_MM_CHOP | integer | No | |
WEAPON_TYPE_MM_SLICE | integer | No | |
WEAPON_TYPE_MM_STAB | integer | No | |
WEAPON_TYPE_NONE | integer | No | |
WEAPON_TYPE_RH_BASH | integer | No | |
WEAPON_TYPE_WH_BASH | integer | No | |
WEAPON_TYPE_WH_SLICE | integer | No | |
WEAPON_TYPE_WL_BASH | integer | No | |
WEAPON_TYPE_WL_SLICE | integer | No | |
WEAPON_TYPE_WL_STAB | integer | No | |
WEAPON_TYPE_WM_BASH | integer | No | |
WEAPON_TYPE_WM_SLICE | integer | No | |
WEAPON_TYPE_WM_STAB | integer | No | |
WeaponTypeDebugStr | string | Yes | |
WillPlaceBinary | integer | No |
//===========================================================================
// Damage Engine lets you detect, amplify, block or nullify damage. It even
// lets you detect if the damage was physical or from a spell. Just reference
// DamageEventAmount/Source/Target or the boolean IsDamageSpell, to get the
// necessary damage event data.
//
// - Detect damage (after it's been dealt to the unit): use the event "DamageEvent Equal to 1.00"
// - To change damage before it's dealt: use the event "DamageModifierEvent Equal to 1.00"
// - Detect spell damage: use the condition "IsDamageSpell Equal to True"
// - Detect zero-damage: use the event "DamageEvent Equal to 2.00"
//
// You can specify the DamageEventType before dealing triggered damage:
// - Set NextDamageType = DamageTypeWhatever
// - Unit - Cause...
//
// You can modify the DamageEventAmount and the DamageEventType from a "DamageModifierEvent Equal to 1.00" trigger.
// - If the amount is modified to negative, it will count as a heal.
// - If the amount is set to 0, no damage will be dealt.
//
// If you need to reference the original in-game damage, use the variable "DamageEventPrevAmt".
//
//===========================================================================
library DamageEngine initializer Init
globals
private boolean started = false
private integer recursion = -1
private boolean recursive = false
private boolean finished = false
private boolean purge = false
private timer ticker = CreateTimer()
private trigger trig = CreateTrigger()
private real previousAmount = 0.00 //Added to track the original modified damage pre-spirit Link
private real previousValue = 0.00 //Added to track the original pure damage amount of Spirit Link
private integer previousType = 0 //Track the type
private boolean previousCode = false //Was it caused by a trigger/script?
private boolean preDamage = false
private boolean holdClear = false
//Added in 5.2 to detect and modify armor and defense types from within the damage instance.
private real previousPierce = 0.00
private integer armorType = 0
private integer previousArmor = 0
private integer prevPreArmor = 0
private integer defenseType = 0
private integer previousDefense = 0
private integer prevPreDefense = 0
private unit array lastSource
private unit array lastTarget
private real array lastAmount
private attacktype array lastAttackT
private damagetype array lastDamageT
private weapontype array lastWeaponT
private trigger array lastTrig
private integer array lastType
endglobals
//GUI Vars:
/*
trigger udg_DamageEventTrigger //Different functionality from before in 5.1
boolean udg_DamageEventOverride
boolean udg_NextDamageType
boolean udg_DamageEventType
boolean udg_IsDamageCode //New in 5.1 as per request from chopinski
boolean udg_IsDamageSpell
boolean udg_IsDamageMelee //New in 5.0
boolean udg_IsDamageRanged //New in 5.0
unit udg_DamageEventSource
unit udg_DamageEventTarget
real udg_AOEDamageEvent
integer udg_DamageEventAOE
group udg_DamageEventAOEGroup
unit udg_AOEDamageSource //New in 5.0
integer udg_DamageEventLevel
unit udg_EnhancedDamageTarget
real udg_DamageModifierEvent
real udg_LethalDamageEvent //New in 5.0
real udg_DamageEvent
real udg_AfterDamageEvent
real udg_DamageEventAmount
real udg_DamageEventPrevAmt
real DamageEventArmorPierced
real udg_DamageScalingWC3
real udg_DamageScalingUser
real udg_LethalDamageHP //New in 5.0
integer udg_DamageEventAttackT //New in 5.0
integer udg_DamageEventDamageT //New in 5.0
integer udg_DamageEventWeaponT //New in 5.0
integer udg_DamageEventArmorT
integer udg_DamageEventDefenseT
*/
private function Error takes nothing returns nothing
local string s = "WARNING: Recursion error when dealing damage! Prior to dealing damage from within a DamageEvent response trigger, do this:\n"
set s = s + "Set DamageEventTrigger = (This Trigger)\n"
set s = s + "Unit - Cause <Source> to damage <Target>...\n\n"
set s = s + "Alternatively, just use the UNKNOWN damage type. It will skip recursive damage on its own without needing the \"Set\" line:\n"
set s = s + "Unit - Cause <Source> to damage <Target>, dealing <Amount> damage of attack type <Attack Type> and damage type Unknown"
call ClearTextMessages()
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0.00, 0.00, 999.00, s)
endfunction
private function OnAOEEnd takes nothing returns nothing
if udg_DamageEventAOE > 1 then
set udg_AOEDamageEvent = 0.00
set udg_AOEDamageEvent = 1.00
set udg_DamageEventAOE = 1
endif
set udg_DamageEventLevel = 1
set udg_EnhancedDamageTarget = null
set udg_AOEDamageSource = null
call GroupClear(udg_DamageEventAOEGroup)
endfunction
private function Finish takes nothing returns nothing
local integer i = -1
if finished then
set finished = false
if udg_DamageEventPrevAmt != 0.00 and udg_DamageEventDamageT != udg_DAMAGE_TYPE_UNKNOWN then
set recursive = true
set udg_AfterDamageEvent = 0.00
set udg_AfterDamageEvent = 1.00
set recursive = false
endif
if recursion > -1 and not holdClear and not purge then
set purge = true
//call BJDebugMsg("Clearing Recursion: " + I2S(recursion))
loop
exitwhen i >= recursion
set i = i + 1 //Need to loop bottom to top to make sure damage order is preserved.
set udg_NextDamageType = lastType[i]
if lastTrig[i] != null then
call DisableTrigger(lastTrig[i])//Since the damage is run sequentially now, rather than recursively, the system needs to disable the user's trigger for them.
endif
//call BJDebugMsg("Stacking on " + R2S(lastAmount[i]))
call UnitDamageTarget(lastSource[i], lastTarget[i], lastAmount[i], true, false, lastAttackT[i], lastDamageT[i], lastWeaponT[i])
call Finish()
endloop
loop
exitwhen i <= -1
if lastTrig[i] != null then
call EnableTrigger(lastTrig[i]) //Only re-enable recursive triggers AFTER all damage is dealt.
endif
set i = i - 1
endloop
//call BJDebugMsg("Cleared Recursion: " + I2S(recursion))
set recursion = -1 //Can only be set after all the damage has successfully ended.
set purge = false
endif
endif
endfunction
private function OnExpire takes nothing returns nothing
set started = false //The timer has expired. Flag off to allow it to be restarted when needed.
call Finish() //Wrap up any outstanding damage instance
call OnAOEEnd() //Reset things so they don't perpetuate for AoE/Level target detection
endfunction
private function CalibrateMR takes nothing returns nothing
set udg_IsDamageMelee = false
set udg_IsDamageRanged = false
set udg_IsDamageSpell = udg_DamageEventAttackT == 0 //In Patch 1.31, one can just check the attack type to find out if it's a spell.
if udg_DamageEventDamageT == udg_DAMAGE_TYPE_NORMAL and not udg_IsDamageSpell then //This damage type is the only one that can get reduced by armor.
set udg_IsDamageMelee = IsUnitType(udg_DamageEventSource, UNIT_TYPE_MELEE_ATTACKER)
set udg_IsDamageRanged = IsUnitType(udg_DamageEventSource, UNIT_TYPE_RANGED_ATTACKER)
if udg_IsDamageMelee and udg_IsDamageRanged then
set udg_IsDamageMelee = udg_DamageEventWeaponT > 0// Melee units play a sound when damaging
set udg_IsDamageRanged = not udg_IsDamageMelee // In the case where a unit is both ranged and melee, the ranged attack plays no sound.
endif // The Huntress has a melee sound for her ranged projectile, however it is only an issue
endif //if she also had a melee attack, because by default she is only UNIT_TYPE_RANGED_ATTACKER.
endfunction
//Load the event responses into the Pre-Damage Modification trigger.
private function OnPreDamage takes nothing returns boolean
local unit src = GetEventDamageSource()
local unit tgt = BlzGetEventDamageTarget()
local real amt = GetEventDamage()
local attacktype at = BlzGetEventAttackType()
local damagetype dt = BlzGetEventDamageType()
local weapontype wt = BlzGetEventWeaponType()
call Finish()
if udg_NextDamageType == 0 and (udg_DamageEventTrigger != null or recursive) then
set udg_NextDamageType = udg_DamageTypeCode
endif
if recursive then
if amt != 0.00 then
if recursion < 512 then //when this many events are run recursively from one damage instance, it's a safe bet that something has gone wrong.
set recursion = recursion + 1
//Store recursive damage into a queue from index "recursion" (0-15)
//This damage will be fired after the current damage instance has wrapped up its events.
//This damage can only be caused by triggers.
set lastAmount[recursion] = amt
set lastSource[recursion] = src
set lastTarget[recursion] = tgt
set lastAttackT[recursion] = at
set lastDamageT[recursion] = dt
set lastWeaponT[recursion] = wt
set lastTrig[recursion] = udg_DamageEventTrigger
set lastType[recursion] = udg_NextDamageType
else
//Delete or comment-out the next line to disable the in-game recursion crash warning
call Error()
endif
endif
set udg_NextDamageType = 0
set udg_DamageEventTrigger = null
call BlzSetEventDamage(0.00) //queue the damage instance instead of letting it run recursively
else
if not purge then
//Added 25 July 2017 to detect AOE damage or multiple single-target damage
if started then
if src != udg_AOEDamageSource then //Source has damaged more than once
call OnAOEEnd() //New damage source - unflag everything
set udg_AOEDamageSource = src
elseif tgt == udg_EnhancedDamageTarget then
set udg_DamageEventLevel= udg_DamageEventLevel + 1 //The number of times the same unit was hit.
elseif not IsUnitInGroup(tgt, udg_DamageEventAOEGroup) then
set udg_DamageEventAOE = udg_DamageEventAOE + 1 //Multiple targets hit by this source - flag as AOE
endif
if preDamage then
set preDamage = false
set previousAmount = udg_DamageEventAmount
set previousValue = udg_DamageEventPrevAmt //Store the actual pre-armor value.
set previousType = udg_DamageEventType //also store the damage type.
set previousCode = udg_IsDamageCode //store this as well.
set previousArmor = udg_DamageEventArmorT
set prevPreArmor = armorType
set previousDefense = udg_DamageEventDefenseT
set prevPreDefense = defenseType
set previousPierce = udg_DamageEventArmorPierced
set holdClear = true
endif
else
call TimerStart(ticker, 0.00, false, function OnExpire)
set started = true
set udg_AOEDamageSource = src
set udg_EnhancedDamageTarget= tgt
endif
call GroupAddUnit(udg_DamageEventAOEGroup, tgt)
endif
set udg_DamageEventType = udg_NextDamageType
if udg_NextDamageType != 0 then
set udg_DamageEventType = udg_NextDamageType
set udg_NextDamageType = 0
set udg_IsDamageCode = true //New in 5.1 - requested by chopinski to allow user to detect Code damage
set udg_DamageEventTrigger = null
endif
set udg_DamageEventOverride = dt == null or amt == 0.00 or udg_DamageEventType*udg_DamageEventType == 4 //Got rid of NextDamageOverride in 5.1 for simplicity
set udg_DamageEventPrevAmt = amt
set udg_DamageEventSource = src
set udg_DamageEventTarget = tgt
set udg_DamageEventAmount = amt
set udg_DamageEventAttackT = GetHandleId(at)
set udg_DamageEventDamageT = GetHandleId(dt)
set udg_DamageEventWeaponT = GetHandleId(wt)
call CalibrateMR() //Set Melee and Ranged settings.
set udg_DamageEventArmorT = BlzGetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_ARMOR_TYPE) //Introduced in Damage Engine 5.2.0.0
set udg_DamageEventDefenseT = BlzGetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_DEFENSE_TYPE)
set armorType = udg_DamageEventArmorT
set defenseType = udg_DamageEventDefenseT
set udg_DamageEventArmorPierced = 0.00
//Ignores event on various debuffs like Faerie Fire - alternatively,
//the user can exploit UNKNOWN damage type to avoid damage detection.
if not udg_DamageEventOverride then
set recursive = true
set udg_DamageModifierEvent = 0.00
set udg_DamageModifierEvent = 1.00 //I recommend using this for changing damage types or for when you need to do things that should override subsequent damage modification.
set udg_DamageEventOverride = udg_DamageEventOverride or udg_DamageEventType*udg_DamageEventType == 4
if not udg_DamageEventOverride then
set udg_DamageModifierEvent = 2.00 //This should involve damage calculation based on multiplication/percentages.
set udg_DamageModifierEvent = 3.00 //This should just be addition or subtraction at this point.
endif
set recursive = false
//All events have run and the pre-damage amount is finalized.
call BlzSetEventAttackType(ConvertAttackType(udg_DamageEventAttackT))
call BlzSetEventDamageType(ConvertDamageType(udg_DamageEventDamageT))
call BlzSetEventWeaponType(ConvertWeaponType(udg_DamageEventWeaponT))
if udg_DamageEventArmorPierced != 0.00 then
call BlzSetUnitArmor(udg_DamageEventTarget, BlzGetUnitArmor(udg_DamageEventTarget) - udg_DamageEventArmorPierced)
endif
if armorType != udg_DamageEventArmorT then
call BlzSetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_ARMOR_TYPE, udg_DamageEventArmorT) //Introduced in Damage Engine 5.2.0.0
endif
if defenseType != udg_DamageEventDefenseT then
call BlzSetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_DEFENSE_TYPE, udg_DamageEventDefenseT) //Introduced in Damage Engine 5.2.0.0
endif
call BlzSetEventDamage(udg_DamageEventAmount)
endif
set preDamage = true
//call BJDebugMsg("Ready to deal " + R2S(udg_DamageEventAmount))
endif
set src = null
set tgt = null
return false
endfunction
//The traditional on-damage response, where armor reduction has already been factored in.
private function OnDamage takes nothing returns boolean
local real r = GetEventDamage()
if recursive then
return false
endif
//call BJDebugMsg("Second event running")
if preDamage then
set preDamage = false //This should be the case in almost all circumstances
else
call Finish() //Wrap up the outstanding damage instance
set holdClear = false
//Unfortunately, Spirit Link and Thorns Aura/Spiked Carapace fire the DAMAGED event out of sequence with the DAMAGING event,
//so I have to re-generate a buncha stuff here.
set udg_DamageEventAmount = previousAmount
set udg_DamageEventPrevAmt = previousValue
set udg_DamageEventType = previousType
set udg_IsDamageCode = previousCode
set udg_DamageEventSource = GetEventDamageSource()
set udg_DamageEventTarget = BlzGetEventDamageTarget()
set udg_DamageEventAttackT = GetHandleId(BlzGetEventAttackType())
set udg_DamageEventDamageT = GetHandleId(BlzGetEventDamageType())
set udg_DamageEventWeaponT = GetHandleId(BlzGetEventWeaponType())
set udg_DamageEventArmorT = previousArmor
set udg_DamageEventDefenseT = previousDefense
set udg_DamageEventArmorPierced = previousPierce
set armorType = prevPreArmor
set defenseType = prevPreDefense
call CalibrateMR() //Apply melee/ranged settings once again.
endif
if udg_DamageEventArmorPierced != 0.00 then
call BlzSetUnitArmor(udg_DamageEventTarget, BlzGetUnitArmor(udg_DamageEventTarget) + udg_DamageEventArmorPierced)
endif
if armorType != udg_DamageEventArmorT then
call BlzSetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_ARMOR_TYPE, armorType) //revert changes made to the damage instance
endif
if defenseType != udg_DamageEventDefenseT then
call BlzSetUnitIntegerField(udg_DamageEventTarget, UNIT_IF_DEFENSE_TYPE, defenseType)
endif
set recursive = true
if udg_DamageEventPrevAmt == 0.00 then
set udg_DamageEvent = 0.00
set udg_DamageEvent = 2.00
else
if udg_DamageEventAmount != 0.00 and r != 0.00 then
set udg_DamageScalingWC3 = r / udg_DamageEventAmount
elseif udg_DamageEventAmount > 0.00 then
set udg_DamageScalingWC3 = 0.00
else
set udg_DamageScalingWC3 = 1.00
endif
set r = udg_DamageEventAmount
set udg_DamageScalingUser = r/udg_DamageEventPrevAmt
set udg_DamageEventAmount = r*udg_DamageScalingWC3
if udg_DamageEventAmount > 0.00 then
//This event is used for custom shields which have a limited hit point value
//The shield here kicks in after armor, so it acts like extra hit points.
set udg_DamageModifierEvent = 0.00
set udg_DamageModifierEvent = 4.00
set udg_LethalDamageHP = GetWidgetLife(udg_DamageEventTarget) - udg_DamageEventAmount
if udg_LethalDamageHP <= 0.405 then
set udg_LethalDamageEvent = 0.00 //New - added 10 May 2019 to detect and potentially prevent lethal damage. Instead of
set udg_LethalDamageEvent = 1.00 //modifying the damage, you need to modify LethalDamageHP instead (the final HP of the unit).
set udg_DamageEventAmount = GetWidgetLife(udg_DamageEventTarget) - udg_LethalDamageHP
if udg_DamageEventType < 0 and udg_LethalDamageHP <= 0.405 then
call SetUnitExploded(udg_DamageEventTarget, true) //Explosive damage types should blow up the target.
endif
endif
set udg_DamageScalingUser = udg_DamageEventAmount/(udg_DamageEventPrevAmt*udg_DamageScalingWC3)
endif
call BlzSetEventDamage(udg_DamageEventAmount) //Apply the final damage amount.
//if recursion > -1 then
//call BJDebugMsg("Dealing " + R2S(udg_DamageEventAmount))
//endif
if udg_DamageEventDamageT != udg_DAMAGE_TYPE_UNKNOWN then
set udg_DamageEvent = 0.00
set udg_DamageEvent = 1.00
endif
endif
set recursive = false
set finished = true
if udg_DamageEventAmount <= 0.00 then
call Finish()
endif
return false
endfunction
//===========================================================================
private function Init takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_DAMAGED) //Thanks to this I no longer have to create an event for every unit in the map.
call TriggerAddCondition(trig, Filter(function OnDamage))
set trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_DAMAGING) //The new 1.31 event which fires before damage.
call TriggerAddCondition(trig, Filter(function OnPreDamage))
endfunction
public function DebugStr takes nothing returns nothing
set udg_AttackTypeDebugStr[0] = "SPELLS" //ATTACK_TYPE_NORMAL in JASS
set udg_AttackTypeDebugStr[1] = "NORMAL" //ATTACK_TYPE_MELEE in JASS
set udg_AttackTypeDebugStr[2] = "PIERCE"
set udg_AttackTypeDebugStr[3] = "SIEGE"
set udg_AttackTypeDebugStr[4] = "MAGIC"
set udg_AttackTypeDebugStr[5] = "CHAOS"
set udg_AttackTypeDebugStr[6] = "HERO"
set udg_DamageTypeDebugStr[0] = "UNKNOWN"
set udg_DamageTypeDebugStr[4] = "NORMAL"
set udg_DamageTypeDebugStr[5] = "ENHANCED"
set udg_DamageTypeDebugStr[8] = "FIRE"
set udg_DamageTypeDebugStr[9] = "COLD"
set udg_DamageTypeDebugStr[10] = "LIGHTNING"
set udg_DamageTypeDebugStr[11] = "POISON"
set udg_DamageTypeDebugStr[12] = "DISEASE"
set udg_DamageTypeDebugStr[13] = "DIVINE"
set udg_DamageTypeDebugStr[14] = "MAGIC"
set udg_DamageTypeDebugStr[15] = "SONIC"
set udg_DamageTypeDebugStr[16] = "ACID"
set udg_DamageTypeDebugStr[17] = "FORCE"
set udg_DamageTypeDebugStr[18] = "DEATH"
set udg_DamageTypeDebugStr[19] = "MIND"
set udg_DamageTypeDebugStr[20] = "PLANT"
set udg_DamageTypeDebugStr[21] = "DEFENSIVE"
set udg_DamageTypeDebugStr[22] = "DEMOLITION"
set udg_DamageTypeDebugStr[23] = "SLOW_POISON"
set udg_DamageTypeDebugStr[24] = "SPIRIT_LINK"
set udg_DamageTypeDebugStr[25] = "SHADOW_STRIKE"
set udg_DamageTypeDebugStr[26] = "UNIVERSAL"
set udg_WeaponTypeDebugStr[0] = "NONE" //WEAPON_TYPE_WHOKNOWS in JASS
set udg_WeaponTypeDebugStr[1] = "METAL_LIGHT_CHOP"
set udg_WeaponTypeDebugStr[2] = "METAL_MEDIUM_CHOP"
set udg_WeaponTypeDebugStr[3] = "METAL_HEAVY_CHOP"
set udg_WeaponTypeDebugStr[4] = "METAL_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[5] = "METAL_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[6] = "METAL_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[7] = "METAL_MEDIUM_BASH"
set udg_WeaponTypeDebugStr[8] = "METAL_HEAVY_BASH"
set udg_WeaponTypeDebugStr[9] = "METAL_MEDIUM_STAB"
set udg_WeaponTypeDebugStr[10] = "METAL_HEAVY_STAB"
set udg_WeaponTypeDebugStr[11] = "WOOD_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[12] = "WOOD_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[13] = "WOOD_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[14] = "WOOD_LIGHT_BASH"
set udg_WeaponTypeDebugStr[15] = "WOOD_MEDIUM_BASH"
set udg_WeaponTypeDebugStr[16] = "WOOD_HEAVY_BASH"
set udg_WeaponTypeDebugStr[17] = "WOOD_LIGHT_STAB"
set udg_WeaponTypeDebugStr[18] = "WOOD_MEDIUM_STAB"
set udg_WeaponTypeDebugStr[19] = "CLAW_LIGHT_SLICE"
set udg_WeaponTypeDebugStr[20] = "CLAW_MEDIUM_SLICE"
set udg_WeaponTypeDebugStr[21] = "CLAW_HEAVY_SLICE"
set udg_WeaponTypeDebugStr[22] = "AXE_MEDIUM_CHOP"
set udg_WeaponTypeDebugStr[23] = "ROCK_HEAVY_BASH"
set udg_DefenseTypeDebugStr[0] = "LIGHT"
set udg_DefenseTypeDebugStr[1] = "MEDIUM"
set udg_DefenseTypeDebugStr[2] = "HEAVY"
set udg_DefenseTypeDebugStr[3] = "FORTIFIED"
set udg_DefenseTypeDebugStr[4] = "NORMAL"
set udg_DefenseTypeDebugStr[5] = "HERO"
set udg_DefenseTypeDebugStr[6] = "DIVINE"
set udg_DefenseTypeDebugStr[7] = "UNARMORED"
set udg_ArmorTypeDebugStr[0] = "NONE"
set udg_ArmorTypeDebugStr[1] = "FLESH"
set udg_ArmorTypeDebugStr[2] = "METAL"
set udg_ArmorTypeDebugStr[3] = "WOOD"
set udg_ArmorTypeDebugStr[4] = "ETHEREAL"
set udg_ArmorTypeDebugStr[5] = "STONE"
endfunction
//This function exists mainly to make it easier to switch from another DDS, like PDD.
function UnitDamageTargetEx takes unit src, unit tgt, real amt, boolean a, boolean r, attacktype at, damagetype dt, weapontype wt returns boolean
if udg_DamageEventTrigger == null then
set udg_DamageEventTrigger = GetTriggeringTrigger() //Directly access the user's calling trigger
endif
if udg_NextDamageType == 0 then
set udg_NextDamageType = udg_DamageTypeCode
endif
call UnitDamageTarget(src, tgt, amt, a, r, at, dt, wt)
return recursive
endfunction
endlibrary