• 🏆 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 Engine 5.A.0.0

This bundle is marked as director's cut. It exceeds all expectations and excels in every regard.
Damage Engine

Three GUI Damage systems for the community of The Hive,
Seven vJass Damage systems for the JASS-heads on their pedestals high,
Nine competing Damage systems, doomed to die,
One for Bribe on his dark throne
In the Land of the Hive where the Workshop lies.
One Damage Engine to rule them all, One Damage Engine to find them,
One Damage Engine to bring them all and in cross-compatibility unite them.


Whether you're looking for a simple DDS (Damage Detection System), need to modify damage or even if you want a complex network of damage pre-and post-processing, this resource is for you. Damage Engine is the most adapted DDS in existence to take full advantage of the new damage detection natives, and is constantly evaluated and scrutinized by both the community and myself for performance improvements, bug fixes and new features alike.

What started with humble beginnings to bring a Unit Indexer-based version of DDS to GUI users to improve on the previous standard (at the time it was Weep's GDDS) would eventually evolve to incorporate other aspects of damage systems out there. @looking_for_help had identified an extremely useful technique with negative spell resistance being used to detect spell damage, and for a time his Physical Damage Detection system became the new standard. It wouldn't be until much later when Damage Engine would resurface and use the same technique in order to be more useful for the community.

Fast forward to 2020, and you'll find not only that cross-compatibility with Weep's and LFH's systems are incorporated, but the most popular DDS systems in existence - even vJass ones - are fully supported via stripped-down API wrappers. All of the functionality of prior DDS systems has been infused into Damage Engine 5.7, and as such the transition to a "one size fits all" DDS is complete. I hope you find this to be useful, and I also hope that it will help you in developing your map to be more dynamic what than you had previously thought possible.

Features

Legacy Code & Requirements

How it works

How to install/upgrade

Video Guides

FAQs

Thanks


  • Damage Type, Attack Type, Weapon Type, Armor Type and Defense Type detection and modification to alter/understand the fundamentals of WarCraft 3's damage processing;
  • Access to the view and change the damage amount before and/or after reduction by armor, armor type and shields.
  • Fully cross-compatible with every major DDS - vJass and GUI alike.
  • Correctly distribute/negate Spirit Link damage.
  • Differentiate between Ranged, Melee, Spell or other types of attack.
  • Does not require any Object Editor data nor Unit Indexer.
  • As of 5.4, it is now completely recursion-proof.
  • Other features:
    • Damage Blocking, reducing, amplifying and/or conversion to healing
    • Does not require you to know nor use Jass NewGen Pack nor any custom script
    • Custom DamageType association available to be set before and/or during damage event
    • Detect when multiple targets were hit simultaneously via DamageEventAOE > 1.
    • Detect when the same unit was hit simultaneously by the same source via DamageEventLevel > 1.
  • Detect damage: use the event "OnDamageEventEqual to <any value>". You have access to the following variables for reference:
    • DamageEventSource - the unit dealing the damage
    • DamageEventTarget - the unit receiving the damage
    • DamageEventAmount - the amount of damage the unit will receive
    • DamageEventPrevAmt - the amount of damage prior to being modified by the game engine.
    • DamageEventAttackT - the attack type (Chaos, Spells, Pierce, etc.)
    • DamageEventDamageT - the damage type - for comprehensive info, click here.
    • DamageEventWeaponT - the weapon type determines if an attack plays some kind of sound on attack (ie. Metal Heavy Bash). It is always NONE for spells and almost always NONE for ranged attacks.
    • DamageEventArmorT - the armor type (Flesh, Stone, Ethereal, etc.)
    • DamageEventDefenseT - the defense type (Hero, Fortified, Unarmored, etc.)
    • DamageEventArmorPierced - if DAMAGE_TYPE_NORMAL, how much armor was set to be ignored by the user.
    • IsDamageSpell, IsDamageRanged, IsDamageMelee - determine the source category of damage dealt.
    • IsDamageCode - Determine if the damage was dealt natively or by the user. This can give incorrect readings if the user has not identified to Damage Engine that it is code damage. Therefore I recommend setting NextDamageType prior to dealing damage.
    • DamageEventType - An integer identifier that can be referenced by you for whatever extra differentiation you need. You can also create your own special damage types and add them to the definitions in the Damage Event Config trigger. If you the unit should explode on death by that damage, use a damage type integer less than 0. If you want the damage to ignore all modifications, use DamageTypePure.
  • To change damage before it's processed by the WarCraft 3 engine: use the event "PreDamageEvent Becomes Equal to <any value>". Whether you just want to use one monolithic trigger for all damage modification like I do in the demo map, or use the different modifier events here, is up to you.
  • To interact with damage after it's been factored for armor and resistances, use "ArmorDamageEvent Becomes Equal to <any value>". This is typically useful for custom shields. If you fully block or absorb DamageEventAmount (setting it to 0 or less), this event doesn't run.
  • To set the DamageEventType before dealing triggered Damage, use:
    - Set NextDamageType = DamageTypeWhatever
    - Unit - Cause...
  • You can modify the following variables from a "PreDamageEvent" trigger:
    • DamageEventAmount
    • DamageEventAttackT/DamageT/WeaponT/ArmorT/DefenseT
    • DamageEventArmorPierced
    • DamageEventType
    • DamageEventOverride - You can set this if you want to remind yourself not to modify the damage further. If you use the UNKOWN damage type from a Unit - Damage Target native or set "NextDamageType = DamageTypePure" before that function, damage modification is skipped.
  • To catch a unit the moment before it would die from damage, use LethalDamageEvent Becomes Equal to 1.00. Instead of modifying the DamageEventAmount here, modify LethalDamageHP to let the system know how much life to keep the unit alive with. Or you can just reference that LethalDamageHP value in order to know how much "overkill" damage was dealt.
  • To catch a unit as soon as the damage is applied against its Hit Points, use AfterDamageEvent Equal to 1.00.
  • Usage of the "<Event> becomes EQUAL to <value>" can be extrapolated as per the below:
    • EQUAL works as it always has - will run for any damage.
    • NOT EQUAL only runs for code damage.
    • LESS THAN only runs for damage from attacks but not coded attacks.
    • LESS THAN OR EQUAL only runs for melee attacks but not coded attacks.
    • GREATER THAN OR EQUAL only runs for ranged attacks but not coded attacks.
    • GREATER THAN only runs for Spell damage but not coded spell damage.

  • Damage Engine 5 and higher requires the latest Warcraft 3 patch (currently 1.32).
  • For people who did not update their game to Reforged / have not updated to Reforged yet. Alternatively, adding the below JASS script to the top of the DamageEngine library SHOULD enable it to work too:

    JASS:
    function BlzGetEventIsAttack takes nothing returns boolean
         return BlzGetEventDamageType() == DAMAGE_TYPE_NORMAL
    endfunction
  • I have created a Pastebin for all information pertaining to Damage Engine 3.8, including the link to download it, via: Damage Engine 3.8.0.0 | HIVE.
  • As of 20 June 2020, JNGP users who are still on WarCraft 3 1.26 can benefit from Damage Engine 3A, which integrates many of the design choices added in various stages of Damage Engine 5. This is a special update which only requires the JASS script be replaced (no new GUI variables added). Can be found here: Damage Engine 3A.0.0.0 and 3.8.0.0 | HIVE

1
Unit attacks or casts a spell. The pure damage is assessed at this point - damage dice, evasion, critical strike. There is currently no event to affect or modify these at source.
→ →
2
The projectile or weapon hits the target unit
→ →
3
EVENT_UNIT_DAMAGING is fired before any modifications to the damage are made.
→ ↓
↓ ←
6
User changes to DamageEventAmount and/or to DamageEventDamageT/AttackT/WeaponT are saved into the WC3 engine.
← ←
5
If any recursive damage is detected from any of those events, it is postponed and the current damage will continue first.
← ←
4
Damage Engine deploys the PreDamageEvent
7
WarCraft 3 processes the user damage.
→ →
8
WarCraft 3 then distributes the user damage into Spirit Link (before armor)
→ →
9
WarCraft 3 runs any interrupting events, such as spirit link or defensive damage like Thorns Aura
→ ↓
↓ ←
12
The EVENT_UNIT_DAMAGED event runs. This is the original event we have always had access to. Damage Engine will either keep using the original variables from the DAMAGING event, or if there was Spirit Link/defensive damage it will freshly retrieve the event values from WC3 and only retain DamageEventPrevAmt.
← ←
11
Once any potential recursive WarCraft 3 damage is processed, the armor/mana shield modifications to the damage are performed.
← ←
10
If such events such as Spirit Link were detected, they fire their own EVENT_UNIT_DAMAGING & EVENT_UNIT_DAMAGED, and DamageEngine processes it along the way for the user.
13
If the damage is above zero, ArmorDamageEvent will run. If any recursive damage is detected, it is postponed.
→ →
14
The user can make modification to the damage here with the after-damage amount.
→ →
15
The user can access DamageEventPrevAmount if they want to know the damage amount before user changes/WarCraft 3 changes.
→ ↓
↓ ←
18
The user can specify whether or not to change LethalDamageHP in order to stop the unit from dying.
← ←
17
If the damage is still above zero, check if the damage is lethal. If so, run LethalDamageEvent 1.00. If any recursive damage is detected, it is postponed.
← ←
16
If the user wants the value that DamageEngine used to have with DamageEventPrevAmt (after WarCraft 3 processing but before user changes) they multiply DamageEventPrevAmt x DamageScalingWC3.
19
Once all modification is done, run OnDamageEvent. If any recursive damage is detected, it is postponed.
→ →
20
After a new damage instance is detected, or the 0.00 timer expires, run AfterDamageEvent. If any recursive damage is detected, it is postponed.
→ →
21
Run all potential recursive Unit - Damage Target function calls in chronological order (first in, first out).

How to install Damage Engine:
  1. Use WarCraft 3 Version 1.32
  2. If you're upgrading from 3.8 or prior, please delete the entire "Damage Engine" category from your map.
  3. Copy & Paste the Damage Engine category from the attached map to your own map.
How do I upgrade to the latest Damage Engine?
- Depending on the complexity, you'll either need to re-copy the Damage Engine category or just the Damage Engine script. Generally, you can use this as a guide:

  • Damage Engine _._._.x - only requires copying of the JASS script
  • Damage Engine _._.x._ - generally only needs copying of the JASS script, but read the patch notes in case there are changes you may want to make to your own code in order to utilize the changes.
  • Damage Engine _.x._._ - delete your current Damage Engine category or manually add the missing variables to your Variable Editor, and update your JASS script.
  • Damage Engine x._._._ - this occurs very infrequently. Typically requires changes to the way Damage Engine needs to be installed and used.

Notes about upgrading from Damage Engine 4.0 or prior:
  • Revert any custom Object Editor changes made (such as Life Drain reversal, Spell Damage Reduction inversion, etc).
  • You can safely delete the custom spells "Spell Damage Detection" and "Cheat Death Ability"
  • You can delete the Unit Indexer trigger if you do not use it or would prefer to use a different indexer.
  • You should delete any "Mana Shield fix" or "Finger of Death fix" you may have imported, as well as revert any Object Editor data that was required to make it work, as these are no longer needed.
  • !!!DEPRECATED FEATURE!!! As of 5.4, do not bother to take any recursive damage mitigation - Damage Engine will now handle all of that for you!
  • !!!DEPRECATED FEATURE!!! Do not use "ClearDamageEvent" - it does nothing. Just delete it.
  • !!!DEPRECATED FEATURE!!! Do not use "NextDamageOverride" - set NextDamageType = DamageTypePure instead.
  • !!!CHANGED FEATURE!!! If the system detects code damage and the user did not specify it as any particular DamageEvenType, the system will assign it DamageTypeCode automatically.
  • !!!CHANGED FEATURE!!! DamageModifierEvent 1.00-3.00 now run prior to armor reduction. This enables the user to modify the damage before armor and resistance changes are applied - also before Mana Shield and Anti-Magic shell kick in, so no more need for special triggers.


  • Q: Why am I getting a bunch of 'trigger was disabled' errors when I save my map?
  • A: This issue is not unique to Damage Engine, but to all vJass resources. Blizzard has taken the very confusing decision to make JassHelper 'disabled' by default, meaning that every new map that uses a vJass resource has to manually enable JassHelper. Please see this thread if you want to know where to find the Enable JassHelper option.
    .
  • Q: How can I detect when a unit gets damaged?
  • A: Create a trigger with the event: "Game - Value of Real Variable <DamageEvent> becomes Equal to 1.00".
    • Use the following custom variables to reference the event responses:
      • DamageEventSource - the unit dealing the damage
      • DamageEventTarget - the unit getting damaged
      • DamageEventAmount - how much damage is being dealt
      • DamageEventAttackT - which attack type was used by DamageEventSource to damage DamageEventTarget
      • DamageEventDamageT - which damage type was used to damage the target (ie. UNIVERSAL for ultimate damage, or NORMAL for damage that gets reduced by armor).
      • DamageEventDefenseT - which defense type does the target unit have (ie. Hero, Fortified, Unarmored).
      • DamageEventArmorT - which armor type does the target unit have (ie. Flesh, Ethereal, Stone).
      • DamageEventPrevAmt - what the value of the damage was before being modified by armor, ethereal/item bonuses or user changes.
        .
  • Q: How do I modify the damage that is dealt to a unit?
  • A: Create a trigger with the event: "Game - Value of Real Variable <PreDamageEvent> becomes Equal to <any value>".
    • You can change the following variables to affect the damage that will be dealt:
      • DamageEventAmount - how much damage will be dealt (before armor reductions)
      • DamageEventAttackT - which attack type will be used by DamageEventSource to damage DamageEventTarget
      • DamageEventDamageT - which damage type will be used to damage the target.
      • DamageEventDefenseT - which defense type should the target unit have during this attack.
      • DamageEventArmorT - which armor type should the target unit have during this attack.
      • DamageEventArmorPierced - how much armor value to ignore when dealing this damage (applies to DAMAGE_TYPE_NORMAL only, otherwise all armor is ignored).
        .

  • Q: How do I deal Pure damage to a unit (bypassing armor/skipping user modification)?
  • A: Use the following actions:
    • Set NextDamageType = DamageTypePure
    • Unit - Cause Source to damage Target for Amount using attack type Spells and damage type Universal
      .

  • Q: How do I protect against recursive damage?
  • A: Damage Engine 5.4 and above is completely recursion-proof, using vJass hooks to detect registered Damage Event triggers.
    .

  • Q: I've been using <insert Damage system here>. Can I use those with Damage Engine?
  • A: Better - Damage Engine has integrated cross-compatibility with all other approved Damage systems and even the major ones from outside of Hiveworkhop.
    .

  • Q: Can I cause an attack to 'Miss' its target?
  • A: Kind of. Ranged attacks will still explode on the target, and on-hit effects will still apply, but you can do the following:
    • Use the event "PreDamageEvent becomes Equal to 1.00"
    • Use the following actions:
      • Set DamageEventAmount = 0.00
      • Set DamageEventArmorT = ARMOR_TYPE_NONE
      • Set DamageEventWeaponT = WEAPON_TYPE_NONE
    • Setting the weapon type and armor type to none like the above will stop any on-hit sounds from playing. When the Peasant attacks in the demo map, this is the trick I'm using. Instead of saying "MISSED!" I have the Floating Text saying "FAIL!" because - again - it's not exactly a "miss".

Thank you to Blizzard for continuing to work on this amazing game to give us awesome new natives that have the best possible control over incoming damage. Damage Engine brings that power to GUI. Also, a very special thank you to @KILLCIDE for getting me motivated to start up the 5.0 project in the first place.

Thank you to the users of this system who have helped me mold this project into the stable, powerful form it is in today!

For versions 3.8 and prior:

Thank you @looking_for_help for finding the spell damage detection method used in Damage Engine 3 - it was the greatest find since the undefend bug.

Thanks to Jesus4Lyf and @Nestharus for building the inspiration that originally led me to create DamageEngine.

Thank you Wietlol and looking_for_help for challenging me on this project to integrate solutions to problems I had not been made aware of, such as the importance of an After-Damage Event.

Thanks to @Spellbound for several crucial bug reports.


Damage Engine Config

Damage Engine vJass

Damage Engine Lua

Changelog


  • Damage Engine Config
    • Events
      • Map initialization
      • Game - DamageModifierEvent becomes Greater than 0.00
      • Game - LethalDamageEvent becomes Less than or equal to 0.00
      • Game - DamageEvent becomes Not equal to 0.00
      • Game - AfterDamageEvent becomes Less than 0.00
      • Game - AOEDamageEvent becomes Greater than or equal to 0.00
      • Game - SourceDamageEvent becomes Equal to 0.00
      • Game - PreDamageEvent becomes Equal to 0.00
      • Game - ArmorDamageEvent becomes Equal to 0.00
      • Game - ZeroDamageEvent becomes Equal to 0.00
    • Conditions
    • Actions
      • -------- You can add extra classifications here if you want to differentiate between your triggered damage --------
      • -------- Use DamageTypeExplosive (or any negative value damage type) if you want a unit killed by that damage to explode --------
      • -------- - --------
      • -------- The pre-defined type Code might be set by Damage Engine if Unit - Damage Target is detected and the user didn't define a type of their own. --------
      • -------- "Pure" is especially important because it overrides both the Damage Engine as well as WarCraft 3 damage modification. --------
      • -------- I therefore gave the user "Explosive Pure" in case one wants to combine the functionality of the two. --------
      • -------- - --------
      • Set VariableSet DamageTypePureExplosive = -2
      • Set VariableSet DamageTypeExplosive = -1
      • Set VariableSet DamageTypeCode = 1
      • Set VariableSet DamageTypePure = 2
      • -------- - --------
      • Set VariableSet DamageTypeHeal = 3
      • Set VariableSet DamageTypeBlocked = 4
      • Set VariableSet DamageTypeReduced = 5
      • -------- - --------
      • Set VariableSet DamageTypeCriticalStrike = 6
      • -------- - --------
      • Custom script: call DamageEngine_DebugStr()

BribeFromTheHive/DamageEngine

Lua 1.0.2.3 - Fixed to match adjustment made in vJass version 5.4.2.3.
Lua 1.0.2.2 - Fixed to match adjustment made in vJass version 5.4.2.2.
Lua 1.0.2.1 - Fixed to match adjustment made in vJass version 5.4.2.1.
Lua 1.0.2.0 - Added support for Lua Fast Triggers ([Lua] Ridiculously Fast Triggers). Fixed an issue where the AfterDamageEvent wasn't always timed the correct way like it was in the JASS verion.
Lua 1.0.1.0 - Fixed encapsulation issue and recursion issue with DamageEngine_inception. Now hooks UnitDamageTarget.
Lua 1.0.0.0 - Release based on Damage Engine 5.4.2.0

5.9.0.0 - Added the following clearer event names to make things less confusing for new users:
  • PreDamageEvent - can be used in place of DamageModifierEvent pre-armor modification
  • ArmorDamageEvent - can be used in place of DamageModifierEvent post-armor modification
  • OnDamageEvent - can be used instead of a non-zero DamageEvent
  • ZeroDamageEvent - can be used instead of a zero damage DamageEvent
  • SourceDamageEvent - runs at the same time as AOEDamageEvent, but doesn't need to hit multiple units.
Added "DamageFilterRunChance" - odds for the trigger to BE run (works inversely to DamageFilterFailChance).
Shortened the Configuration trigger so that it focuses primarily on what the user can modify.
Organized all variables into categories to help users better understand what does what.
Installation or updating from a previous version will require re-copying the entire Damage Engine folder.
Updated the demo map's text tag production to include a new custom update for ArcingTextTag, thanks to @Ugabunda and @Kusanagi Kuro.
Side note - the Demo Map's triggers have been heavily cleaned up and will now no longer cause crashes when being imported into a new map.
5.8.0.0 -
  • Added a new functionality to the AOEDamageEvent, which allows it to fire even when only one unit is hit, if the AOEDamageEvent is registered as "Not Equal" instead of "Equal to". This is useful in a very specific scenario where an AfterDamageEvent may not be able to be relied upon to properly deallocate data from a running instance that needs to be able to function when multiple units are hit, but also needs to not fail when only one unit is hit.
  • Added additional filters for GUI users to avoid using trigger conditions in even more scenarios:
    • DamageFilterSource/TargetI (has item)
    • DamageFilterSource/TargetA (has ability)
    • DamageFilterSource/TargetC (has a certain classification, like hero or Tauren)
    • DamageFilterFailChance - odds for the trigger to not be run (ideal for critical strike or evasion)
  • Provided a way for GUI to un-register a Damage Event by setting "RemoveDamageEvent" to true from within their trigger's actions.
  • Moved the CreateTimer/CreateTrigger/CreateGroup calls that had been included in the globals block down to the onInit block as per request of @Ricola3D
  • Minor performance improvements thanks to @BLOKKADE
5.7.1.2 - Fixed an issue with armor penetration sometimes bugging out.
5.7.1.1 - Fixed an issue with the eventFilter not retaining its value during an AOE event. Fixed an issue with eventFilter when USE_MELEE_RANGE was set to false. Both issues reported by @lolreported
5.7.1.0 -
I have fixed several potential points of failure reported by multiple users that stopped Damage Engine from working for the rest of the game. In any case there should no longer be ANY SITUATION where Damage Engine just "stops working", even in ways I can't predict. The most likely issue was with DamageScalingWC3/User having possible 0-division errors.​
Fixed the "configured" issue reported by @lolreported where manual configuration didn't work unless the damage and attack type checks were initialized tto -1.​
In addition to these fixed bugs, I have added several more static ifs so that advanced users have more control over getting rid of features they might not care about.​

5.7.0.3 - Fixed the issue reported by @KitsuneTailsPrower wherein the DamageInterface extension wasn't working. This needed to be fixed both in the Damage Engine source as well as the DamageInterface plugin itself.
5.7.0.2 - Fixed the issue reported by @Wazzz where the armor reduction wasn't taken into consideration. Actually there was a much bigger flaw that I had overlooked that was prompting this.
5.7.0.1 - Improved the logic of the 0 damage event.
5.7.0.0:

  • Usage of the "DamageEvent becomes EQUAL to 1.00" now can be extrapolated further than ever before:
    • EQUAL works as it always has.
    • NOT EQUAL only runs for code damage.
    • LESS THAN only runs for damage from attacks.
    • LESS THAN OR EQUAL only runs for melee attacks.
    • GREATER THAN OR EQUAL only runs for ranged attacks.
    • GREATER THAN only runs for Spell damage.
  • Fully adapted Damage Engine to work with every other major DDS
  • Rewrote the internal script to use vJass structs: Damage and DamageTrigger.
  • Changed some of the vJass API. You can find the API listed in the Damage Engine trigger. Notably:
    • I removed UnitDamageTargetEx. You can replace this with Damage.apply.
      • The reason for this change is because of cross-compatibility. Rising Dusk's IDDS uses a different set of parameters for this function, so I removed it from my library to allow this to work seamlessly.
    • TriggerRegisterDamageEvent -> TriggerRegisterDamageEngine
    • RegisterDamageEvent -> RegisterDamageEngine
      • The reason for the above two changes is, like for UnitDamageTargetEx, because Rising Dusk's IDDS uses them. I don't want to make the same mistake I did with Table's API and preferred to walk back my API choices before things got out of hand again.
  • Various performance tweaks, bug fixes and re-commenting of variables.
  • Recursive damage is now processed more intelligently and possibly be more performance-friendly.
  • Adapted the cross-compatibility libraries for Weep and LFH's systems to use textmacros to insert themselves into Damage Engine (this might have been in the 5.6 update, but these two updates were both tailored to achieve similar goals).
5.6.2.0 - Fixed a bug with Damage modification and laid groundwork for a bunch of optional vJass compatibility addons.
5.6.1.0 - Patchwork on Melee/Ranged detection, recursion tracking. Also added the ability to modify damage from a DamageEvent to make it easier on beginners.
5.6.0.1 - Fixed an issue where the DamageEventType for recursive damage that used NextDamageType would always default to DamageTypeCode.
5.6.0.0
Rewrote a significant amount of the internal code so that struct and GUI syntax both work - and are synchronized with each other. vJass-exclusive users can disable the GUI synchronization if they don't use any GUI damage events in their maps.​
Four new variables must be added to your variable editor:​
  • boolean NextDamageIsAttack
  • boolean NextDamageIsMelee
  • boolean NextDamageIsRanged
  • integer NextDamageWeaponT
Struct syntax should not need too much introduction - Damage.index is the triggering event ID, and the syntax is Damage.index.amount/source/target/etc. To initialize a JASS damage event, use:​
JASS:
function RegisterDamageEvent takes code c, string eventName, real value returns nothing
The string is simplified: "Modifier", "" (for simple DamageEvent), "After", "Lethal", "AOE"​
Finally, a neat QOL improvement is that I have assigned weight to each of the events. When registering an event, you can include numbers different than 1, 2, 3 or 4 (for modification) or just the plain "1" for the others. Now you can set your own sequencing and use 1.5, 3.14 or even -1 to give an even more extreme priority to something. Lower numbers run first, higher ones last.​
5.5.0.0 - Added support for the new native BlzGetEventIsAttack via "IsDamageAttack". Also updated the Config trigger to make importing a bit easier
5.4.2.3 - Fixed a mis-flag of the IsDamageSpell value when not being actual spell damage.
5.4.2.2 - Actually fixed the Cold Arrows issue (division by 0.00001 or something ...somehow... either way, it is fixed).
5.4.2.1 - A fix which should hopefully quell the recent reports of damage events failing in complex situations involving Cold Arrows.
5.4.2.0 - A ton of fixes to repair the issues plaguing Sunken City and anyone else who might be pushing this engine well beyond what I imagined it would be used for. Also added a couple of variables intended to be used to ricochet damage: CONVERTED_ATTACK_TYPE and CONVERTED_DAMAGE_TYPE. Check the demo map for how they can be used in a Unit - Damage Target action.
5.4.1.0 - The "Inception" update. Advanced users can interact with Damage Engine via custom script to set DamageEvent_inception = true to allow their damage to potentially go recursive (to a fixed extent).
5.4.0.1 - Hotfixed that modifiers 2 and 3 weren't running.
5.4.0.0 - By using an innovative approach of hooking TriggerRegisterVariableEvent, I've permanently eliminated all risks of recursion in the engine.
5.3.0.1 - Fixed unexpected behavior with DamageTypePure when it is affected by Anti-Magic Shell or Mana Shield. DamageTypePure now no longer ignores DamageScalingWC3.
5.3.0.0 - Fixed an issue with AfterDamageEvent sometimes being delayed. Added DamageScalingUser to track the ratio of user modified damage, as well as DamageEventArmorPierced which allows the user to define how much armor to ignore when working with DAMAGE_TYPE_NORMAL.
5.2.0.1 - Fixed an issue where with the final unit in a Spirit Link chain or the retaliating damage of Thorns/Carapace would not deploy an AfterDamageEvent. Also fixed an issue where AfterDamageEvent would still fire from DAMAGE_TYPE_UNKNOWN if it was greater than 0. Simply copy over the JASS from this post in order to update your own implementation.
5.2.0.0

  • Now features DamageEventArmorT and DamageEventDefenseT, which pull from the target unit's Object Editor data in order to allow you more complete access to detect and even MODIFY those defenses. Changes must be made in a DamageModifierEvent, and they are reverted as soon as armor is calculated.
  • Re-introduced AfterDamageEvent, which is the moment after the unit's life is changed, but before any recursive damage has run.

5.1.3.1 - Bug fixes and performance improvements. No, really. Fixed an issue with the DAMAGED event running even though it was turned off (who would've guessed that?)
5.1.3.0 - Engine re-tooling to improve accuracy and get Spirit Link/Defensive damage out of hardcoded mode - it will now work even in circumstances I haven't tested for (in case those weren't the only issues). Also fixed the Is Unit Moving resource.
5.1.2.1 - Fixed an issue with Spiked Carapace and Thorns Aura where the melee attacker would not get recorded correctly. This required the same fix as I needed to apply for the initial target in a spirit link chain.
5.1.2.0 - Tweaked recursion and fixed a few bugs. Re-introduced the zero damage event now that patch 1.31.1 brought it back.
5.1.1.1 - Minor tweak to Spirit Link in rare situation.
5.1.1.0 - Fixed issues related to Spirit Link. Now works intuitively as expected.
5.1.0.0 - Crazy improvements - check out the details in "How to upgrade from Damage Engine 4.0 or earlier" and "How to use Damage Engine 5.1"
5.0.0.0 - Oh man. Where do I even start?
  • You can now set/compare DamageEventDamageT, DamageEventAttackT or DamageEventWeaponT
  • No longer needs Unit Indexer nor any custom Object Editor data nor modifications.
  • Requires WarCraft 3 1.31 or higher.
  • Changed vanilla JASS code to vJass to clean up a lot of things such as making certain variables private.
  • Look for more details in "How to upgrade from Damage Engine 4.0 or earlier"

4.0.0.0 - Never officially released, but was the first iteration which used SetEventDamage.
For 3.8.0.0 and prior, see: Damage Engine 3.8.0.0 | HIVE


Cross-Compatibility:

BribeFromTheHive/DamageEngine

Keywords:unit indexer, damage detection, damage event, weep, nestharus, looking_for_help, EVENT_PLAYER_UNIT_DAMAGED, damage engine, spell, physical, EVENT_PLAYER_UNIT_DAMAGED, attacktype, damagetype, weapontype, armortype, defensetype, BlzSetEventDamage
Previews
Contents

Damage Engine Demo Map (Map)

Lua Damage Engine 2.0.0.0 (Map)

Reviews
23:20, 11th Jan 2015, BPower Criticism: On the one hand Damage Engine offers extremely high utility to every spell, system and map maker independent of the coding style ( GUI, JASS, vJass, .... ) on the other hand it's very easy to import and...

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
It probably doesn't really matter as it's just an extra BlzSetUnitArmor call that's made but in the setArmor function where it modifies the armor the "if pierce != 0.00" is always true if there is no armor piercing, because in that case it sets pierce to -0.00, which apparently is different than 0.00.
View attachment 395576
lol, that’s a weird behavior. I’ll add it to the backlog of stuff.
 
I have done some testing, and it does seem to enter calculation before armor type.
Code:
(DamageEventPrevAmt - Hardened Skin reduction)*Armor type*Armor value reduction = DamageEventAmount
(checked using DamageEventModifier 4.00, not detected by DamageEventModifier before 4.00)
So if you mean Hardened Skin is calculated before armor, you are correct.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I have done some testing, and it does seem to enter calculation before armor type.
Code:
(DamageEventPrevAmt - Hardened Skin reduction)*Armor type*Armor value reduction = DamageEventAmount
(checked using DamageEventModifier 4.00, not detected by DamageEventModifier before 4.00)
So if you mean Hardened Skin is calculated before armor, you are correct.
The real question now is whether Mana Shield applies before or afterward. I would think before.
 
Level 2
Joined
Aug 10, 2021
Messages
7
I have a problem. My unit has 'missile splash' attack. When I use DamageModifierEvent event, the trigger will run for all units in the AOE, so it runs multiple times just in one attack. I just want it to only run once a attack. Then I tried AOEDamageEvent event and it run once each attack as expected but I cannot modify the damage. How can I modify the damage of an AOE attack?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I have a problem. My unit has 'missile splash' attack. When I use DamageModifierEvent event, the trigger will run for all units in the AOE, so it runs multiple times just in one attack. I just want it to only run once a attack. Then I tried AOEDamageEvent event and it run once each attack as expected but I cannot modify the damage. How can I modify the damage of an AOE attack?
Just go back to your original trigger with a normal DamageModifierEvent and check if DamageEventAOE is equal to 1.
 
Level 2
Joined
Aug 10, 2021
Messages
7
Just go back to your original trigger with a normal DamageModifierEvent and check if DamageEventAOE is equal to 1.
I checked DamageEventAOE equal to 1 as you said and the trigger run once each attack, but it only modify the damage dealt to the main target of the attack, not the damage dealt to other units in AOE. To be more specific, my unit (has 'missile splash' attack) has an ability that every 3rd attack it will deal x2 damage of damage type Universal and restore 100hp. This is my trigger:

  • Critical Shoot
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
      • DamageEventAOE Equal to 1
    • Actions
      • Set X = (X + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • X Equal to 3
        • Then - Actions
          • Set DamageEventAmount = (DamageEventAmount x 2.00)
          • Set DamageEventDamageT = DAMAGE_TYPE_UNIVERSAL
          • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + 100.00)
          • Set X = 0
        • Else - Actions

It works for the main target of the attack and the HP is restored correctly, but the other units in AOE still got the unmodified damage. I want the damage to be modified for all units in AOE.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I'm aware of that, what I really mean to ask is if it's possible to make a damage event ONLY ignore modification from abilities on the target, but still calculate armor reduction.
Yes, but you’ll need to calculate the armor reduction yourself.

percentage = (armor * modifier) / ( 1 + armor * modifier ). Modifier is usually 0.06.

The above gets you the percentage of reduction based on armor quantity.

If you need armor types as well, the you can use this method:

 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I checked DamageEventAOE equal to 1 as you said and the trigger run once each attack, but it only modify the damage dealt to the main target of the attack, not the damage dealt to other units in AOE. To be more specific, my unit (has 'missile splash' attack) has an ability that every 3rd attack it will deal x2 damage of damage type Universal and restore 100hp. This is my trigger:

  • Critical Shoot
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
    • Actions
      • DamageEventAOE Equal to 1
  • [/QUOTE]
  • [QUOTE="googery, post: 3526080, member: 297688"]
  • Set X = (X + 1)
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • X Equal to 3
      • Then - Actions
        • Set DamageEventAmount = (DamageEventAmount x 2.00)
        • Set DamageEventDamageT = DAMAGE_TYPE_UNIVERSAL
        • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + 100.00)
        • Set X = 0
      • Else - Actions

