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

[Spell] simple damage engine

Status
Not open for further replies.
Level 21
Joined
Mar 29, 2020
Messages
1,237
hey there,

I'm trying to make a spell that very basically modifies the attack of some units ( I just want to make "all picked units" attack for X% more damage when they attack units belonging to player Y ). I am having trouble detecting a few aspects necessary for this -

how much damage the unit is doing or alternatively if the unit is using weapon index1 or 0
what type of damage the unit is doing
when the unit is doing the damage (so that that the damage I add happens at the same time as the unit is attacking)

I assume what I need is some kind of damage engine(/Ddetection system?) and would be happy for a suggestion of a reliable one that works with patch 1.31

If that is not the most straightforward solution to this I would be happy to hear what is.

thanks!
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
Bribe's Damage Engine is the one I use and know how to use. Damage Engine 5.6.2.0

I uploaded a slightly older version just in his case his latest version (5.6.2.0) is incompatible. He says it requires 1.32.

And this is taken straight from his thread.

HOW TO USE:
  • Detect damage: use the event "DamageEvent Equal to 1.00". 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.
    • 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 "DamageModifierEvent Becomes Equal to 1.00, 2.00 or 3.00". 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 "DamageModifierEvent Becomes Equal to 4.00". 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 "DamageModifierEvent" 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.

What your trigger could look like:
  • Events:
  • DamageModifierEvent becomes equal to 1.00
  • Conditions:
  • Owner of DamageEventTarget belongs to Player X
  • Owner of DamageEventSource belongs to Player Y
  • Actions:
  • Set DamageEventAmount = DamageEventAmount * 1.50
This Event will run just before damage is dealt and before reduction calculations are made such as armor reduction. This is useful for modifying the damage before it's dealt.

As you can see in the trigger you simply reference some variables that come with the Damage Engine.
DamageEventSource = the unit that dealt the damage.
DamageEventTarget = the unit that was damaged.
DamageEventAmount = the amount of damage dealt.

So, I'm checking the owners of both the damaged unit and damaging unit, and if they're the correct players, I multiply the damage dealt by 1.50, resulting in 50% more damage.
 

Attachments

  • Damage Engine v5.6.0.0.w3x
    64 KB · Views: 37
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
Open this map, open the Damage engine & text folder in the Trigger Editor, delete the Unit Indexer trigger (since you already have this in your map), and then copy the folder and paste it into your map.
 

Attachments

  • Bone Armor v1.13.1.w3x
    107 KB · Views: 27

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
You need to copy and paste the Detect Spell Damage ability into your map. After doing that go into the config trigger and set the variable:
  • Set Variable SpellDamageAbility = Detect Spell Damage
I think that's all that you need to do. Then you can create that trigger I posted earlier.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
thanks! this seems to be running smoothly :smile:

mind proofreading the triggers? (pretty short)

  • Grudge
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Grudge
    • Actions
      • Set CV = (Custom value of (Triggering unit))
      • Set GrudgeCaster[CV] = (Triggering unit)
      • Set GrudgeOwner[CV] = (Triggering player)
      • Set GrudgeTarget[CV] = (Owner of (Target unit of ability being cast))
  • Grudge damage add
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
      • (Owner of DamageEventTarget) Equal to GrudgeTarget[CV]
      • (Owner of DamageEventSource) Equal to GrudgeOwner[CV]
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Grudge for GrudgeCaster[CV]) Equal to 1
        • Then - Actions
          • Set DamageEventAmount = (DamageEventAmount x 1.08)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Grudge for GrudgeCaster[CV]) Equal to 2
            • Then - Actions
              • Set DamageEventAmount = (DamageEventAmount x 1.16)
            • Else - Actions
              • Set DamageEventAmount = (DamageEventAmount x 1.24)
also - is there any way to get an effect or buff to show up only when this becomes active, or to have a buff with text that shows a variable player's name?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
You're referencing CV without setting it in the damage trigger.


Also, and this is up to you, there's 2 ways of handling the effects of this trigger.

Snapshot method:
1) Save a Real variable that is equal to the "bonus damage multiplier" when you cast the ability. So if Grudge is equal to level 1, set GrudgeMultiplier[CV] to 1.08. Then you can just reference GrudgeMultiplier[CV] instead of doing the If Then Else stuff in your damage trigger, since that was already taken care of in the cast trigger.

