• 🏆 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!
  • ✅ The POLL for Hive's Texturing Contest #33 is OPEN! Vote for the TOP 3 SKINS! 🔗Click here to cast your vote!

Unique, Non-Stacking Orb Effects Trigger System

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
Theory:
In Warcraft 3, orb effects are unique meaning they cannot stack with other orbs and only one of them can be active at a time. The priority of the orb used depends on which slot it is in (The orb from the slot with a higher priority will be used). If an attacking unit has several orbs, only one of them can be active. All orbs have the same priority. If there are several orbs in the inventory, their position determines which one is active.

Request:
I need to create a system that will make my Orb work like other orbs = it will be unique. I have created a trigger that is responsible for the effect of my orb. Now I would like my orb to act like other orbs. This can be achieved by adding a condition in my trigger that checks whether the orb should work or not (depending on the setting of orb type items in the inventory). My orb should only work if it has the highest priority (i.e., there are no other orb type items with higher priority in the hero's inventory). If the orb is in the first slot then there is no problem because we know that no other item can have a higher priority. If the hero doesn't have any other orb-type item there is no problem either, the orb should work because it is the only one of its kind. The problem arises when we have other orb-type items in the inventory, then we should check if my orb has a higher priority than those. If the orb should not work because the other orbs have a higher priority then you should make a variable (semaphore) that will make the trigger responsible for the orb's action not trigger. Does anyone have an idea how to do this or could create such a system? I have too many dilemmas when it comes to how to store variables and how to make an implementation. I would be very grateful


1716201993128.png
 
Level 3
Joined
Sep 6, 2016
Messages
6
  • Trigger
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet NumberOfOrbs = 0
      • Set VariableSet Hero = Paladin 0000 <gen>
      • -------- Checking if there is more than 1 orb, could add more orb types --------
      • Set VariableSet ItemType = Orb of Frost
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Item-type of (Item carried by Hero in slot 1)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 2)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 3)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 4)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 5)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 6)) Equal to ItemType
        • Then - Actions
          • Set VariableSet NumberOfOrbs = (NumberOfOrbs + 1)
        • Else - Actions
      • Set VariableSet ItemType = Orb of Lightning
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Item-type of (Item carried by Hero in slot 1)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 2)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 3)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 4)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 5)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 6)) Equal to ItemType
        • Then - Actions
          • Set VariableSet NumberOfOrbs = (NumberOfOrbs + 1)
        • Else - Actions
      • Set VariableSet ItemType = Orb of Darkness
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Item-type of (Item carried by Hero in slot 1)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 2)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 3)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 4)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 5)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 6)) Equal to ItemType
        • Then - Actions
          • Set VariableSet NumberOfOrbs = (NumberOfOrbs + 1)
        • Else - Actions
      • Set VariableSet ItemType = Orb of Fire
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Item-type of (Item carried by Hero in slot 1)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 2)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 3)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 4)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 5)) Equal to ItemType
              • (Item-type of (Item carried by Hero in slot 6)) Equal to ItemType
        • Then - Actions
          • Set VariableSet NumberOfOrbs = (NumberOfOrbs + 1)
        • Else - Actions
      • -------- I there is more then ... --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • NumberOfOrbs Greater than 1
        • Then - Actions
          • For each (Integer A) from 2 to 6, do (Actions)
            • Loop - Actions
              • Set VariableSet Item[(Integer A)] = (Item carried by Hero in slot (Integer A))
              • Set VariableSet ItemType = (Item-type of (Item carried by Hero in slot (Integer A)))
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • (Custom value of Item[(Integer A)]) Equal to 0
                      • Or - Any (Conditions) are true
                        • Conditions
                          • ItemType Equal to Orb of Frost
                          • ItemType Equal to Orb of Lightning
                          • ItemType Equal to Orb of Darkness
                          • ItemType Equal to Orb of Fire
                • Then - Actions
                  • Item - For Item: Item[(Integer A)], Remove Ability: Orb ability, should add another check for a specific orb type to define ability
                  • Item - Set the custom value of Item[(Integer A)] to 1
                • Else - Actions
        • Else - Actions
          • For each (Integer A) from 2 to 6, do (Actions)
            • Loop - Actions
              • Set VariableSet Item[(Integer A)] = (Item carried by Hero in slot (Integer A))
              • Set VariableSet ItemType = (Item-type of (Item carried by Hero in slot (Integer A)))
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • And - All (Conditions) are true
                    • Conditions
                      • (Custom value of Item[(Integer A)]) Equal to 1
                      • Or - Any (Conditions) are true
                        • Conditions
                          • ItemType Equal to Orb of Frost
                          • ItemType Equal to Orb of Lightning
                          • ItemType Equal to Orb of Darkness
                          • ItemType Equal to Orb of Fire
                • Then - Actions
                  • Item - For Item: Item[(Integer A)], Add Ability: Like with Remove ability, do item type test for example if itemtype is orb of fire then delete orb of fire ability and so on
                  • Item - Set the custom value of Item[(Integer A)] to 0
                • Else - Actions