It works for the main target of the attack and the HP is restored correctly, but the other units in AOE still got the unmodified damage. I want the damage to be modified for all units in AOE.
I checked DamageEventAOE equal to 1 as you said and the trigger run once each attack, but it only modify the damage dealt to the main target of the attack, not the damage dealt to other units in AOE. To be more specific, my unit (has 'missile splash' attack) has an ability that every 3rd attack it will deal x2 damage of damage type Universal and restore 100hp. This is my trigger:

  • Critical Shoot
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
      • DamageEventAOE Equal to 1
    • Actions
      • Set X = (X + 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • X Equal to 3
        • Then - Actions
          • Set DamageEventAmount = (DamageEventAmount x 2.00)
          • Set DamageEventDamageT = DAMAGE_TYPE_UNIVERSAL
          • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + 100.00)
          • Set X = 0
        • Else - Actions

It works for the main target of the attack and the HP is restored correctly, but the other units in AOE still got the unmodified damage. I want the damage to be modified for all units in AOE.
This trigger can be modified with the following flow:

A) Move the condition “DamageEventAOE” to a new if/else block at the top of the Actions.

B) Move Set X = X + 1 into A’s “then” actions

C) Move Set X = 0 into a separate trigger with the event AOEDamageEvent and the condition “X Equal to or greater than 3”.