Current method:
2) Your current method will update the effects of Grudge when you level up the skill. So say you cast level 1 Grudge on an enemy (8% bonus damage), then spend 2 skill points into Grudge, the enemy player will now take 24% bonus damage despite the fact that it was a Level 1 Grudge that was cast on them.
 
Last edited:
Level 21
Joined
Mar 29, 2020
Messages
1,237
how can I access the CV of a specific hero owned by the owner of DamageEventSource?

edit: nvm, I think I got it...

should this do the trick?

  • Grudge damage add
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units owned by (Owner of DamageEventSource) of type King Of Salt) and do (Actions)
        • Loop - Actions
      • Set CV = (Custom value of (Picked unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of DamageEventTarget) Equal to GrudgeTarget[CV]
          • (Owner of DamageEventSource) Equal to GrudgeOwner[CV]
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Grudge for GrudgeCaster[CV]) Equal to 1
            • Then - Actions
              • Set DamageEventAmount = (DamageEventAmount x 1.08)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Grudge for GrudgeCaster[CV]) Equal to 2
                • Then - Actions
                  • Set DamageEventAmount = (DamageEventAmount x 1.16)
                • Else - Actions
                  • Set DamageEventAmount = (DamageEventAmount x 1.24)
        • Else - Actions
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
Set CV = Custom Value of DamageEventSource

Or

  • Conditions:
  • (Owner of DamageEventTarget) Equal to GrudgeTarget[custom value of DamageEventSource]
  • (Owner of DamageEventSource) Equal to GrudgeOwner[custom value of DamageEventSource]
Remember, CV is just a shortcut. You don't even need it. Every unit's custom value can be directly referenced like I did above.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
Set CV = Custom Value of DamageEventSource

Or

  • Conditions:
  • (Owner of DamageEventTarget) Equal to GrudgeTarget[custom value of DamageEventSource]
  • (Owner of DamageEventSource) Equal to GrudgeOwner[custom value of DamageEventSource]
Remember, CV is just a shortcut. You don't even need it. Every unit's custom value can be directly referenced like I did above.

but I set it according to the custom value of the casting hero, whereas I want it to effect all of the units owned by that player. so wouldn't it be wrong to set it to the custom value of attacking unit?

also - could you check the edit on my previous pst (if you didn't already):pgrin:

thanks!!!
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
Oh, if you want ALL units owned by Player X to take more damage from units owned by Player Y then you're dealing with Players and not units.

Custom value is of no use here, instead use Player Numbers as the Indexes in your Grudge variables.

Set PN = (Player number of (Triggering Player))
Set GrudgeOwner[PN] = (Triggering player)

etc...

Then in your damage trigger you get the Player Number of the owner of DamageEventSource.

If owner of DamageEventTarget equal to GrudgeTarget[PN] then deal bonus damage

You don't even need GrudgeOwner. GrudgeCaster is optional depending on how you want it to work.

I'm not sure how you want this to work though, if you want it so that a player can have Grudges against more than 1 player at a time you can use a Player Group instead.

Then add GrudgeTarget to this group upon casting the spell like: Add GrudgeTarget to GrudgeForce[PN]. Then in the damage trigger check to see if owner of DamageEventTarget is in GrudgeForce[PN].
 
Last edited:
Level 21
Joined
Mar 29, 2020
Messages
1,237
You're referencing CV without setting it in the damage trigger.

Current method:
2) Your current method will update the effects of Grudge when you level up the skill. So say you cast level 1 Grudge on an enemy (8% bonus damage), then spend 2 skill points into Grudge, the enemy player will now take 24% bonus damage despite the fact that it was a Level 1 Grudge that was cast on them.

That was intentional. it's kind of like a passive ability where you choose the one player it effects so that is fine.

Oh, if you want ALL units owned by Player X to take more damage from units owned by Player Y then you're dealing with Players and not units.

Custom value is of no use here, instead use Player Numbers as the Indexes in your Grudge variables.

Set PN = (Player number of (Triggering Player))
Set GrudgeOwner[PN] = (Triggering player)

etc...

Then in your damage trigger you get the Player Number of the owner of DamageEventSource.

I really have a knack for overcomplicating things lol
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
actually, that makes me lose the option to easily check the level of the ability for the caster. is there any reason my trigger from post #9 wont work?