That's how I would approach this problem, but deleting ability might also substract attack damage bonus. Splitting damage bonus and effect to a different item ability and removing just effect ability via trigger could solve this.
 
Last edited:

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
By your description it sounds like your main focus is on ITEM orb effects.

I imagine the best solution here would be to trigger every orb effect yourself.

Step 1:
Create your different Items that offer orb effects. Put them in their own category so you can easily detect them in your triggers.

Step 2:
Setup your variable data using Arrays at the start of the game. Track each type of item that has an orb effect in an Item-Type array, track it's priority in an Integer array, and track the trigger that holds the "actions to run on dealing damage" in a Trigger array. Their [indexes] should match so you can pair this data together.

Step 3:
Upon acquiring an Orb effect item, Loop over your Array data from before by using a For Loop. Once you find the [index] of the item you acquired, check to see if it's priority is higher than your hero's current priority value, and if it is you can set this as the hero's new "orb index":
  • For each integer (Index) from 1 to X do (Actions)
    • Loop - Actions
      • If if's a higher priority item then...
        • Set Variable CV = (Custom value of (Hero manipulating item))
        • Set Variable Hero_Orb_Index[CV] = Index
^ This is using the Unit Indexing method in order to store data directly to our hero.

Step 4:
Upon losing an Orb effect item, reset the hero's Orb_Index to 0 and Loop over their inventory to find the new highest priority item. If none are found, the Orb_Index will remain at 0, otherwise, it will be set to the Index of the highest priority item it could find.

Now whenever your hero deals damage with a basic attack you can simply run the trigger associated with it's highest priority orb effect:
  • Events
    • Unit - A unit Takes damage
  • Conditions
    • (Damage was from a normal attack) Equal to True
    • Hero_Orb_Index[(Custom value of (Damage source))] Greater than 0
  • Actions
    • Set Variable CV = (Custom value of (Damage source))
    • Trigger - Run Hero_Orb_Trigger[Hero_Orb_Index[CV]]
If on a patch below 1.31, you will have to rely on a Damage Engine to get access to this sort of trigger in GUI.
 
Last edited:

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
By your description it sounds like your main focus is on ITEM orb effects.

I imagine the best solution here would be to trigger every orb effect yourself.

Step 1:
Create your different Items that offer orb effects. Put them in their own category so you can easily detect them in your triggers.

Step 2:
Setup your variable data using Arrays at the start of the game. Track each type of item that has an orb effect in an Item-Type array, track it's priority in an Integer array, and track the trigger that holds the "actions to run on dealing damage" in a Trigger array. Their [indexes] should match so you can pair this data together.

Step 3:
Upon acquiring an Orb effect item, Loop over your Array data from before by using a For Loop. Once you find the [index] of the item you acquired, check to see if it's priority is higher than your hero's current priority value, and if it is you can set this as the hero's new "orb index":
  • For each integer (Index) from 1 to X do (Actions)
    • Loop - Actions
      • If if's a higher priority item then...
        • Set Variable CV = (Custom value of (Hero manipulating item))
        • Set Variable Hero_Orb_Index[CV] = Index
^ This is using the Unit Indexing method in order to store data directly to our hero.

Step 4:
Upon losing an Orb effect item, reset the hero's Orb_Index to 0 and Loop over their inventory to find the new highest priority item. If none are found, the Orb_Index will remain at 0, otherwise, it will be set to the Index of the highest priority item it could find.

Now whenever your hero deals damage with a basic attack you can simply run the trigger associated with it's highest priority orb effect:
  • Events
    • Unit - A unit Takes damage
  • Conditions
    • (Damage was from a normal attack) Equal to True
    • Hero_Orb_Index[(Custom value of (Damage source))] Greater than 0
  • Actions
    • Set Variable CV = (Custom value of (Damage source))
    • Trigger - Run Hero_Orb_Trigger[Hero_Orb_Index[CV]]
If on a patch below 1.31, you will have to rely on a Damage Engine to get access to this sort of trigger in GUI.
Are we able to detect a change in the position of an item in the inventory? I mean someone can pick up 2 orbs and then swap them places. Will we be able to detect this or are we forced to check it separately with each hero attack?
 

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
By your description it sounds like your main focus is on ITEM orb effects.

I imagine the best solution here would be to trigger every orb effect yourself.

Step 1:
Create your different Items that offer orb effects. Put them in their own category so you can easily detect them in your triggers.