The flow will then work exactly as you wish it to, affecting all units hit by that splash instance.
 
Level 2
Joined
Aug 10, 2021
Messages
7
Thank you Bribe, it works fine now.
  • Critical Shoot 1
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DamageEventAOE Equal to 1
        • Then - Actions
          • Set X = (X + 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • X Equal to 3
        • Then - Actions
          • Set DamageEventAmount = (DamageEventAmount x 2.00)
          • Set DamageEventDamageT = DAMAGE_TYPE_UNIVERSAL
        • Else - Actions
  • Critical Shoot 2
    • Events
      • Game - AOEDamageEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
      • X Greater than or equal to 3
    • Actions
      • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + 100.00)
      • Set X = 0
Edit: I think the EnhancedDamageTarget unit refer to the main target of the attack in AOEDamageEvent.
 
Last edited:
Level 2
Joined
Aug 10, 2021
Messages
7
There is a problem with the 2nd trigger in my comment above (the AOEDamageEvent trigger). It is: that trigger won't run when the attack only damage one unit. That means the event AOEDamageEvent won't run if there is only one unit damaged by the attack, even though the attack is splash. How do I fix this?
 
Level 2
Joined
Aug 10, 2021
Messages
7
Have you tried making a duplicate trigger but the condition AOEDamageEvent being 0?
You mean condition DamageEventAOE? Well I just tested that condition:
Game - Display to (All players) the text: (String(DamageEventAOE))

  • In DamageModifierEvent: If there are 3 units got damaged by the attack then the DamageEventAOE integer can be 1, 2 or 3 at the same time; if only 1 unit then DamageEventAOE will only be 1, so I think it cannot be 0.
  • In AOEDamageEvent: DamageEventAOE is equal to the number of units damaged by the attack, except when there is only one unit => DamageEventAOE returns nothing.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