EDIT: for clarity's sake: this is an ability that someone can only cast on 1 enemy, and then have it work like a passive against them until casted on someone else. only 1 targt at a time.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
This is what I ended up with, I think I'm set. thanks!! (and I'm starting a separate thread about the buff... I feel like it's really a different subject)

  • Grudge
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Grudge
    • Actions
      • Set PN = (Player number of (Triggering player))
      • Set GrudgeCaster[PN] = (Triggering unit)
      • Set GrudgeOwner[PN] = (Triggering player)
      • Set GrudgeTarget[PN] = (Owner of (Target unit of ability being cast))
  • Grudge damage add
    • Events
      • Game - DamageModifierEvent becomes Equal to 1.00
    • Conditions
    • Actions
      • Set PN = (Player number of (Owner of DamageEventSource))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of DamageEventTarget) Equal to GrudgeTarget[PN]
          • (Owner of DamageEventSource) Equal to GrudgeOwner[PN]
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Grudge for GrudgeCaster[PN]) Equal to 1
            • Then - Actions
              • Set DamageEventAmount = (DamageEventAmount x 1.08)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Grudge for GrudgeCaster[PN]) Equal to 2
                • Then - Actions
                  • Set DamageEventAmount = (DamageEventAmount x 1.16)
                • Else - Actions
                  • Set DamageEventAmount = (DamageEventAmount x 1.24)
        • Else - Actions
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
You can't edit the text of a buff with triggers.

For applying the buff, you can use a Dummy to apply a buff to a unit with something like Slow. Or add a hidden ability to the unit (like a self-targeting Devotion Aura) that applies the buff. The Aura is undispellable which may or may not be wanted.
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
If you want something more complicated you can use custom UI: UI: Frames and Tooltips
is there any way to do this with GUI?

I just want to make a small icon (ReplaceableTextures\CommandButtons\BTNBerserk.blp) that will sit in an unused corner of the screen for the relevant player and display the text (either when you hover your mouse over it or just next to it) player X has a grudge against you/you have a grudge against player Y.

I feel like this is way above my paygrade...
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
It has to be done in Jass/Lua. Technically Jass is accessible in GUI, that's what Custom script is afterall.

I attached a map I had sitting around. Might be able to open it idk.

This map has GUI examples of interacting with frames through Custom Script. It was designed to hide all of the default UI.

It's not really that useful besides that.
 

Attachments

  • UI GUI.w3x
    17.4 KB · Views: 19

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
Well, you need to look up UI tutorials like the one I linked (edit: that one was for Lua, look for Jass tutorials). Then use Custom Script to basically re-create the code but in GUI form.

OR, learn how to use a bit of Jass scripting. It's not that difficult, you don't need to master all of it in order to get the frames working. [JASS/AI] - UI: Create a TextButton

A lot of this stuff you can just copy and paste from people's work and then tweak yourself.

Make sure you use the JASS ones, I think I linked you a Lua example earlier. Tour map uses Jass (wc3's default language).
 
Last edited:
Level 21
Joined
Mar 29, 2020
Messages
1,237
this is my mediocre method (just texting the player) -

  • Actions
    • Set Temp_PlayerGroup = (Player group(GrudgeTarget[PN]))
    • Game - Display to Temp_PlayerGroup for 30.00 seconds the text: ((Name of (Triggering player)) + has a grudge against you. His armies fight you with a passion and do extra damage to your units. )
    • Custom script: call DestroyForce(udg_Temp_PlayerGroup)

but how would I target the player who just got switched (the one who used to be GrudgeTarget[PN] but is not anymore) to let them know they are not "grudged" anymore?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,511
Before setting a new GrudgeTarget, display a message to the old GrudgeTarget.

  • Example
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Set VariableSet PN = (Player number of (Triggering player))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GrudgeTarget[PN] Not equal to Neutral Extra
          • (Owner of (Target unit of ability being cast)) Not equal to GrudgeTarget[PN]
        • Then - Actions
          • -------- Send message to old GrudgeTarget --------
        • Else - Actions
      • Set VariableSet GrudgeTarget[PN] = (Owner of (Target unit of ability being cast))
Then set the default value in the Variable editor (Control + B) for GrudgeTarget to some Player that is untargetable. In my example I use Neutral Extra. Note: Variables are bugged at the moment, so make sure you set the default value in the actual Variable Editor and nowhere else.

This way, GrudgeTarget[PN] by default will be set to Neutral Extra.

This is useful since we know if it's set to Neutral Extra then you haven't used the ability yet. And if you haven't used the ability yet then there is no previous GrudgeTarget.

You should also do nothing if you target a player that you already have a Grudge against.
 
Status
Not open for further replies.
Top