Step 2:
Setup your variable data using Arrays at the start of the game. Track each type of item that has an orb effect in an Item-Type array, track it's priority in an Integer array, and track the trigger that holds the "actions to run on dealing damage" in a Trigger array. Their [indexes] should match so you can pair this data together.

Step 3:
Upon acquiring an Orb effect item, Loop over your Array data from before by using a For Loop. Once you find the [index] of the item you acquired, check to see if it's priority is higher than your hero's current priority value, and if it is you can set this as the hero's new "orb index":
  • For each integer (Index) from 1 to X do (Actions)
    • Loop - Actions
      • If if's a higher priority item then...
        • Set Variable CV = (Custom value of (Hero manipulating item))
        • Set Variable Hero_Orb_Index[CV] = Index
^ This is using the Unit Indexing method in order to store data directly to our hero.

Step 4:
Upon losing an Orb effect item, reset the hero's Orb_Index to 0 and Loop over their inventory to find the new highest priority item. If none are found, the Orb_Index will remain at 0, otherwise, it will be set to the Index of the highest priority item it could find.

Now whenever your hero deals damage with a basic attack you can simply run the trigger associated with it's highest priority orb effect:
  • Events
    • Unit - A unit Takes damage
  • Conditions
    • (Damage was from a normal attack) Equal to True
    • Hero_Orb_Index[(Custom value of (Damage source))] Greater than 0
  • Actions
    • Set Variable CV = (Custom value of (Damage source))
    • Trigger - Run Hero_Orb_Trigger[Hero_Orb_Index[CV]]
If on a patch below 1.31, you will have to rely on a Damage Engine to get access to this sort of trigger in GUI.
My orb = Orb of Kiljaeden
  • ORB
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • IsDamageAttack Equal to True
      • (DamageEventSource is A Hero) Equal to True
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource).) Equal to True
      • (DamageEventSource has an item of type Orb of Kil'jaeden) Equal to True
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • -------- THIS LOOP WILL CHECK EVERY SLOT IN HERO INVENTORY --------
          • For each (Integer A) from 1 to 6, do (Actions)
            • Loop - Actions
              • -------- THIS LOOP WILL CHECK FOR EVERY ORB-TYPE ITEM --------
              • For each (Integer B) from 0 to 13, do (Actions)
                • Loop - Actions
                  • -------- THIS CONDITION WILL DETECT WHENEVER HERO HAS ORB IN THE INVENTORY --------
                  • -------- ABS(INT A - 7) GIVES US LOOP FROM 6 TO 1 SO THE LAST ASIGNED ITEM WILL BE FROM THE HIGHEST PRIRITY SLOT --------
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Item-type of (Item carried by DamageEventSource in slot (Abs(((Integer A) - 7))))) Equal to UniqueEffectItem[(Integer B)]
                    • Then - Actions
                      • -------- THIS ACTION WILL ASIGN ORB-TYPE ITEM DETECTED IN SPECIFIC SLOT TO HighestPriorityOrb VARIABLE --------
                      • Set VariableSet HighesPriorityOrb = UniqueEffectItem[(Integer B)]
                    • Else - Actions
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • HighesPriorityOrb Equal to Orb of Kil'jaeden
        • Then - Actions
          • -------- TRIGGER MY ORB EFFECT --------
        • Else - Actions
1716238968287.png

I created a solution but the problem is that I do not know if it is oso efficient. Doesn't it slow down the game too much? Because for each hero attack I check each of the 6 slots for 14 items. If I detect an orb type item in any slot I assign it to a variable, I do this redundantly but I move up the pririty of the slots so the last item assigned at the end will be the one with the highest priority. Could you tell me which of the solutions presented is the most efficient and if my solution is acceptable in terms of performance in the game? Or what to do to make it more efficient?
 

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
So if the priority system is related to the inventory slot then it's even more simple.

Step 3 becomes:
Upon acquiring an Orb effect item, first check if Hero_orb_Index[CV] is equal to 0. If it is, then Loop over the Array of items and store the Index of the one that matches. If it's not equal to 0, then Loop over the Inventory and find the first slot that is of the Orb "classification" and store that Index.

Step 4 becomes:
Upon losing an Orb effect item, Set Hero_orb_Index[CV] to 0, then Loop over the Inventory and find the first slot that is of the Orb "classification" and store that Index.

This will ensure that Hero_orb_Index[] is always equal to the correct [index].