You mean condition DamageEventAOE? Well I just tested that condition:
Game - Display to (All players) the text: (String(DamageEventAOE))

  • In DamageModifierEvent: If there are 3 units got damaged by the attack then the DamageEventAOE integer can be 1, 2 or 3 at the same time; if only 1 unit then DamageEventAOE will only be 1, so I think it cannot be 0.
  • In AOEDamageEvent: DamageEventAOE is equal to the number of units damaged by the attack, except when there is only one unit => DamageEventAOE returns nothing.
DamageEngine can’t detect if damage is AOE unless the damage does hit multiple units.

Using AfterDamageEvent doesn’t work unless the damage only hits one unit, and would fail to affect all the units as you wanted it to.

Therefore, it seems like the only way to make this work for you is if I add an extra event modifier that runs the AOE damage event regardless of if the damage had hit multiple units. Something like “Less Than” instead of “Equal to”. This is worth doing, if it would help you. I will try to get it done this weekend if so.

Basically, you’d have that trigger turned off at all times, and just allow it to be turned on when X is 3, then the trigger turns itself back off once it runs.
 
Level 2
Joined
Aug 10, 2021
Messages
7
I think I found the way! I figured out how the integer DamageEventAOE works from my post above, so I tried to modify my triggers according to it.
In the first trigger, I replace the condition "X equal to 3" with "X equal to 3 or X equal to 0". In the second trigger, I replace "AOEDamageEvent" back to "DamageEvent". I tested and I think it works fine, for both case only one unit and more than one unit hit by the splash attack.
  • Critical Shoot 1
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DamageEventAOE Equal to 1
        • Then - Actions
          • Set X = (X + 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • X Equal to 3
              • X Equal to 0
        • Then - Actions
          • Set DamageEventAmount = (DamageEventAmount x 2.00)
          • Set DamageEventDamageT = DAMAGE_TYPE_UNIVERSAL
        • Else - Actions
  • Critical Shoot 2
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • (Unit-type of DamageEventSource) Equal to My Unit
      • IsDamageRanged Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource)) Equal to True
      • X Greater than or equal to 3
    • Actions
      • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + 100.00)
      • Set X = 0
