• 🏆 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...
Level 4
Joined
Jul 31, 2019
Messages
19
Lua damage engine ceases to function 15 seconds after map start when copied into a new custom map. Has happened on a few maps when attempting to use Damage Engine.

Note: Was working exclusively in Lua custom scripts. Could be some interaction with garbage collection?

EDIT:

Any attempt to modify or remove the "Damage Tag" trigger completely breaks the damage engine ~15 seconds into the game.

EDIT 2:
After extensive testing I'd found that any function that does nothing but has the event
"Game - DamageEvent becomes Equal to 1.00"
will fix any problems I have but becomes completely non functional without something of that type.
 
Last edited:
Level 4
Joined
Mar 15, 2020
Messages
32
First I wanna say, this is a great tool and is greatly improving the quality of my work but I am having 1 problem. Now call me a noob but I can't seem to wrap my head around how I can get the damage engine to detect heals and modify the heal; (for example making rejuvenation scale) if you could point me to the right direction I would be really grateful.

Aside from that, great job! This engine is amazing!
 
Level 11
Joined
Jul 17, 2013
Messages
544
i updated the damage engine in my map from very old version to the newest one but i have issue, in the middle or late game the fps sometimes drops to 1.0 has this ever been reported? i need to test it out myself because updating damage engine isnt the only thing i did. i wanted to read comments to find out about it but its almost 80 pages xd
 
Level 13
Joined
Oct 18, 2013
Messages
690
If I copy and paste all the variables for the new version, it crashes my world editor. How can I import the variables?
 
Level 13
Joined
Jul 15, 2007
Messages
763
If I copy and paste all the variables for the new version, it crashes my world editor. How can I import the variables?

I have had this problem for a while. A solution is to copy over the new engine code and then copy and paste in only the new variables you need. There's something about pasting numerous variables (or copies of variables) that makes the editor freak out, especially in maps that already have a lot of variables.
 
Level 13
Joined
Oct 18, 2013
Messages
690
Code:
boolean udg_IsDamageAttack
integer udg_NextDamageWeaponT
boolean udg_NextDamageIsMelee
boolean udg_NextDamageIsRanged
boolean udg_NextDamageIsAttack

Put this in my script header and it compiled, but dmgEvent is not working. I'll try what you suggested and get back to this post @GhostHunter123

edit: Seems to make no difference if I move the Vars folder out of the main folder, it still crashes on c/p.

Additionally, adding function names and variables like mod and dmg, that modders are likely to have already initialized in their maps is kind of a no-no. I see that DamageModiferEvent is a changed feature, but it actually does nothing in my map when function are set to run on it ==1., should check into that.


Lastly, here's where I'm stuck. My dmg handler uses ModEvent==1., and nothing was happening. "Maybe the variables can't be declared in this block of globals I threw it in", so I make the variables in GUI. NOW statements are being cut into global blocks of my code that I'm not putting in there. (Luckily I made a backup before even trying to do this because I knew with the state of WC3 that was once a simple copy paste is now 10 compiles of debugging something painfully rudimentary. Sigh.)
Multiply assigned variables names don't even give a tell as to where they were previously declared anymore.
Does this version of DamageEngine use the variable pflag as well, because just a line down from my declaration of it is where the random text is placed. Stuff like this needs to be in the documentation to prevent this mess.


Takeaway: If youre ever asking if youre doing backups too frequently, the answer is no. Just importing code has seemingly permanently broken this copy of my map. If I had not made a backup, I'd of been frustrated enough to put the WC3 scene behind me forever.

edit2: The problem was a % symbol in a comment. I've had this issue come up before, each time its seemingly random and I've documented a few of these compiler mishaps but don't have them organized together. I should make a post on compiler quirks. Despite this line working in the test map, it doesn't work on my map. I've no clue why, the rest of damageEngine *appears* to be working:
Code:
if udg_DamageEventDamageT == udg_DAMAGE_TYPE_NORMAL then

edit3: The initializations for the udg_DamageTypes is in the config funct, it looks like that didn't make it through the paste crash I had trying to import this. Yay
 
Last edited:
Level 18
Joined
Oct 17, 2012
Messages
820
@Kakerate I placed the Vars folders into a single folder and copied that first to my map. Then I copied the rest of the variables to my map. That worked for me. Perhaps, try this method to see if it works for you.