You shouldn't be checking for the Orb items each time the hero deals damage. You only need to check for these items when the hero's inventory changes (acquires item/loses item) and keep track of the highest priority orb at that time. Like in my example, you would run a specific trigger based on which Orb has priority:
  • ORB
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • IsDamageAttack Equal to True
      • Hero_Orb_Index[(Custom value of DamageEventSource)] Greater than 0
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource).) Equal to True
    • Actions
      • Set Variable CV = (Custom value of DamageEventSource)
      • Trigger - Run Hero_Orb_Trigger[Hero_Orb_Index[CV]]
  • Events
    • Time - Elapsed game time is 0.00 seconds
  • Conditions
  • Actions
    • Set Variable Hero_Orb_Item[1] = Orb of Bonus Damage
    • Set Variable Hero_Orb_Trigger[1] = OnHeroDamage Orb of Bonus Damage <gen>
    • Set Variable Hero_Orb_Item[2] = Orb of Fire
    • Set Variable Hero_Orb_Trigger[2] = OnHeroDamage Orb of Fire <gen>
    • -------- Continue this pattern for each type of orb ---------
  • OnHeroDamage Orb of Bonus Damage
    • Events
  • Conditions
    • Actions
      • Set Variable DamageEventAmount = (DamageEventAmount + 100.00)
  • OnHeroDamage Orb of Fire
    • Events
  • Conditions
    • Actions
      • -------- Deal splash damage or whatever it is that the orb of fire is supposed to do --------
 
Last edited:

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
So if the priority system is related to the inventory slot then it's even more simple.

Step 3 becomes:
Upon acquiring an Orb effect item, first check if Hero_orb_Index[CV] is equal to 0. If it is, then Loop over the Array of items and store the Index of the one that matches. If it's not equal to 0, then Loop over the Inventory and find the first slot that is of the Orb "classification" and store that Index.

Step 4 becomes:
Upon losing an Orb effect item, Set Hero_orb_Index[CV] to 0, then Loop over the Inventory and find the first slot that is of the Orb "classification" and store that Index.

This will ensure that Hero_orb_Index[] is always equal to the correct [index].

You shouldn't be checking for the Orb items each time the hero deals damage. You only need to check for these items when the hero's inventory changes (acquires item/loses item) and keep track of the highest priority orb at that time. Like in my example, you would run a specific trigger based on which Orb has priority:
  • ORB
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • IsDamageAttack Equal to True
      • Hero_Orb_Index[(Custom value of DamageEventSource)] Greater than 0
      • (DamageEventTarget belongs to an enemy of (Owner of DamageEventSource).) Equal to True
    • Actions
      • Set Variable CV = (Custom value of DamageEventSource)
      • Trigger - Run Hero_Orb_Trigger[Hero_Orb_Index[CV]]
  • Events
    • Time - Elapsed game time is 0.00 seconds
  • Conditions
  • Actions
    • Set Variable Hero_Orb_Item[1] = Orb of Bonus Damage
    • Set Variable Hero_Orb_Trigger[1] = OnHeroDamage Orb of Bonus Damage <gen>
    • Set Variable Hero_Orb_Item[2] = Orb of Fire
    • Set Variable Hero_Orb_Trigger[2] = OnHeroDamage Orb of Fire <gen>
    • -------- Continue this pattern for each type of orb ---------
  • OnHeroDamage Orb of Bonus Damage
    • Events
  • Conditions
    • Actions
      • Set Variable DamageEventAmount = (DamageEventAmount + 100.00)
  • OnHeroDamage Orb of Fire
    • Events
  • Conditions
    • Actions
      • -------- Deal splash damage or whatever it is that the orb of fire is supposed to do --------
What if I swap orb positions in my inventory? Like when I swap 2 orbs with each other, this will change their priority. Can this be detected by Event?
 

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
What if I swap orb positions in my inventory? Like when I swap 2 orbs with each other, this will change their priority. Can this be detected by Event?
I believe that swapping items is detected with Orders. So you'll just need an additional trigger that repeats Step 4 upon detecting one of these orders. Of course update the Event Responses accordingly.
 

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
The angel says: Just write your own game engine, ez pz.

Anyway, here's an example map showcasing my suggested method (with some tweaks to keep it as simple as possible). Hopefully you can open it, if you even care to use it in the first place. No worries either way, it didn't take long to make and maybe someone else will find it useful.
 

Attachments

  • Custom Orb Effects 1.w3m
    73.6 KB · Views: 4
Last edited:

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
The angel says: Just write your own game engine, ez pz.