I guess that the chronological order of these triggers in one attack should be:
  1. Projectile hit the main target of the attack (the 1st unit)
  2. The 1st unit is going to take damage => Run the first trigger actions. DamageEventAOE returns 1 => Add 1 to X => X now has a value of 1, 2 or 3. If X equal to 3, modify the damage deal to this unit.
  3. The 1st unit takes damage. If X equal to 3, run the second trigger actions => Add HP to the attacker and Set X to 0.

    If there are more than one unit in AOE, it will continue as below:
  4. The 2nd unit is going to take damage => Run the first trigger actions. DamageEventAOE returns 2. At this time, X is having a value of 1, 2 or 0. If X equal to 0, modify the damage deal to this unit.
  5. The 2nd unit takes damage.
  6. The 3rd unit... similar to the 2nd unit, but the DamageEventAOE returns 3...
I'm using DamageEngine 5.4.2.3, my patch is 1.31. I don't have Reforged so I think I can't use the update versions.

Edit: condition ''DamageEventAOE equal to 1'' not needed in second trigger
 
Last edited:
Level 4
Joined
May 18, 2018
Messages
38
Its possible to check from which exact spell damage came from? For example if unit was damage with finger of death of firebolt?
You'd have to make some edits to DamageEngine to make it support that.

In my map what I do is whenever a hero casts a spell it actually uses a dummy unit to cast the real spell, this dummy unit has a variable linked to the spell its casting and then I can just use damage engine to detect the damage source to check what spell the damage is from.