I also placed all the Vars folders into a single new folder. Then I put that new folder back into the main folder. That also was successful in copying the vars to my map without crashes. Be sure to place the new folder into the main folder or it will crash. And you might want to minimize the folders during the copying process.

Vars folders.jpg
 
Last edited:
Level 7
Joined
Feb 9, 2021
Messages
301
I tried to open the system, but I got "
"Unable to load file 'C:\Program Files\Warcraft III\Maps\High Elves.w3x'
- Level info data missing or invalid.""
 
Level 9
Joined
Jul 18, 2005
Messages
319
@maxodors there is a link to one such version if you click the Requirements tab:

  • 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
 
Level 7
Joined
Feb 9, 2021
Messages
301
I got this error for some reason, when I tried to install 3.A version. I just changed damage engine trigger from the one in the file to the 3.A version.
1615720721272.png
 
Level 18
Joined
Oct 17, 2012
Messages
820
Right before the endmethod line, type return false.

By the way, it appears you did not fix your first error. The method finish that you have to made changes to is the one under the struct DamageTrigger.
Your second error is also related to the first error.

@Bribe
Damage Engine [Lua] is crashing my Wc3, whenever two units hit each other.

I attached an example map for you, which is completely empty apart of Damage Engine and two adjacent footmans.
It crashes a second after map start, as soon as the footmans hit with their attacks.
Bribe has left, so you will have to rely on yourself or others to fix the issue.
 
Last edited:
Level 7
Joined
Feb 9, 2021
Messages
301
Right before the endmethod line, type return false.

By the way, it appears you did not fix your first error. The method finish that you have to made changes to is the one under the struct DamageTrigger.
Your second error is also related to the first error.


Bribe has left, so you will have to rely on yourself or others to fix the issue.
I made changes under the struct DamageTrigger this time, but I still get an error "missing return".
1615890076653.png
 
Level 18
Joined
Oct 17, 2012
Messages
820
You need a return boolean before the endfunction. On the original code, that would be before the endmethod for the method finish that is under the struct DamageTrigger.

I am guessing you added it at the wrong spot. Can you show me your changes, so I can better assist you?
 
Last edited:
Level 7
Joined
Feb 9, 2021
Messages
301
You need a return boolean before the endfunction. On the original code, that would be before the endmethod for the method finish that is under the struct DamageTrigger.

I am guessing you added it at the wrong spot. Can you show me your changes, so I can better assist you?
So, I was able to fix the error. However, I am not sure whether it is correct. I changed this:

JASS:
static method finish takes nothing returns nothing
        if checkLife() and not blocked and udg_DamageEventAmount != 0.00 then
            call DamageTrigger.AFTER.run()
        endif
    endmethod

To this

JASS:
static method finish takes nothing returns boolean
        if checkLife() and not blocked and udg_DamageEventAmount != 0.00 then
            call DamageTrigger.AFTER.run()
        endif
        return false
    endmethod

I tried to use this system in a simple way, but it doesn't really work. Also, how do you transfer "caster" for damage from another unit?


JASS:
function Trig_VMR_Attack_Actions takes nothing returns nothing
    if UnitHasBuffBJ(udg_DamageEventSource, 'B00E') and not udg_IsDamageSpell then
        call UnitDamageTarget( udg_DamageEventSource, udg_DamageEventSource, 20.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_PLANT, null)
    endif
endfunction

//===========================================================================
function InitTrig_VMR_Attack takes nothing returns nothing
    set gg_trg_VMR_Attack = CreateTrigger(  )
    call TriggerRegisterVariableEvent( gg_trg_VMR_Attack, "udg_DamageEvent", EQUAL, 1.00 )
    call TriggerAddAction( gg_trg_VMR_Attack, function Trig_VMR_Attack_Actions )
endfunction
 
Level 7
Joined
Feb 9, 2021
Messages
301
You are issuing damage within a damage detection block, crashing the thread with an infinite loop.

Disable the trigger before issuing the damage and enable the trigger right after.
1. I didn't quite get you. I want to cause damage to the unit by the caster every time it attacks, while it has debuff. I have another timer function, which makes this debuff.

2. Did I fix DDS correctly?
 