Anyway, here's an example map showcasing my suggested method (with some tweaks to keep it as simple as possible). Hopefully you can open it, if you even care to use it in the first place. No worries either way, it didn't take long to make and maybe someone else will find it useful.
I have tested your system and of course everything works flawlessly and is very readable and efficient. I tried throughout the day to reproduce what you wrote however I did not get very far.
My write-ups:
  • Orb
    • Events
      • Unit - A unit Acquires an item
    • Conditions
    • Actions
      • For each (Integer A) from 0 to 12, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Item-type of (Item being manipulated)) Equal to UniqueEffectItems[(Integer A)]
              • Semaphore Equal to True
            • Then - Actions
              • Set VariableSet CV = (Custom value of (Hero manipulating item))
              • For each (Integer B) from 1 to 6, do (Actions)
                • Loop - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Semaphore Equal to True
                    • Then - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • Hero_Orb_Index[CV] Equal to 0
                        • Then - Actions
                          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                            • If - Conditions
                              • (Item-type of (Item carried by (Hero manipulating item) in slot (Integer B))) Equal to (Item-type of (Item being manipulated))
                            • Then - Actions
                              • Set VariableSet Hero_Orb_Index[CV] = (Integer B)
                              • Set VariableSet Semaphore = False
                            • Else - Actions
                        • Else - Actions
                          • For each (Integer A) from 0 to 12, do (Actions)
                            • Loop - Actions
                              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                                • If - Conditions
                                  • Semaphore Equal to True
                                  • (Item-type of (Item carried by (Hero manipulating item) in slot (Abs(((Integer B) - 7))))) Equal to UniqueEffectItems[(Integer A)]
                                • Then - Actions
                                  • Set VariableSet Hero_Orb_Index[CV] = (Integer B)
                                  • Set VariableSet Semaphore = False
                                • Else - Actions
                    • Else - Actions
            • Else - Actions
      • Set VariableSet Semaphore = True
I have also verified that it is indeed possible to check for changes to items in the inventory and even return the slot number that was changed.
852002 means you move it to slot 1
852003 means you move it to slot 2
852004 means you move it to slot 3
852005 means you move it to slot 4
852006 means you move it to slot 5
852007 means you move it to slot 6

  • Move Item
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
    • Actions
      • Custom script: set udg_i = GetIssuedOrderId()
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • i Greater than or equal to 852002
              • i Less than or equal to 852007
        • Then - Actions
          • Game - Display to (All players) the text: (You move the item to Slot: + (String((i - 852001))))
        • Else - Actions
1716334614660.png

In any case, I am very grateful, it would have taken me a very long time and I probably wouldn't have done it well anyway. Thank you very much I appreciate what you did, it will be used in the Mini Dota game and the community will appreciate it too.

However, there is a very important thing that I left out when creating this post, namely:

Arrows have the highest priority
In my game there are only classic heroes so we only have 4 types of arrows (searing, black, frost arrows and incinerate). Bullets shouldn't work at the same time as arrows so a few things should also be monitored:
1. whether the hero has autocast enabled on the arrows
2. whether the hero has used maual arrow casting for the attack

I tried to implement it for incinerate in this way:
  • Incinerate Learns a skill
    • Events
      • Unit - A unit Learns a skill
    • Conditions
      • (Learned Hero Skill) Equal to Incinerate (new)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Level of Incinerate (new) for (Triggering unit)) Greater than 1
        • Then - Actions
          • Set VariableSet IdTarget = (Triggering unit)
          • Set VariableSet IsAutocast = (Load 0 of (Key IdTarget.) from TablaHash.)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • IsAutocast Equal to 1
            • Then - Actions
              • Unit - Set level of Incinerate (Arrow Ability) for (Triggering unit) to (Level of Incinerate (new) for (Triggering unit))
            • Else - Actions
        • Else - Actions
          • Hashtable - Save 1 as 1 of (Key (Triggering unit).) in TablaHash.
  • Incinerate On Off
    • Events
      • Unit - A unit Is issued an order with no target
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Issued order) Equal to (Order(unflamingarrows))
          • (Issued order) Equal to (Order(flamingarrows))
      • (Level of Incinerate (new) for (Triggering unit)) Greater than 0
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Issued order) Equal to (Order(flamingarrows))
        • Then - Actions
          • -------- Autocast ON --------
          • Hashtable - Save 1 as 0 of (Key (Triggering unit).) in TablaHash.
          • -------- CanChange False --------
          • Hashtable - Save 0 as 1 of (Key (Triggering unit).) in TablaHash.
          • -------- Add Incinerate and Set Level --------
          • Unit - Add Incinerate (Arrow Ability) to (Triggering unit)
          • Unit - Set level of Incinerate (Arrow Ability) for (Triggering unit) to (Level of Incinerate (new) for (Triggering unit))
        • Else - Actions
          • -------- Autocast OFF --------
          • Hashtable - Save 0 as 0 of (Key (Triggering unit).) in TablaHash.
          • -------- CanChange True --------
          • Hashtable - Save 1 as 1 of (Key (Triggering unit).) in TablaHash.
          • -------- Remove Incinerate --------
          • Unit - Remove Incinerate (Arrow Ability) from (Triggering unit)
  • Incinerate Fix
    • Events
      • Unit - A unit Starts the effect of an ability
      • Unit - A unit Is attacked
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Level of Incinerate (new) for (Attacking unit)) Greater than or equal to 1
          • (Ability being cast) Equal to Incinerate (new)
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target unit of ability being cast) Equal to No unit
        • Then - Actions
          • -------- Autoattack by Firelord --------
          • Set VariableSet IdTarget = (Attacking unit)
          • Set VariableSet IsAutocast = (Load 0 of (Key IdTarget.) from TablaHash.)
          • Set VariableSet CanChangeAutocast = (Load 1 of (Key IdTarget.) from TablaHash.)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • IsAutocast Equal to 1
              • CanChangeAutocast Equal to 1
            • Then - Actions
              • Unit - Remove Incinerate (Arrow Ability) from (Attacking unit)
              • -------- Autocast OFF --------
              • Hashtable - Save 0 as 0 of (Key IdTarget.) in TablaHash.
            • Else - Actions
        • Else - Actions
          • -------- Incinerate casted manually --------
          • Set VariableSet IdTarget = (Triggering unit)
          • Set VariableSet IsAutocast = (Load 0 of (Key IdTarget.) from TablaHash.)
          • Set VariableSet CanChangeAutocast = (Load 1 of (Key IdTarget.) from TablaHash.)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • IsAutocast Equal to 0
              • CanChangeAutocast Equal to 1
            • Then - Actions
              • Unit - Add Incinerate (Arrow Ability) to (Triggering unit)
              • Unit - Set level of Incinerate (Arrow Ability) for (Triggering unit) to (Level of Incinerate (new) for (Triggering unit))
              • -------- Autocast ON --------
              • Hashtable - Save 1 as 0 of (Key IdTarget.) in TablaHash.
            • Else - Actions