You could also do it by making all spell damage coded and then just adding a damage source ability variable to damage engine and setting that right before you deal damage, like the udg_nextblablabla variable already in the library.
 
Level 8
Joined
Aug 5, 2014
Messages
194
You'd have to make some edits to DamageEngine to make it support that.

In my map what I do is whenever a hero casts a spell it actually uses a dummy unit to cast the real spell, this dummy unit has a variable linked to the spell its casting and then I can just use damage engine to detect the damage source to check what spell the damage is from.

You could also do it by making all spell damage coded and then just adding a damage source ability variable to damage engine and setting that right before you deal damage, like the udg_nextblablabla variable already in the library.
Well i actually use first one with dummy units, but i was curious if it possible to attach trigger to exact spell instead of attaching it to a unit, in cases where i dont want to use dummy cast for simple passives like envenomed weapon.
 
Level 8
Joined
Aug 5, 2014
Messages
194
How to reference DamageEventSource/DamageEventTarget in GethandleID functions for hashtable? You see, i cant reference unit from global variables which DamageEventSource/DamageEventTarget are.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
By making 3 events:
  • <Event> Less than 1 = Only runs for damage from attacks
  • <Event> Greater than 1 = Only runs for damage from abilities (I assume passive abilities like Thorns Aura, Spiked Carapace count toward this?)
  • <Event> Not equal to 1 = Only runs for damage from triggers (UnitDamageTarget etc.)
This will practically cover all possibilities of damage in WC3, am I correct? It's much handier than running one <Event> Equal to 1 and have to filter for attack/ability/code damage with "ifs".
Is it correct to also assume that this works the same for real values !=1 (e.g. DamageModifierEvent less than 4.00 if I want to catch only attack damage after calculation has been applied)

Yes, that would cover every major branch. Those three events would never occur for the same damage instance.

Hello !

I'd like to report a really minor side effect of this library: because Damage Engine uses "CreateTrigger", "CreateGroup" and "CreateTimer" in a "globals" scope, you cannot hook those functions.

Indeed, on build you will have an build error saying "h__CreateTimer does not exist, do you mean CreateTrigger ?" (for example).
It is because, if you look at the war3map.j displayed in the error window, the "globals" definition appears first in the file, and only several lines below appears the hook definitions.

I think a simple "fix" would be to declare the variables with null value, and then initialize them with CreateTimer/Trigger/Group in the "onInit".

Sincerely,

Ricola3D

Are you using vJass or Lua? I'm just wondering why anyone would want to be hooking those functions. If it helps you, I can do it, but I am mostly curious as to why.

It probably doesn't really matter as it's just an extra BlzSetUnitArmor call that's made but in the setArmor function where it modifies the armor the "if pierce != 0.00" is always true if there is no armor piercing, because in that case it sets pierce to -0.00, which apparently is different than 0.00.
View attachment 395576

I have a version of 5.8 I'm testing that has now implemented this fix.

I think I found the way! I figured out how the integer DamageEventAOE works from my post above, so I tried to modify my triggers according to it.
In the first trigger, I replace the condition "X equal to 3" with "X equal to 3 or X equal to 0". In the second trigger, I replace "AOEDamageEvent" back to "DamageEvent". I tested and I think it works fine, for both case only one unit and more than one unit hit by the splash attack.

I guess that the chronological order of these triggers in one attack should be:
  1. Projectile hit the main target of the attack (the 1st unit)
  2. The 1st unit is going to take damage => Run the first trigger actions. DamageEventAOE returns 1 => Add 1 to X => X now has a value of 1, 2 or 3. If X equal to 3, modify the damage deal to this unit.
  3. The 1st unit takes damage. If X equal to 3, run the second trigger actions => Add HP to the attacker and Set X to 0.

    If there are more than one unit in AOE, it will continue as below:
  4. The 2nd unit is going to take damage => Run the first trigger actions. DamageEventAOE returns 2. At this time, X is having a value of 1, 2 or 0. If X equal to 0, modify the damage deal to this unit.
  5. The 2nd unit takes damage.
  6. The 3rd unit... similar to the 2nd unit, but the DamageEventAOE returns 3...
I'm using DamageEngine 5.4.2.3, my patch is 1.31. I don't have Reforged so I think I can't use the update versions.

Edit: condition ''DamageEventAOE equal to 1'' not needed in second trigger

1. You can use the latest version of Damage Engine with patch 1.31 with just the small edit of adding in your own custom BlzGetEventIsAttack, as shown in the "Requirements" section.

2. The actual, correct method is still for me to update Damage Engine. The next update (5.8) has a working method that makes "AOEDamageEvent equal to 0.00" react as if it doesn't matter whether it's AOE or not. This solves several problems by removing any dependency that users may have for a 0.00 second timer, which is actually the correct solution to the problem you presented.

Well i actually use first one with dummy units, but i was curious if it possible to attach trigger to exact spell instead of attaching it to a unit, in cases where i dont want to use dummy cast for simple passives like envenomed weapon.

Checking the damage type is the best option for you here. You can reference the following link to differentiate between many different types of spells per group. As long as your unit doesn't have more than one ability per damage type, then you can determine which spell was cast that dealt the damage: REPO in progress - mapping damage types to their abilities