Level 6
Joined
Dec 29, 2019
Messages
82
@Bribe
Damage Engine [Lua] is crashing my Wc3, whenever two units hit each other.

I attached an example map for you, which is completely empty apart of Damage Engine and two adjacent footmans.
It crashes a second after map start, as soon as the footmans hit with their attacks.

I've checked your example... to be honest this system is a mess... it was designed mainly for GUI usage, since GUI map makers cannot create AnyUnit damage event... i mean for coders this system is maybe too complex and not efficient.

damage events is handled through one real global variable, and damage values are handled through globals as well which can cause desyncing when there are too many dmg events in a moment... i mean that system contains everything u can possibly think about when it comes to managing damage encounters, but everyone should ask before using it, do i really need that many features ? Wouldn't it be nice to make something more optimized for my project ?

If you are using lua, that means you don't need system like this and everything u need are natives...

Code:
TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DAMAGED) -- trigger catches dmg event after its recalculated (armor reductions ect...)
TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DAMAGING) -- trigger catches dmg event before its recalculated (the value which comes into event...)

-- some fundamental natives which catches and sets everything u possibly need...
-- whith those everything other like absorbing system, blocking system or anything else is doable and only limit is your imagination
-- + you don't need to use globals and unsafe real value event ... you are free to run properly scoped function on dmg event... which uses local vars and never desync

BlzSetEventAttackType(attackType)
BlzSetEventDamage(damage)
BlzSetEventDamageType(damageType)
BlzSetEventWeaponType(weaponType)
GetEventDamage()
GetEventDamageSource()
BlzGetEventDamageTarget()
BlzGetEventDamageType()
BlzGetEventWeaponType()
BlzGetEventAttackType()
 
Level 20
Joined
Jul 10, 2009
Messages
477
If you are using lua, that means you don't need system like this and everything u need are natives...
Right! I hoped to save time by using other modders systems, but self building a system for my needs has its own benefits of course. I do notice that I have to get familiar with the new natives. Thank you very much, Sir! Your time investment is much appreciated!
 
Level 1
Joined
Mar 18, 2021
Messages
1
I'm having a difficult time understanding what to set the actual event values to:
How would something like Game - DamageModifierEvent Less than 0.00 be different from if it were Less than -1.00 or Less than 3.00? The description above just says to use 1.00, 2.00, 3.00, but I don't know what the differences would be if any.
A few pages back I see that there is even an example that uses -420.69 (nice), so am I right to assume I can just choose any number I want as long as it's <4 for raw damage and >=4 for reduced damage?

Similarly for the other events, like DamageEvent, LethalDamageEvent, AOEDamageEvent, would these also use the same rules as above?

edit: clarified my second questiono
 
Last edited:
Level 7
Joined
Feb 9, 2021
Messages
301
You are issuing damage within a damage detection block, crashing the thread with an infinite loop.

Disable the trigger before issuing the damage and enable the trigger right after.
Sorry, it was quite stupid by me. I tried to do it before the if statement and after. It still does not work.

JASS:
function Trig_VMR_Attack_Actions takes nothing returns nothing
    
    call DisableTrigger( GetTriggeringTrigger() )
    if UnitHasBuffBJ(udg_DamageEventSource, 'B00E') and not udg_IsDamageSpell and IsUnitEnemy(udg_DamageEventTarget, GetOwningPlayer(udg_DamageEventSource)) then
        call UnitDamageTarget( udg_DamageEventTarget, udg_DamageEventSource, 20.00, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_PLANT, null)
    endif
    call EnableTrigger( GetTriggeringTrigger() )
   
endfunction

//===========================================================================
function InitTrig_VMR_Attack takes nothing returns nothing
    set gg_trg_VMR_Attack = CreateTrigger(  )
    call TriggerRegisterVariableEvent( gg_trg_VMR_Attack, "udg_DamageEvent", EQUAL, 1.00 )
    call TriggerAddAction( gg_trg_VMR_Attack, function Trig_VMR_Attack_Actions )
endfunction
 
Last edited:

Wrda

Spell Reviewer
Level 25
Joined
Nov 18, 2012
Messages
1,870
I've checked your example... to be honest this system is a mess... it was designed mainly for GUI usage, since GUI map makers cannot create AnyUnit damage event... i mean for coders this system is maybe too complex and not efficient.