Do you have any idea how to keep track of whether the hero uses arrows that have a higher priority than the orb? This would make the Item Uniqueness system complite and ready.
 

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
These Attack-Autocast abilities have always been near impossible to get completely right. The user can toggle autocast at any time while an attack projectile is in flight. This means that you can toggle on searing arrows, launch a fiery attack with bonus damage, then turn it off a moment before the missile makes contact, and the Damage Event trigger will think that the ability is off and allow the item-based orb effects to trigger.

If you're fine with that user manipulation (it would be slightly annoying for the user to do consistently) then the solution is simple, check that the hero doesn't have any of these abilities toggled on in the Damage Event conditions. Of course they can also just manually cast the ability, so again, there's not much to do here without some unique system in place.
 
Last edited:

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
These Attack-Autocast abilities have always been near impossible to get completely right. The user can toggle autocast at any time that an attack projectile is in flight. This means that you can toggle on searing arrows, launch a fiery attack with bonus damage, then turn it off a moment before the missile makes contact, and the Damage Event trigger will think that the ability is off and allow the item-based orb effects to trigger.

If you're fine with that user manipulation (it would be slightly annoying for the user to do consistently) then the solution is simple, check that the hero doesn't have any of these abilities toggled on in the Damage Event conditions. Of course they can also just manually cast the ability, so again, there's not much to do here without some unique system in place.
I have no objection to such user manipulation. As you said it would be a bit annoying for the user to do it consistently. I have created a simple system that records the current state of auto-casting for a particular unit:

  • AutoCast[CV] = 0 // Autocast is OFF
  • AutoCast[CV] = 1 // Autocast is ON
  • Autocast On Off
    • Events
      • Unit - A unit Is issued an order with no target
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Issued order) Equal to (Order(incineratearrowon))
          • (Issued order) Equal to (Order(incineratearrowoff))
          • (Issued order) Equal to (Order(flamingarrows))
          • (Issued order) Equal to (Order(unflamingarrows))
          • (Issued order) Equal to (Order(blackarrowon))
          • (Issued order) Equal to (Order(blackarrowoff))
          • (Issued order) Equal to (Order(coldarrows))
          • (Issued order) Equal to (Order(coldarrowstarg))
    • Actions
      • Set VariableSet CV = (Custom value of (Triggering unit))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Or - Any (Conditions) are true
            • Conditions
              • (Issued order) Equal to (Order(incineratearrowon))
              • (Issued order) Equal to (Order(flamingarrows))
              • (Issued order) Equal to (Order(blackarrowon))
              • (Issued order) Equal to (Order(coldarrows))
        • Then - Actions
          • -------- Autocast ON --------
          • Set VariableSet AutoCast[CV] = 1
          • -------- CanChange False --------
          • Set VariableSet CanChange = False
        • Else - Actions
          • -------- Autocast OFF --------
          • Set VariableSet AutoCast[CV] = 0
          • -------- CanChange True --------
          • Set VariableSet CanChange = True
  • Manual Cast Autoattack
    • Events
      • Unit - A unit Starts the effect of an ability
      • Unit - A unit Is attacked
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Level of Incinerate (Arrow) for (Attacking unit)) Greater than or equal to 1
          • (Ability being cast) Equal to Incinerate (Arrow)
          • (Level of Searing Arrows for (Attacking unit)) Greater than or equal to 1
          • (Ability being cast) Equal to Searing Arrows
          • (Level of Black Arrow for (Attacking unit)) Greater than or equal to 1
          • (Ability being cast) Equal to Black Arrow
          • (Level of Frost Arrows for (Attacking unit)) Greater than or equal to 1
          • (Ability being cast) Equal to Frost Arrows
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Target unit of ability being cast) Equal to No unit
        • Then - Actions
          • -------- Autoattack Arrow --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • CanChange Equal to True
            • Then - Actions
              • -------- Autocast OFF --------
              • Set VariableSet CV = (Custom value of (Attacking unit))
              • Set VariableSet AutoCast[CV] = 0
            • Else - Actions
        • Else - Actions
          • -------- Manually Cast Arrow --------
          • -------- Autocast ON --------
          • Set VariableSet CV = (Custom value of (Triggering unit))
          • Set VariableSet AutoCast[CV] = 1