How to reference DamageEventSource/DamageEventTarget in GethandleID functions for hashtable? You see, i cant reference unit from global variables which DamageEventSource/DamageEventTarget are.

You have to store every piece of information separately in that hashtable, or use arrays with indexing to store each of them separately. Damage Engine does not have a way to retain such information for longer than an instant. It is up to the user to determine what - if any - data needs to be stored for longer, and then use their own method of preference to do so.
 
Level 8
Joined
Aug 5, 2014
Messages
194
Checking the damage type is the best option for you here. You can reference the following link to differentiate between many different types of spells per group. As long as your unit doesn't have more than one ability per damage type, then you can determine which spell was cast that dealt the damage: REPO in progress - mapping damage types to their abilities
Well for spells which i use without dummy cast i figure out exact same decision, to replace exact damage type which spell uses, but i thought that there is intended way which i overlooked.
You have to store every piece of information separately in that hashtable, or use arrays with indexing to store each of them separately. Damage Engine does not have a way to retain such information for longer than an instant. It is up to the user to determine what - if any - data needs to be stored for longer, and then use their own method of preference to do so.
I know that damage engine can store information in global varible only for a bref moment, but there is no way to like:
"DamageEventModifier becomes 1.0

Save real as 1 of GetHandleID(DamageEventTarget)"
?

So i dont need Damage engine to actually store information, i only need a way to reference unit in a moment when its become a DamageEventTarget.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I know that damage engine can store information in global varible only for a bref moment, but there is no way to like:
"DamageEventModifier becomes 1.0

Save real as 1 of GetHandleID(DamageEventTarget)"
?

So i dont need Damage engine to actually store information, i only need a way to reference unit in a moment when its become a DamageEventTarget.

That works just fine. How do your triggers currently look?
 
Level 8
Joined
Aug 5, 2014
Messages
194
That works just fine. How do your triggers currently look?
First of all i must point out that i use 1.31 pre reforged version so maybe there is can be differences.
In my map i try to implement custom resistances, which stored in hash-table, each unit has its own resistance stored in such way:

Save Real(resistance amount) as 1(number of resistance) of Key*(EnteringUnit) in last created hashtable

*Where key is GetHandleID, and it is getting ID of unit to which i apply resistance

As you can see its a simple operation and i have no troubles with it.

When i try to load resistance Value:

Event:
DamageModifierEvent becomes 1.0

Actions: (simple example)
DamageEventAmount = DamageEventAmount x Load 1 of Key(**) from last created hashtable

**And here should be DamageEventTarget, but i cant select it.

When i try to use GetHandleID function, only thing that i can reference is a units from other functions, like "Matching Unit" for example, as you can see in the variable field in example below i cant select any unit variable which DamageEventTarget is.

1647872630826.png


Maybe i overlooked something?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
First of all i must point out that i use 1.31 pre reforged version so maybe there is can be differences.
In my map i try to implement custom resistances, which stored in hash-table, each unit has its own resistance stored in such way:

Save Real(resistance amount) as 1(number of resistance) of Key*(EnteringUnit) in last created hashtable

*Where key is GetHandleID, and it is getting ID of unit to which i apply resistance

As you can see its a simple operation and i have no troubles with it.

When i try to load resistance Value:

Event:
DamageModifierEvent becomes 1.0

Actions: (simple example)
DamageEventAmount = DamageEventAmount x Load 1 of Key(**) from last created hashtable

**And here should be DamageEventTarget, but i cant select it.

When i try to use GetHandleID function, only thing that i can reference is a units from other functions, like "Matching Unit" for example, as you can see in the variable field in example below i cant select any unit variable which DamageEventTarget is.

View attachment 396947

Maybe i overlooked something?
Oh, right. I think Hashtables work a bit oddly in GUI. You may have to use custom script in order to properly get the handle ID:

Code:
set udg_YourInteger = GetHandleId(udg_DamageEventTarget)

Then reference the integer "YourInteger" rather than the Handle ID of the damage event target.
 
Level 8
Joined
Aug 5, 2014
Messages
194
Thank you! Yes usually what you can freely do in JASS, is not possible in GUI sometimes. I read about case when you need to get handle ID of unit from varibale and you need to use custom script in the end, but i thought that this case will be a little workaround, and there is more narrow way which i just cant see. I tried your advice and its working. Thank you.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Thank you! Yes usually what you can freely do in JASS, is not possible in GUI sometimes. I read about case when you need to get handle ID of unit from varibale and you need to use custom script in the end, but i thought that this case will be a little workaround, and there is more narrow way which i just cant see. I tried your advice and its working. Thank you.
No problem. Another thing you could do, now that I think of it, is use "Custom value of unit". Since Damage Engine requires Unit Indexer, each unit already has an integer assigned to it which you can use in a GUI hashtable without having to use custom script.
 
Level 8
Joined
Aug 5, 2014
Messages
194
No problem. Another thing you could do, now that I think of it, is use "Custom value of unit". Since Damage Engine requires Unit Indexer, each unit already has an integer assigned to it which you can use in a GUI hashtable without having to use custom script.
I actually came with this idea as first solution, it worked well, but i wanted more straight forward way directly using unit ID without adding unit hadle id into its custom value in separate trigger.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I actually came with this idea as first solution, it worked well, but i wanted more straight forward way directly using unit ID without adding unit hadle id into its custom value in separate trigger.
You never would need a unit’s handle ID for reference if you already have its Unit Indexer-assigned ID. It honestly sounds like you gave up too easily.
 
Level 4
Joined
May 14, 2018
Messages
34
Ok, I´m really sorry for that
Playing Warcraft 1.26 and using DamageEvent 3.8 with 3.A.0.0 modification

But I can do anything for like a month
Can someone help me with trouble:


I want to make a trigger, that will cause Dying Unit damage Killing unit for some number.
If I do it by event Unit dies - nothing happens if unit killed by spell.

If I do it by checking the unit`s life before death (DamageEventAmount >= Life of DamageEventTarget) it bugged
Killing unit in this way by normal attacks works fine, but if I kill unit by spell causes unit survive and killing unit receive lot much damage that was noticed in "Cause Damage" action.


Any suggestions?
Thank you very much
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Ok, I´m really sorry for that
Playing Warcraft 1.26 and using DamageEvent 3.8 with 3.A.0.0 modification

But I can do anything for like a month
Can someone help me with trouble:


I want to make a trigger, that will cause Dying Unit damage Killing unit for some number.
If I do it by event Unit dies - nothing happens if unit killed by spell.

If I do it by checking the unit`s life before death (DamageEventAmount >= Life of DamageEventTarget) it bugged
Killing unit in this way by normal attacks works fine, but if I kill unit by spell causes unit survive and killing unit receive lot much damage that was noticed in "Cause Damage" action.


Any suggestions?
Thank you very much
Hi,

The equation there is not perfect, but would work in most cases. You'd instead want to do something like "((Life of DamageEventTarget) - DamageEventAmount) Less than 0.41" if you wanted something to cover pretty much every lethal damage event.

If I had to guess why your on-damage trigger is bugged, I'd have to assume it's because you may have forgotten to update the variables from things like (Killing unit) or (Dying unit) to the equivalent DamageEvent variables.
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
hi can anyone help me with this?.
I'm getting an error. I'm using the Lua Damage Engine based on 5.4.2.3 since i have 1.31.

i got "too many nested ifs (max is 50)"


under "damage engine" script.. i'm not familliar with
Seems like the formatting got jacked up there. The equals signs need to be connected, not separated by a space
 
Level 7
Joined
Nov 8, 2008
Messages
174
Seems like the formatting got jacked up there. The equals signs need to be connected, not separated by a space
I tried what you suggested. but I still got the error, I tried on a empty map, but still got the same error.