damage events is handled through one real global variable, and damage values are handled through globals as well which can cause desyncing when there are too many dmg events in a moment... i mean that system contains everything u can possibly think about when it comes to managing damage encounters, but everyone should ask before using it, do i really need that many features ? Wouldn't it be nice to make something more optimized for my project ?

If you are using lua, that means you don't need system like this and everything u need are natives...

Code:
TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DAMAGED) -- trigger catches dmg event after its recalculated (armor reductions ect...)
TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_DAMAGING) -- trigger catches dmg event before its recalculated (the value which comes into event...)

-- some fundamental natives which catches and sets everything u possibly need...
-- whith those everything other like absorbing system, blocking system or anything else is doable and only limit is your imagination
-- + you don't need to use globals and unsafe real value event ... you are free to run properly scoped function on dmg event... which uses local vars and never desync

BlzSetEventAttackType(attackType)
BlzSetEventDamage(damage)
BlzSetEventDamageType(damageType)
BlzSetEventWeaponType(weaponType)
GetEventDamage()
GetEventDamageSource()
BlzGetEventDamageTarget()
BlzGetEventDamageType()
BlzGetEventWeaponType()
BlzGetEventAttackType()
You clearly don't know the history behind this system.
Many of these features weren't possible on older patches as in, implementing them in a simple way. This was innovative because it differenciated between spell damage and physical, didn't have to make 1000000 unit takes damage events, handled recursion, and countless more. And no it wasn't made for "GUIers", it was made for people who wanted a complex system.
Sure, many of these features are now possible to do easily, but still some that are a nuisance, e.g.: detect AOE damage, main target and secundary ones; bouncing damage, main target and secundary ones; multi-shot, main target and secundary ones; same unit hit simultaneously by the same source.
Tell me, do all the natives do this work for me? Is it that simple to do?
Also I was unable to find any information about real value event being unsafe and that it cause desyncs, and without any source this will be viewed as some bullshit made up.
 
Level 6
Joined
Dec 29, 2019
Messages
82
You clearly don't know the history behind this system.
Many of these features weren't possible on older patches as in, implementing them in a simple way. This was innovative because it differenciated between spell damage and physical, didn't have to make 1000000 unit takes damage events, handled recursion, and countless more. And no it wasn't made for "GUIers", it was made for people who wanted a complex system.
Sure, many of these features are now possible to do easily, but still some that are a nuisance, e.g.: detect AOE damage, main target and secundary ones; bouncing damage, main target and secundary ones; multi-shot, main target and secundary ones; same unit hit simultaneously by the same source.
Tell me, do all the natives do this work for me? Is it that simple to do?
Also I was unable to find any information about real value event being unsafe and that it cause desyncs, and without any source this will be viewed as some bullshit made up.
Yeah, i don't know backstory behind this system and i really did not want to offend anyone... i've just pointed out that today, one can easily create dmg engine on his own, maybe not this complex, but good eough for their map + many of system logic can by simplified in Lua i mean Lua version of this system is clearly not optimized as good as it could be and that's the reason why i gave advice to Lua coder rather build up his own logic. Warcraft 3 engine (reforged especially) is far from optimized ... and if you can save some CPU power by avoiding existing systems which oftenly contains dozens of logic which u will never use and creating your own to fill your requirements then why the hell not... My statement is this system is MESS for Lua usage that's all... it's perfect for GUI-ers and maybe for JASSers as well, cannot judge since i know jackshit about jass.
 
Level 7
Joined
Feb 9, 2021
Messages
301
You are issuing damage within a damage detection block, crashing the thread with an infinite loop.

Disable the trigger before issuing the damage and enable the trigger right after.
Sorry, I just wanted to follow up on my question. I need this system as air for my project.
 
Level 11
Joined
Jul 17, 2013
Messages
544
hey nice system but i have a problem. my hero has multishoot based on vanillia barage and when he attacks it detects his attack with trigger 3 times because he shoots 3 arrows 1 basic one +2 from multishoot. any idea how can i make it so it detects only his main attack? Because then all of my trigger is ruined if it decets his attack 3 times all futher actions dont work propley.


