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

[Solved] Multiplicative Stacking Evasion - MUI

Status
Not open for further replies.
Level 4
Joined
Sep 25, 2018
Messages
81
I have been making an evasion system where all evasion stacks multiplicatively with each other.

So all Heroes start with a base evasion stat (Humans gets 15% and so on). Every 10 agility points, the Hero gains 1% evasion (This part is working correctly). I am now making a start on adding evasion items now. Planning on having three different evasion items (+15%, +25% and +35%). These items should all stack multiplicatively with themselves and all the other evasion stats as well.

The problem I have is detecting the number of items of a certain type a unit has in its inventory.

So lets say a Hero is carrying three Talisman of Evasion's, so that would be "1 - ( 1 - 0.15 ) x ( 1 - 0.15 ) x ( 1 - 0.15 )" giving a total of 0.386 or +38.6% evasion. This would then be multiplied on top of the Heroes base evasion and their agility evasion. Instead of having to write out ( 1 - 0.15 ) for every separate item the best way to write this is "( 1 - 0.15 ) ^ (number of items of type held in inventory)".

I cannot find a good method for detecting this number and was wondering if anyone had any advice. I made an attempt on the item part of the trigger, but it was a mess so I removed it so you can view my current trigger easier.

  • Evasion
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • True Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Racial Passive (Human) for (Triggering unit)) Greater than or equal to 1
        • Then - Actions
          • Set VariableSet E_RacialPassive = (1.00 - 0.10)
          • Set VariableSet E_AgilityBonus = (1.00 - ((Real((Integer(((Real((Agility of (Triggering unit) (Include bonuses)))) x 0.10))))) x 0.01))
          • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Racial Passive (Human) )'s Real Level Field: Chance to Evade ('Eev1') of Level: 0 to (1.00 - (E_RacialPassive x (E_AgilityBonus x 1.00)))
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Racial Passive (Human - Horse) for (Triggering unit)) Greater than or equal to 1
            • Then - Actions
              • Set VariableSet E_RacialPassive = (1.00 - 0.05)
              • Set VariableSet E_AgilityBonus = (1.00 - ((Real((Integer(((Real((Agility of (Triggering unit) (Include bonuses)))) x 0.10))))) x 0.01))
              • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Racial Passive (Human - Horse) )'s Real Level Field: Chance to Evade ('Eev1') of Level: 0 to (1.00 - (E_RacialPassive x (E_AgilityBonus x 1.00)))
            • Else - Actions
 
Level 4
Joined
Sep 25, 2018
Messages
81
isnt the sensible way to do this to just have one variable that you multiply for each instance

ie. 10% evasion = multiply by 0.90

  • for each integer a from 1 to 6
    • if item in slot [integer a] = blah
      • set variable to blahblah
Do you mean something like this?

  • For each (Integer A) from 1 to 6, do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Item carried by (Triggering unit) in slot (Integer A)) Equal to (Item carried by (Triggering unit) of type Talisman of Evasion)
        • Then - Actions
          • Set VariableSet E_ItemToE = (Power((1.00 - 0.15), (Real((Integer A)))))
        • Else - Actions
This seems to give all sorts of strange results when testing. If only one Talisman of Evasion is picked up and placed in the bottom right inventory slot, it will act as if the Hero is actually carrying 6 Talisman of Evasions rather than just one. Hmmm....
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,012
No, that's not what they meant. doom is suggesting you start with a 'hitchance' value of 1, then multiply this sequentially by the hitchance of each item on the unit: hitchance = 1*(item hit 1)*(item hit 2)*(item hit 3) .. *(item hit 6). Then your evasion chance is 1-hitchance. It acts like 6 because you are always raising it to the 6th power (int A always loops up to 6). The easiest way to do this would be to store the evasion amounts for various items in a hashtable (with the item type as a key), then load them from the table and multiply out the evasion chance. Item/unit types can't be keys in GUI so you have to use some JASS to tell the game to save an integer that is really an item type:
  • Events
    • Time - Elapsed game-time is 0.50 seconds //don't use map init event
  • Conditions
  • Actions
    • Hashtable - Create a hashtable
    • Set EvasionHash = (Last created hashtable)
    • -------- --------
    • Set IType = Talisman of Evasion
    • Set Evasion = 0.15
    • Custom script: set udg_IType_Int = udg_Itype
    • Hashtable - Save (1.00 - Evasion) as 0 of IType_Int in EvasionHash
    • -------- --------
    • Set IType = Cloak of Everdodge
    • Set Evasion = 0.50
    • Custom script: set udg_IType_Int = udg_Itype
    • Hashtable - Save (1.00 - Evasion) as 0 of IType_Int in EvasionHash
    • -------- --------
    • Set IType = Elune's Circlet
    • Set Evasion = 0.10
    • Custom script: set udg_IType_Int = udg_Itype
    • Hashtable - Save (1.00 - Evasion) as 0 of IType_Int in EvasionHash
    • // etc.
  • Events
    • Unit - A unit is attacked
  • Conditions
  • Actions
    • Set hitchance = 1.00
    • For each (Integer A) from 1 to 6 do (Actions)
      • Loop - Actions
        • Set IType = (Item type of (Item carried by (Triggering Unit)) in slot (Integer A))
        • Custom script: set udg_IType_Int = udg_Itype
        • Set itemhit = (Load 0 of IType_Int) from EvasionHash
        • If (All conditions are true) then do (Then actions) else do (Else actions)
          • If - Conditions
            • itemhit greater than 0.00
          • Then - Actions
            • Set hitchance = (hitchance * itemhit)
          • Else - Actions
    • -------- do whatever you want with this value, at this point evasionchance = 1-hitchance but you're not yet adding in agility and racial bonuses --------