Not quite sure how to do this and I wanted to cover all cases:
1. detecting whether autocast is on/off
2. detecting if shots were thrown manually

I adjust these values accordingly for normal autocasts and for retraining where the hero could unlearn the ability.

I had to change the orders in the arrows abilities a bit because I don't quite know how it works.
1716375419832.png

I don't know why but I can't detect turning off the Cold Arrows autocast. The rest works.

Then, in your COE Damage Event trigger, I just check if autocast is disabled for a specific unit.

Perhaps there is a simpler solution or a simpler way to implement this. Or there is a more efficient method. If you have a moment take a look at this please, maybe you can come up with something better.
 

Attachments

  • Custom Orb Effects + Arrows.w3m
    77.4 KB · Views: 4

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
1) You can't change the Order String of abilities. The exception is Channel and a couple other abilities that have the Base Order Id field.
2) You can figure out the Order String of anything by displaying it in an Issued Order trigger:
  • Game - Display text to (All players): (Issued order)
3) You could determine if an Autocast ability is on or not using a Boolean array or Integer array variable (or anything really). Whatever makes sense to you. It's the same concept as my Hero_orb_Index[] variable which is Set to 0 when there is no Orb and > 0 when there is an Orb.
 
Last edited:

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
These Attack-Autocast abilities have always been near impossible to get completely right. The user can toggle autocast at any time while an attack projectile is in flight. This means that you can toggle on searing arrows, launch a fiery attack with bonus damage, then turn it off a moment before the missile makes contact, and the Damage Event trigger will think that the ability is off and allow the item-based orb effects to trigger.

If you're fine with that user manipulation (it would be slightly annoying for the user to do consistently) then the solution is simple, check that the hero doesn't have any of these abilities toggled on in the Damage Event conditions. Of course they can also just manually cast the ability, so again, there's not much to do here without some unique system in place.
I found a map like this. It looks like it is very well controlled here whether the unit has used arrows or not. I don't quite understand how it works but it seems to solve even the problems you mentioned i.e. turning on arrows after a normal attack.
Burning Spear - Huskar Spell - Warcraft 3 Maps - Epic War.com
 
Level 22
Joined
Feb 27, 2019
Messages
713
I found a map like this. It looks like it is very well controlled here whether the unit has used arrows or not. I don't quite understand how it works but it seems to solve even the problems you mentioned i.e. turning on arrows after a normal attack.
Burning Spear - Huskar Spell - Warcraft 3 Maps - Epic War.com
That map is outdated but it uses the same logic as the map I posted, which is an old technique to detect orb effect damage from the buff when the target takes damage. Take Black arrows for example, when the target takes damage from Black arrows it instantly has the buff Black arrows. At the event of damage taken, check if the target has the buff Black arrows and if so remove the buff and trigger your own unique orb effect. Simple as.
 

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
That map is outdated but it uses the same logic as the map I posted, which is an old technique to detect orb effect damage from the buff when the target takes damage. Take Black arrows for example, when the target takes damage from Black arrows it instantly has the buff Black arrows. At the event of damage taken, check if the target has the buff Black arrows and if so remove the buff and trigger your own unique orb effect. Simple as.
How could it have been so simple. I searched for a solution for a week. Thanks for explaining it to me again.
 

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
That map is outdated but it uses the same logic as the map I posted, which is an old technique to detect orb effect damage from the buff when the target takes damage. Take Black arrows for example, when the target takes damage from Black arrows it instantly has the buff Black arrows. At the event of damage taken, check if the target has the buff Black arrows and if so remove the buff and trigger your own unique orb effect. Simple as.
These Autocast abilities don't all apply buffs though, nor would you be preventing things like bonus damage that are tied to the projectile and not the buff. But I can see everything being triggered to work with this. Base every Autocast ability on Freezing Arrows with zero extra effects aside from applying the buff. Give each ability their own unique buff for identifying purposes. Then check for/remove these buffs on damage and apply the corresponding effects with triggers.