i know about condition ,,is an attack'' that has been aded recently but i cant really use it because when i updated my damage engine my game started to have low fps so i must now take away the new ver of damage engine and test it on old one again to check if it was the reason of low fps.


there are also screenshoots of my problemw ith hero's attack https://cdn.discordapp.com/attachments/311662737015046144/808092454150471680/unknown.png

if its checked 3 times at once then all spells are added too quickly. it should be checked and ran 1 time per heroes attack
 
Level 11
Joined
Jul 17, 2013
Messages
544
Is it possible to make the damage engine ignore specific players? Cause I have a map with a lot of mobs and I think the damage engine is causing some lag. So I want to have that computer player ignored by it.
Sadly i dont know answer to your issue but i AM curious about Ur problem. For long time i was using 5.4.2.3 ver of damage engine then łater i updated IT and i had the latest version of damage engine but i noticed that my map started to lag. Do you use the latest damage engine version?
 
@Bribe
Damage Engine [Lua] is crashing my Wc3, whenever two units hit each other.

I attached an example map for you, which is completely empty apart of Damage Engine and two adjacent footmans.
It crashes a second after map start, as soon as the footmans hit with their attacks.
Try adding the "FastTriggers" script in the demo category to your map, that solved the issue for me.
 
Level 20
Joined
Jul 10, 2009
Messages
477
Try adding the "FastTriggers" script in the demo category to your map, that solved the issue for me.
Thanks for sharing your finding, much appreciated! Actually, I already removed Damage Engine from my map, since I only need basic stuff that Reforged can do natively, but your suggestion will definitely be useful for the next poor guy having this issue :)
 
Level 4
Joined
Sep 25, 2018
Messages
81
Hey! Seems to be having a strange inconsistency issue with this DDS.

I have an ability, based on Envenomed Spears, which deals damage based on the attacking units agility, and removes 1 strength every second that the target is poisened.

  • EnfeeblingPoisonDamage
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventTarget has buff Enfeebling Poison (Stacking)) Equal to True
      • DamageEventPrevAmt Equal to 5.00
    • Actions
      • -------- Add to EP_UnitGroup --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventTarget is in EP_UnitGroup.) Not equal to True
        • Then - Actions
          • Unit Group - Add DamageEventTarget to EP_UnitGroup
          • Hashtable - Save (Ability: (Unit: DamageEventTarget's Ability with Ability Code: Attribute Bonus )'s Integer Level Field Strength Bonus ('Istr'), of Level: 0) as (Key EP_AttributeHandle.) of (Key EP_TempHandle.) in EP_HastTable.
        • Else - Actions
      • -------- - --------
      • -------- Turn on EnfeeblingPoisonTimer --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (EnfeeblingPoisonTimer <gen> is on) Not equal to True
        • Then - Actions
          • Trigger - Turn on EnfeeblingPoisonTimer <gen>
        • Else - Actions
      • -------- - --------
      • -------- Set Damage --------
      • Set VariableSet DamageEventAmount = (Real(((Integer(((Real((Agility of DamageEventSource (Include bonuses)))) / 10.00))) x (Integer(DamageEventPrevAmt)))))
      • -------- - --------
      • -------- Reduce Strength if total Strength greater than 0 --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Strength of DamageEventTarget (Include bonuses)) Greater than 0
        • Then - Actions
          • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Attribute Bonus )'s Integer Level Field: Strength Bonus ('Istr') of Level: 0 to ((Ability: (Unit: DamageEventTarget's Ability with Ability Code: Attribute Bonus )'s Integer Level Field Strength Bonus ('Istr'), of Level: 0) - 1)
          • Unit - Increase level of Attribute Bonus for DamageEventTarget
          • Unit - Decrease level of Attribute Bonus for DamageEventTarget
        • Else - Actions

  • EnfeeblingPoisonTimer
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in EP_UnitGroup and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Enfeebling Poison (Stacking)) Not equal to True
            • Then - Actions
              • Ability - Set Ability: (Unit: (Picked unit)'s Ability with Ability Code: Attribute Bonus )'s Integer Level Field: Strength Bonus ('Istr') of Level: 0 to (Load (Key EP_AttributeHandle.) of (Key EP_TempHandle.) from EP_HastTable.)
              • Unit - Increase level of Attribute Bonus for (Picked unit)
              • Unit - Decrease level of Attribute Bonus for (Picked unit)
              • Hashtable - Clear all child hashtables of child (Key EP_TempHandle.) in EP_HastTable.
              • Unit Group - Remove (Picked unit) from EP_UnitGroup.
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Number of units in EP_UnitGroup) Less than or equal to 0
            • Then - Actions
              • Trigger - Turn off (This trigger)
            • Else - Actions