Overall I think it would be better to use a DDS and manually play a "dodge!" floating text instead of relying on setting the value of the evasion chance in an evasion ability, but that's just me.
 
Level 4
Joined
Sep 25, 2018
Messages
81
No, that's not what they meant. doom is suggesting you start with a 'hitchance' value of 1, then multiply this sequentially by the hitchance of each item on the unit: hitchance = 1*(item hit 1)*(item hit 2)*(item hit 3) .. *(item hit 6). Then your evasion chance is 1-hitchance. It acts like 6 because you are always raising it to the 6th power (int A always loops up to 6). The easiest way to do this would be to store the evasion amounts for various items in a hashtable (with the item type as a key), then load them from the table and multiply out the evasion chance. Item/unit types can't be keys in GUI so you have to use some JASS to tell the game to save an integer that is really an item type:
  • Events
    • Time - Elapsed game-time is 0.50 seconds //don't use map init event
  • Conditions
  • Actions
    • Hashtable - Create a hashtable
    • Set EvasionHash = (Last created hashtable)
    • -------- --------
    • Set IType = Talisman of Evasion
    • Set Evasion = 0.15
    • Custom script: set udg_IType_Int = udg_Itype
    • Hashtable - Save (1.00 - Evasion) as 0 of IType_Int in EvasionHash
    • -------- --------
    • Set IType = Cloak of Everdodge
    • Set Evasion = 0.50
    • Custom script: set udg_IType_Int = udg_Itype
    • Hashtable - Save (1.00 - Evasion) as 0 of IType_Int in EvasionHash
    • -------- --------
    • Set IType = Elune's Circlet
    • Set Evasion = 0.10
    • Custom script: set udg_IType_Int = udg_Itype
    • Hashtable - Save (1.00 - Evasion) as 0 of IType_Int in EvasionHash
    • // etc.
  • Events
    • Unit - A unit is attacked
  • Conditions
  • Actions
    • Set hitchance = 1.00
    • For each (Integer A) from 1 to 6 do (Actions)
      • Loop - Actions
        • Set IType = (Item type of (Item carried by (Triggering Unit)) in slot (Integer A))
        • Custom script: set udg_IType_Int = udg_Itype
        • Set itemhit = (Load 0 of IType_Int) from EvasionHash
        • If (All conditions are true) then do (Then actions) else do (Else actions)
          • If - Conditions
            • itemhit greater than 0.00
          • Then - Actions
            • Set hitchance = (hitchance * itemhit)
          • Else - Actions
    • -------- do whatever you want with this value, at this point evasionchance = 1-hitchance but you're not yet adding in agility and racial bonuses --------
Overall I think it would be better to use a DDS and manually play a "dodge!" floating text instead of relying on setting the value of the evasion chance in an evasion ability, but that's just me.
I tried it with Bribes DDS system and it turned out to be more of a headache when you take into account things like orb effects and such than doing it this way.

I think I found a method which works. I have tested it and it seems to be working as expected. Just wondering if you may see any glaring issues as you have more experience.

  • Actions
    • Set VariableSet E_ItemNumberToE = 0.00
    • For each (Integer A) from 1 to 6, do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Item-type of (Item carried by (Triggering unit) in slot (Integer A))) Equal to Talisman of Evasion
          • Then - Actions
            • Set VariableSet E_ItemNumberToE = (E_ItemNumberToE + 1.00)
          • Else - Actions
    • Set VariableSet E_ItemToE = (Power((1.00 - 0.15), E_ItemNumberToE))