@KPC
In regards to my system, you could restructure the Damage Event trigger to have an If Then Else in the actions. If the damage target has one of these special buffs, remove it and apply the corresponding Actions like dealing bonus damage, applying a slow debuff, etc. ELSE, if the damage target's Orb_Index is > 0 then run the corresponding Orb_Trigger (like we were doing originally).

Not a huge fan of this solution though, you're now checking for what I imagine will be 5+ different buffs every single time a Hero deal's attack damage. I guess that's not so bad...
 

KPC

KPC

Level 7
Joined
Jun 15, 2018
Messages
188
These Autocast abilities don't all apply buffs though, nor would you be preventing things like bonus damage that are tied to the projectile and not the buff. But I can see everything being triggered to work with this. Base every Autocast ability on Freezing Arrows with zero extra effects aside from applying the buff. Give each ability their own unique buff for identifying purposes. Then check for/remove these buffs on damage and apply the corresponding effects with triggers.

@KPC
In regards to my system, you could restructure the Damage Event trigger to have an If Then Else in the actions. If the damage target has one of these special buffs, remove it and apply the corresponding Actions like dealing bonus damage, applying a slow debuff, etc. ELSE, if the damage target's Orb_Index is > 0 then run the corresponding Orb_Trigger (like we were doing originally).

Not a huge fan of this solution though, you're now checking for what I imagine will be 5+ different buffs every single time a Hero deal's attack damage. I guess that's not so bad...


The first problem I noticed with the new approach is that when unit dies from certain attack then the effect will not be applied. Other problem was that u cant both do bash + orb of slow effect in the same time.

Sometimes it works sometimes not.
  • Kiljaeden Splash Damage Copy
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • (DamageEventTarget has buff Splash Damage ) Equal to True
    • Actions
      • Unit - Remove Splash Damage buff from DamageEventTarget
      • Set VariableSet SmallDamage1 = (DamageEventPrevAmt x 0.35)
      • Set VariableSet TempPoint9 = (Position of (Triggering unit))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 250.00 of TempPoint9.) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal to True
              • (Picked unit) Not equal to DamageEventTarget
              • ((Picked unit) belongs to an enemy of (Owner of DamageEventSource).) Equal to True
              • And - All (Conditions) are true
                • Conditions
                  • (Unit-type of (Picked unit)) Not equal to Sentry Ward
                  • (Unit-type of (Picked unit)) Not equal to Healing Ward
                  • (Unit-type of (Picked unit)) Not equal to Stasis Trap
                  • (Unit-type of (Picked unit)) Not equal to Serpent Ward (Level 1)
                  • (Unit-type of (Picked unit)) Not equal to Serpent Ward (Level 2)
                  • (Unit-type of (Picked unit)) Not equal to Serpent Ward (Level 3)
                  • (Unit-type of (Picked unit)) Not equal to Serpent Ward (Level 4)
                  • (Unit-type of (Picked unit)) Not equal to Serpent Ward (Level 5)
                  • (Unit-type of (Picked unit)) Not equal to Serpent Ward (Level 6)
            • Then - Actions
              • Unit - Cause DamageEventSource to damage (Picked unit), dealing SmallDamage1 damage of attack type Chaos and damage type Normal
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint9)
 
Last edited:

Uncle

Warcraft Moderator
Level 68
Joined
Aug 10, 2018
Messages
7,134
If native Warcraft 3 abilities don't play nice together then you need to trigger them yourself. This whole system is based on that concept. Also, a Damage Event will definitely allow you to run effects before the unit is killed as the lethal damage hasn't been applied yet. Damage Engine gives you different Events for different stages of the damage dealing process.

The final setup would be something like this:
  • Autocast "attack" abilities use the previously mentioned solution. Checking for a buff on hit, removing said buff, and triggering the corresponding effects.
  • Passive Orbs effects, regardless of whether they come from an Item or not, would be completely triggered from scratch.
Your priority system for which of these Orbs occur when more than one is active:
Autocast (hardcoded limit of 1) > Passive Orb (no item) (based on whatever you want) > Passive Orb (item) (based on inventory slot)

Of course you can modify this and do whatever you want, IE: Make these all stack with one another. (Assuming that the effects are all triggered)
 
Last edited:
Top