The problem is that the ability only works with my Blood Mage unit (I was using the Blood Mage initally to test the damage part of the ability). When I add the Ability to other units, the damage and the strength reduction doesn't work.

Wondering what could be the problem!
 
Level 4
Joined
May 19, 2020
Messages
319
I congratulate Bribe and all the other contributors for this ingenious and very useful work for the community, you saved the lives of several players! lolol
Although my case was only useful to use a small fraction of all this wonderful work, but for my current modifications, this function was extremely important in order not to cause "Break" in my map and above all, to make it possible to give projects, which previously did not seem to have a solution.
I needed to use only the damage detector for "Melee Damage", trying to identify all attacks from a minimum distance, to create after each attack an additional order of action for all melee units, using only this single event and trigger.

Of course, I could easily develop this on my own, just with triggers in the GUI.
But my problem was the extreme leaks of event objects, due to the infinite amount of each new blow, that would trigger almost every millisecond several shots of the same event.
I expect and believe that this powerful DDS will be able to not cause leaks even in battles of 300vs300 units activating new attacks and receiving new orders simultaneously.

Edit: Once again, I thank this team of coders. 👏 👏 👏
 
Level 12
Joined
May 16, 2020
Messages
660
Can I somehow distinguish between Pulverize and Cleaving Attack?

Apparently they both use DAMAGE TYPE ENHANCED. In my case, I have an item with Cleaving Attack and an ability which uses Pulverize as base. When Pulverize triggers, it fires triggers specifically for the Pulverize.

Combined however (the hero with Pulverize + item), the trigger of the Pulverize-Ability fires at every single unit hit by the Cleave Attack (which is funny, but I still wanna fix it xD).
 
Level 20
Joined
May 16, 2012
Messages
635
Can I somehow distinguish between Pulverize and Cleaving Attack?

Apparently they both use DAMAGE TYPE ENHANCED. In my case, I have an item with Cleaving Attack and an ability which uses Pulverize as base. When Pulverize triggers, it fires triggers specifically for the Pulverize.

Combined however (the hero with Pulverize + item), the trigger of the Pulverize-Ability fires at every single unit hit by the Cleave Attack (which is funny, but I still wanna fix it xD).
You can check for the ATTACK_TYPE. Pulverize has ATTACK_TYPE_NORMAL, meaning spell damage, while cleaving attack do not.
 
Level 20
Joined
May 16, 2012
Messages
635
What exactly constitutes "IsDamageAttack"?

I was under the assumption that this somehow checks if the attack is done via autoattacking. But spells which deal attack type NORMAL and damage type NORMAL also trigger IsDamageAttack. Is this by design?
DAMAGE_TYPE_NORMAL is the damage type dealt when a unit attacks another, so this is a Warcraft standard. If you have in a trigger or in code a UnitDamageTarget() and you set the damage type to DAMAGE_TYPE_NORMAL then it will be seen as an attack. I would recommend not using DAMAGE_TYPE_NORMAL unless you want the trigger damage seen as an attack.
 
Level 12
Joined
May 16, 2020
Messages
660
Thanks for the quick reply Chopinski.

I want to keep this particular spell doing DAMAGE_TYPE_NORMAL damage, so that it deals more damage with armor reduction. As workaround I added the following line before to the spell and added a condition to another trigger to ignore this type of damage.
  • Set VariableSet NextDamageType = DamageTypeCode

That fixed it.

However, a separate problem which very much confuses me:

In my map I use 3 items:
1) 1 which has the standard WC3 Cleave ability
2) 1 which provides life steal. I triggered the lifesteal, to ignore ORB problems
3) 1 which "slows" enemies on damage. This ability is also triggered on damage

The interaction between the 3 items is currently like this:
  • Item 1) and 2) completely stack. Meaning if you cleave a group of enemies, you steal a lot more life than when attacking a single one
  • Item 1) and 3) do NOT stack. I want them to stack though