i'm using 1.31b, i did all the how to install and as well as in preferences but still got "too many nested ifs (max is 50)"
do i need some tools to copy the code???

do I also have to copy the demo folder? i only copied the damage engine folder as the description said..
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I tried what you suggested. but I still got the error, I tried on a empty map, but still got the same error.

i'm using 1.31b, i did all the how to install and as well as in preferences but still got "too many nested ifs (max is 50)"
do i need some tools to copy the code???

do I also have to copy the demo folder? i only copied the damage engine folder as the description said..
I honestly can't remember how it goes, but I think you need to copy the demo folder as well. The Lua version is kinda bork as I haven't messed around with Lua in years.
 
Level 7
Joined
Nov 8, 2008
Messages
174
I honestly can't remember how it goes, but I think you need to copy the demo folder as well. The Lua version is kinda bork as I haven't messed around with Lua in years.
ah, thanks.
i think i found the problem, my script languange was set to JASS, since i have some spell and system uses JASS,
is it possible you have some old ver that required 1.31b only in JASS? since I can't access your latest map
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
ah, thanks.
i think i found the problem, my script languange was set to JASS, since i have some spell and system uses JASS,
is it possible you have some old ver that required 1.31b only in JASS? since I can't accept your latest map
The latest map works perfectly fine with patch 1.31 as long as you add the below function (provided in my "How to install" section) to the top of the Damage Engine library:

JASS:
 function BlzGetEventIsAttack takes nothing returns boolean
    return BlzGetEventDamageType() == DAMAGE_TYPE_NORMAL
 endfunction
 
Level 7
Joined
Nov 8, 2008
Messages
174
The latest map works perfectly fine with patch 1.31 as long as you add the below function (provided in my "How to install" section) to the top of the Damage Engine library:

JASS:
 function BlzGetEventIsAttack takes nothing returns boolean
    return BlzGetEventDamageType() == DAMAGE_TYPE_NORMAL
 endfunction
ah sorry, I meant "can't access the map", I tried opening your latest map, but it said level info data missing or invalid,

weird since im 100% sure my war3 is 1.31b patch. maybe I miss something?
 

Attachments

  • batch 2 updated list.png
    batch 2 updated list.png
    30.8 KB · Views: 13
Level 4
Joined
May 14, 2018
Messages
34
Hi,

The equation there is not perfect, but would work in most cases. You'd instead want to do something like "((Life of DamageEventTarget) - DamageEventAmount) Less than 0.41" if you wanted something to cover pretty much every lethal damage event.

If I had to guess why your on-damage trigger is bugged, I'd have to assume it's because you may have forgotten to update the variables from things like (Killing unit) or (Dying unit) to the equivalent DamageEvent variables.
I`ve tried but didn`t worked.
I did it on map attached to ur pastebin post, so no changes to system was made
Probly with that u can get what i mean:

JASS:
function Trig_Set_Damage_____________________u_Actions takes nothing returns nothing
if GetUnitTypeId(udg_DamageEventTarget) == 'hpea' then
    if GetUnitState(udg_DamageEventTarget,UNIT_STATE_LIFE) - udg_DamageEventAmount <= 0.41 then
        call UnitDamageTargetBJ( udg_DamageEventTarget, udg_DamageEventSource, 500, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL)
    else
    endif
endif
endfunction

//===========================================================================
function InitTrig_Set_Damage_____________________u takes nothing returns nothing
    set gg_trg_Set_Damage_____________________u = CreateTrigger(  )
    call TriggerRegisterVariableEvent( gg_trg_Set_Damage_____________________u, "udg_DamageModifierEvent", EQUAL, 1.00 )
    call TriggerAddAction( gg_trg_Set_Damage_____________________u, function Trig_Set_Damage_____________________u_Actions )
endfunction

1648304733455.png

Archimond had Divine armor and 3200 HP
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Curious to see changelog updated. I wonder whats new!
Not sure what happened to the formatting, but the whole thing is bonkers.

This is what's new with 5.8:
  • Added a new functionality to the AOEDamageEvent, which allows it to fire even when only one unit is hit, if the AOEDamageEvent is registered as "Not Equal" instead of "Equal to". This is useful in a very specific scenario where an AfterDamageEvent may not be able to be relied upon to properly deallocate data from a running instance that needs to be able to function when multiple units are hit, but also needs to not fail when only one unit is hit.
  • Added additional filters for GUI users to avoid using trigger conditions in even more scenarios:
    • DamageFilterSource/TargetI (has item)
    • DamageFilterSource/TargetA (has ability)
    • DamageFilterSource/TargetC (has a certain classification, like hero or Tauren)
    • DamageFilterFailChance - odds for the trigger to not be run (ideal for critical strike or evasion)
  • Provided a way for GUI to un-register a Damage Event by setting "RemoveDamageEvent" to true from within their trigger's actions.
  • Moved the CreateTimer/CreateTrigger/CreateGroup calls that had been included in the globals block down to the onInit block as per request of @Ricola3D
  • Minor performance improvements thanks to @BLOKKADE

@Gerional which Damage Engine are you on again? DamageEngine 3A should be detecting that recursive flow and not allowing the unit to die. Also, how is the peasant even getting damaged by Archie?
 
Level 4
Joined
May 14, 2018
Messages
34
@Gerional which Damage Engine are you on again? DamageEngine 3A should be detecting that recursive flow and not allowing the unit to die. Also, how is the peasant even getting damaged by Archie?
That was 3.8.0.0 without 3.A.0.0.
I deleted part in which Archi heals, for showing main problem - enormous damage loop.

I just can`t get why does this happens?
I thought it would run once - in moment of getting damage by Pea.
Smth like

Pea got damage -> Damage taken > Life of Pea -> Cause Pea Damage DamageSource (Archi in this case) -> Coz Pea already dead and he can`t recieve damage, stop causing damage.

Where i`m wrong?

Sry for this stupid questions, but i`ve already tried every my theory to fix this, and stil can`t get over it
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
That was 3.8.0.0 without 3.A.0.0.
I deleted part in which Archi heals, for showing main problem - enormous damage loop.

I just can`t get why does this happens?
I thought it would run once - in moment of getting damage by Pea.
Smth like

Pea got damage -> Damage taken > Life of Pea -> Cause Pea Damage DamageSource (Archi in this case) -> Coz Pea already dead and he can`t recieve damage, stop causing damage.

Where i`m wrong?

Sry for this stupid questions, but i`ve already tried every my theory to fix this, and stil can`t get over it
If you're using 3.8 rather than 3A, then you need to take into account the recursion that will trigger when this damage amount is reached. Only Damage Engine 5 and version 3A are considered foolproof when it comes to recursion.
 
Level 4
Joined
May 14, 2018
Messages
34
If you're using 3.8 rather than 3A, then you need to take into account the recursion that will trigger when this damage amount is reached. Only Damage Engine 5 and version 3A are considered foolproof when it comes to recursion.
Ok, there is still some questions about 3.A.0.0 in that case

If i`m using 3.A.0.0 i should use it INSTEAD 3.8.0.0 Damage Engine trigger or it should be in ADDITION to this trigger?

Coz if i`m trying to install 3.A.0.0 there is this kind of error so i cant get what shoul to do

1648308116376.png
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Ok, there is still some questions about 3.A.0.0 in that case

If i`m using 3.A.0.0 i should use it INSTEAD 3.8.0.0 Damage Engine trigger or it should be in ADDITION to this trigger?

Coz if i`m trying to install 3.A.0.0 there is this kind of error so i cant get what shoul to do

You would delete all the JASS from the 3.8 damage engine script and replace it with the vJass of the 3A script. I am pretty sure that the Config trigger does not need to be amended.
 
Top