Edit: So the trigger should look something like this.

  • Evasion
    • Events
      • Unit - A unit Is attacked
    • Conditions
      • True Equal to True
    • Actions
      • Set VariableSet E_ItemNumberToE = 0.00
      • For each (Integer A) from 1 to 6, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Item-type of (Item carried by (Triggering unit) in slot (Integer A))) Equal to Talisman of Evasion
            • Then - Actions
              • Set VariableSet E_ItemNumberToE = (E_ItemNumberToE + 1.00)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Racial Passive (Human) for (Triggering unit)) Greater than or equal to 1
        • Then - Actions
          • Set VariableSet E_RacialPassive = (1.00 - 0.10)
          • Set VariableSet E_AgilityBonus = (1.00 - ((Real((Integer(((Real((Agility of (Triggering unit) (Include bonuses)))) x 0.10))))) x 0.01))
          • Set VariableSet E_ItemToE = (Power((1.00 - 0.15), E_ItemNumberToE))
          • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Racial Passive (Human) )'s Real Level Field: Chance to Evade ('Eev1') of Level: 0 to (1.00 - (E_RacialPassive x (E_AgilityBonus x (E_ItemToE x 1.00))))
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Racial Passive (Human - Horse) for (Triggering unit)) Greater than or equal to 1
            • Then - Actions
              • Set VariableSet E_RacialPassive = (1.00 - 0.05)
              • Set VariableSet E_AgilityBonus = (1.00 - ((Real((Integer(((Real((Agility of (Triggering unit) (Include bonuses)))) x 0.10))))) x 0.01))
              • Set VariableSet E_ItemToE = (Power((1.00 - 0.15), E_ItemNumberToE))
              • Ability - Set Ability: (Unit: (Triggering unit)'s Ability with Ability Code: Racial Passive (Human - Horse) )'s Real Level Field: Chance to Evade ('Eev1') of Level: 0 to (1.00 - (E_RacialPassive x (E_AgilityBonus x (E_ItemToE x 1.00))))
            • Else - Actions
 
Last edited:
Level 23
Joined
Oct 18, 2008
Messages
937
DDS can't replicate evasion and anyone who tells you otherwise is a lying liar.

you are making yourself a lot of headache by saving the modifiers separately. pyro's system looks good.

Item/unit types can't be keys in GUI so you have to use some JASS to tell the game to save an integer that is really an item type

you could turn it into a string key
 
How is avoiding damage by setting DDS damage to 0 not the same...? Other events that trigger off of dealt damage could be avoided with proper planning.
In theory yes, but there is a minor difference: While a dodged attack is known at attack time, a triggered one is only known on the event damage.
Maybe not a problem for most things, but can be problematic.

Edit: Also orb abilities/attack effects would act differently I guess.
 
Level 20
Joined
Jul 12, 2010
Messages
1,717
I have a whole different suggestion to make, if you don't mind having the icon just make an evasion ability with 100 levels, each one representing a 1% dodge like this:
upload_2020-2-14_16-31-45.png
and then just increase the levels when an item is picked up
  • Item Pickup
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • ((Triggering unit) is A Hero) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Item-type of (Item being manipulated)) Equal to Talisman of Evasion
        • Then - Actions
          • Unit - Set level of Evasion for (Triggering unit) to ((Level of Evasion for (Triggering unit)) + 10)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Item-type of (Item being manipulated)) Equal to Kelen's Dagger of Escape
            • Then - Actions
              • Unit - Set level of Evasion for (Triggering unit) to ((Level of Evasion for (Triggering unit)) + 18)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Item-type of (Item being manipulated)) Equal to Spider Ring
                • Then - Actions
                  • Unit - Set level of Evasion for (Triggering unit) to ((Level of Evasion for (Triggering unit)) + 3)
                • Else - Actions
Also don't forget to make a trigger for when dropping things(was in a hurry so I didn' do it)

Although you need to put extra effort into avoiding values over 100 that will cause problems.

I think this is by far the easiest and laziest way to do it lol
 
Level 4
Joined
Sep 25, 2018
Messages
81
I have a whole different suggestion to make, if you don't mind having the icon just make an evasion ability with 100 levels, each one representing a 1% dodge like this:
and then just increase the levels when an item is picked up
  • Item Pickup
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • ((Triggering unit) is A Hero) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Item-type of (Item being manipulated)) Equal to Talisman of Evasion
        • Then - Actions
          • Unit - Set level of Evasion for (Triggering unit) to ((Level of Evasion for (Triggering unit)) + 10)
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Item-type of (Item being manipulated)) Equal to Kelen's Dagger of Escape
            • Then - Actions
              • Unit - Set level of Evasion for (Triggering unit) to ((Level of Evasion for (Triggering unit)) + 18)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Item-type of (Item being manipulated)) Equal to Spider Ring
                • Then - Actions
                  • Unit - Set level of Evasion for (Triggering unit) to ((Level of Evasion for (Triggering unit)) + 3)
                • Else - Actions
Also don't forget to make a trigger for when dropping things(was in a hurry so I didn' do it)

Although you need to put extra effort into avoiding values over 100 that will cause problems.

I think this is by far the easiest and laziest way to do it lol
I have tried this method in the past and it can cause serious frame rate drops. Even when only one unit has the 100 level ability.

tbh, the trigger that I have now is working without any issues so far. Just need to do some stress testing.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,537
The way I would go about it is keeping track of the Heros agility throughout the game:

A unit acquires an item
Item equal to evasion 15%
Set unit's EvasionStat equal to EvasionStat + 15
Set Ability Chance to Evade to EvasionStat

A unit loses an item
-15 Evasion
Calculate agility/evasion

A unit gains a level:
Calculate agility/evasion

A unit enters map:
Calculate agility/evasion

A unit starts the effects of an ability
Ability equal to Agility Buff
Increase target unit's EvasionStat by 50
Calculate agility/evasion

These Events occur way less often than 'A unit is attacked", plus you'll be able to get the Evasion stat of your unit at any given moment.

Then again, this might be overkill.
 
Status
Not open for further replies.
Top