Here the 2 triggers of item 2) and 3) for comparison:

LIFE STEAL:
  • Mask of Death
    • Events
      • Game - DamageEvent becomes Less than 1.00
      • Game - LethalDamageEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventSource has an item of type Mask of Death) Equal to True
      • (DamageEventTarget is A structure) Equal to False
      • (DamageEventSource belongs to an enemy of (Owner of DamageEventTarget).) Equal to True
      • IsDamageCode Equal to False
    • Actions
      • Special Effect - Create a special effect attached to the chest of DamageEventSource using Abilities\Spells\Undead\VampiricAura\VampiricAuraTarget.mdl
      • Special Effect - Destroy (Last created special effect)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventSource is an illusion) Equal to False
        • Then - Actions
          • Set VariableSet MaskOfDeath_CV = (Custom value of DamageEventSource)
          • Set VariableSet MaskOfDeath_HealValue = (0.15 x DamageEventAmount)
          • Unit - Set life of DamageEventSource to ((Life of DamageEventSource) + (MaskOfDeath_HealValue - (MaskOfDeath_HealValue x HealReduction_Multiplier[MaskOfDeath_CV])))
        • Else - Actions
SLOW ON ATTACK DAMAGE:
  • Eye of Skadi
    • Events
      • Game - DamageEvent becomes Less than 1.00
    • Conditions
      • (DamageEventSource has an item of type Eye of Skadi) Equal to True
      • (DamageEventTarget is A structure) Equal to False
    • Actions
      • Set VariableSet HealReduction_CV = (Custom value of DamageEventTarget)
      • Set VariableSet HealReduction_Multiplier[HealReduction_CV] = 0.40
      • Set VariableSet HealReduction_Time[HealReduction_CV] = 15
      • Set VariableSet HealReduction_Buff[HealReduction_CV] = Slowed
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventTarget is in HealReduction_Group.) Equal to False
        • Then - Actions
          • Unit Group - Add DamageEventTarget to HealReduction_Group
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Heal Reduction <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Heal Reduction <gen>
        • Else - Actions
      • -------- --------
      • Set VariableSet Vertex_CV = (Custom value of DamageEventTarget)
      • Set VariableSet Vertex_Time[Vertex_CV] = 15
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventTarget is in Vertex_Group.) Equal to False
        • Then - Actions
          • Unit Group - Add DamageEventTarget to Vertex_Group
          • Set VariableSet Vertex_Ability[Vertex_CV] = Freeze (Undispellable)
          • Set VariableSet Vertex_Buff[Vertex_CV] = Slowed (Undispellable)
          • Set VariableSet Vertex_Delay[Vertex_CV] = True
          • -------- --------
          • Animation - Change DamageEventTarget's vertex coloring to (50.00%, 75.00%, 80.00%) with 0.00% transparency
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DamageEventSource is A melee attacker) Equal to True
            • Then - Actions
              • Unit - Add Freeze (Undispellable) to DamageEventTarget
              • Unit - Remove Slowed (Undispellable) buff from DamageEventTarget
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Movement Speed Increase (%) ('Oae1') of Level: 0 to (1.00 x -0.50)
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Attack Speed Increase (%) ('Oae2') of Level: 0 to (1.00 x -0.50)
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: True, Hide UI: False
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: False, Hide UI: False
            • Else - Actions
              • Unit - Add Freeze (Undispellable) to DamageEventTarget
              • Unit - Remove Slowed (Undispellable) buff from DamageEventTarget
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Movement Speed Increase (%) ('Oae1') of Level: 0 to (1.00 x -0.25)
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Attack Speed Increase (%) ('Oae2') of Level: 0 to (1.00 x -0.25)
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: True, Hide UI: False
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: False, Hide UI: False
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Vertex Coloring <gen> is on) Equal to False
        • Then - Actions
          • Countdown Timer - Start Vertex_Timer as a Repeating timer that will expire in 0.20 seconds
          • Trigger - Turn on Vertex Coloring <gen>
        • Else - Actions


--> I don't understand why Cleave works for 2), but not for 3)
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Hi Bribe, the item with Cleave (it's called Battle Fury) uses the default "Cleaving Attack" ability, see the settings here:

1621066729016.png


Battle Fury has only 1 trigger attached to it:
  • Battle Fury
    • Events
      • Game - DamageModifierEvent becomes Less than 1.00
    • Conditions
      • (DamageEventSource has an item of type Battle Fury) Equal to True
      • (DamageEventTarget is A structure) Equal to False
      • (DamageEventTarget is A Hero) Equal to False
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventSource is A melee attacker) Equal to True
        • Then - Actions
          • Set VariableSet DamageEventAmount = (DamageEventAmount + 18.00)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DamageEventSource is A ranged attacker) Equal to True
            • Then - Actions
              • Set VariableSet DamageEventAmount = (DamageEventAmount + 6.00)
            • Else - Actions

What I tried to "debug": I added a "kill DamageEventTarget" at the very beginning of the trigger for the item which doesn't interact with cleave. Result: Only the main Target is instantly killed. All other cleaved targets stay alive. So it already fails at this very early point...

Could it be that when you modify damage, other triggers can no longer recognize it?


Edit: So I experimented some more, and what makes it interact is if I add the Event "Game - LethalDamageEvent becomes Equal to 1.00" to the non-interacting trigger. But I don't understand why.

To illustrate, the following DOES interact with cleave. The other one (see previous post) doesn't.

  • Eye of Skadi
    • Events
      • Game - DamageEvent becomes Less than 1.00
      • Game - LethalDamageEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventSource has an item of type Eye of Skadi) Equal to True
      • (DamageEventTarget is A structure) Equal to False
    • Actions
      • Set VariableSet HealReduction_CV = (Custom value of DamageEventTarget)
      • Set VariableSet HealReduction_Multiplier[HealReduction_CV] = 0.40
      • Set VariableSet HealReduction_Time[HealReduction_CV] = 15
      • Set VariableSet HealReduction_Buff[HealReduction_CV] = Slowed (Undispellable)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventTarget is in HealReduction_Group.) Equal to False
        • Then - Actions
          • Unit Group - Add DamageEventTarget to HealReduction_Group
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Heal Reduction <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Heal Reduction <gen>
        • Else - Actions
      • -------- --------
      • Set VariableSet Vertex_CV = (Custom value of DamageEventTarget)
      • Set VariableSet Vertex_Time[Vertex_CV] = 15
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DamageEventTarget is in Vertex_Group.) Equal to False
        • Then - Actions
          • Unit Group - Add DamageEventTarget to Vertex_Group
          • Set VariableSet Vertex_Ability[Vertex_CV] = Freeze (Undispellable)
          • Set VariableSet Vertex_Buff[Vertex_CV] = Slowed (Undispellable)
          • -------- --------
          • Animation - Change DamageEventTarget's vertex coloring to (50.00%, 75.00%, 80.00%) with 0.00% transparency
          • -------- --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (DamageEventTarget is A melee attacker) Equal to True
            • Then - Actions
              • Unit - Add Freeze (Undispellable) to DamageEventTarget
              • Unit - Remove Slowed (Undispellable) buff from DamageEventTarget
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Movement Speed Increase (%) ('Oae1') of Level: 0 to (1.00 x -0.25)
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Attack Speed Increase (%) ('Oae2') of Level: 0 to (1.00 x -0.25)
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: True, Hide UI: False
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: False, Hide UI: False
            • Else - Actions
              • Unit - Add Freeze (Undispellable) to DamageEventTarget
              • Unit - Remove Slowed (Undispellable) buff from DamageEventTarget
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Movement Speed Increase (%) ('Oae1') of Level: 0 to (1.00 x -0.50)
              • Ability - Set Ability: (Unit: DamageEventTarget's Ability with Ability Code: Freeze (Undispellable))'s Real Level Field: Attack Speed Increase (%) ('Oae2') of Level: 0 to (1.00 x -0.50)
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: True, Hide UI: False
              • Unit - For DamageEventTarget, Ability Freeze (Undispellable), Disable ability: False, Hide UI: False
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Vertex Coloring <gen> is on) Equal to False
        • Then - Actions
          • Countdown Timer - Start Vertex_Timer as a Repeating timer that will expire in 0.20 seconds
          • Trigger - Turn on Vertex Coloring <gen>
        • Else - Actions
 
Last edited:
Top