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

How to track an unit that changed owners?

Status
Not open for further replies.
Level 5
Joined
Jan 22, 2023
Messages
51
Well I have no idea how to make unit go back to initial owner without a wait action (im not using it, its my miserable try to return the owner)

The idea of the spell is: Charms the target, if the buff ends or charmed unit is below 50% health - return it to original owner
  • INS cast
    • Events
      • Unit - A unit Starts an effect of the Ability
    • Conditions
      • (Ability being cast) Equal to Insanity
    • Actions
      • Unit Group - Add (Target unit of ability being cast) to INS_Group
      • -------- --------
      • Set Temppoint = (Position of (Target unit of ability being cast))
      • Unit - Create 1 Dummy for (Triggering Player) at Temppoint facing default building facing degrees
      • Custom script: call RemoveLocation(udg_Temppoint)
      • Unit - Add Insanity dummy to (Last created unit)
      • Unit - Order (Last created unit) to Human - Priest: Inner Fire (Target unit of ability being cast)
      • Unit - Add a 0.50 second generic expiration timer to (Last created unit)
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Insanity ) Equal to True
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to (Triggering Player) and Change Color
            • Else - Actions
      • Trigger - Turn on INS charm <gen>
  • INS charm
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
      • (Number of units in INS_Group) Greater than 0
    • Actions
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Insanity ) Equal to False
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to (Previous owner) and Change Color
              • Unit Group - Remove (Picked unit) from INS_Group
            • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Percentage life of (Picked unit)) Lesser than or Equal to 50.00
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to (Previous owner) and Change Color
              • Unit Group - Remove (Picked unit) from INS_Group
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in INS_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
Here's the Unit Indexer solution (my personal favorite):
  • INS cast
    • Events
      • Unit - A unit Starts an effect of the Ability
    • Conditions
      • (Ability being cast) Equal to Insanity
    • Actions
      • Set Insanity_Unit = (Target unit of ability being cast)
      • Set Insanity_Player = (Triggering player)
      • Unit Group - Add Insanity_Unit to INS_Group
      • Trigger - Turn on INS charm <gen>
      • -------- --------
      • -------- this doesn't really make sense to me: --------
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Insanity ) Equal to True
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to Insanity_Player and Change Color
              • Set Variable Insanity_Owner[Custom value of (Picked unit)] = Insanity_Player
            • Else - Actions
      • -------- --------
      • Set TempPoint = (Position of Insanity_Unit)
      • Unit - Create 1 Dummy for Insanity_Player at TempPoint facing default building facing degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Set TempDummy = (Last created unit)
      • Unit - Add a 0.20 second generic expiration timer to TempDummy
      • Unit - Add Insanity dummy to TempDummy
      • Unit - Order TempDummy to Human - Priest: Inner Fire Insanity_Unit
  • INS charm
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • Set Insanity_Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • (Insanity_Unit has buff Insanity ) Equal to False
                • (Percentage life of Insanity_Unit) Less than 50.00
            • Then - Actions
              • Unit - Change ownership of Insanity_Unit to Insanity_Owner[Custom value of Insanity_Unit] and Change Color
              • Unit Group - Remove Insanity_Unit from INS_Group
            • Else - Actions
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in INS_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
Also, note some adjustments I made.
  • I got rid of the first condition in INS charm since we already check that at the bottom of the trigger, plus we want it to Turn Off if the group is empty.
  • I also adjusted the Loop in INS charm to take advantage of the OR condition to remove some redundancy.
  • I added some variables to optimize it as well as help prevent issues.
  • I reordered the Actions to follow a pattern that can help prevent issues.


Oh, and maybe this is intentional but why are you doing this in the first trigger?
  • Unit Group - Pick every unit in INS_Group and do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Picked unit) has buff Insanity ) Equal to True
        • Then - Actions
          • Unit - Change ownership of (Picked unit) to Insanity_Player and Change Color
          • Set Variable Insanity_Owner[Custom value of (Picked unit)] = Insanity_Player
        • Else - Actions
This is stealing every single unit under the effects of Insanity, not just the one we targeted with the ability. I think it should be as simple as this:
  • Unit - Change ownership of Insanity_Unit to Insanity_Player and Change Color
  • Set Variable Insanity_Owner[Custom value of Insanity_Unit] = Insanity_Player
Also, there's a good chance that the (Target unit of ability being cast) doesn't even have the Insanity buff yet.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,023
You could do this entirely without a unit indexer or any dynamic indexing by using a group to store 'currently affected units' and then giving such affected units a 24-level passive ability with no effects that doesn't show on the command card. Set the level of the ability to the player number of the original owning player.

Be advised that the solutions shown in this thread will break if the same unit is charmed by multiple players in succession. If such a thing can occur, the easiest fix is simply not to update the owning player (keep the original owner stored instead) when an already-affected unit is charmed.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
This should fix the issue Pyrogasm described regarding multiple players permanently stealing units.

First, we create a new trigger that automatically tracks the original owner of all of our units. This Player variable can be used in ANY of our triggers:
  • Events
    • Game - UnitIndexEvent becomes Equal to 1.00
  • Conditions
  • Actions
    • Set Unit_OriginalOwner[UDex] = (Owner of UDexUnits[UDex])
Next let's simplify our Insanity cast trigger:
  • INS cast
    • Events
      • Unit - A unit Starts an effect of the Ability
    • Conditions
      • (Ability being cast) Equal to Insanity
    • Actions
      • Set Insanity_Unit = (Target unit of ability being cast)
      • Set Insanity_Player = (Triggering player)
      • -------- --------
      • Set TempPoint = (Position of Insanity_Unit)
      • Unit - Create 1 Dummy for Insanity_Player at TempPoint facing default building facing degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Set TempDummy = (Last created unit)
      • Unit - Add a 0.20 second generic expiration timer to TempDummy
      • Unit - Add Insanity dummy to TempDummy
      • Unit - Order TempDummy to Human - Priest: Inner Fire Insanity_Unit
      • -------- --------
      • Unit - Change ownership of Insanity_Unit to Insanity_Player and Change Color
      • Unit Group - Add Insanity_Unit to INS_Group
      • Trigger - Turn on INS charm <gen>
Lastly, let's simplify the INS charm trigger:
  • INS charm
    • Events
      • Time - Every 0.05 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • Set Insanity_Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • (Insanity_Unit has buff Insanity ) Equal to False
                • (Percentage life of Insanity_Unit) Less than 50.00
            • Then - Actions
              • Unit - Change ownership of Insanity_Unit to Unit_OriginalOwner[Custom value of Insanity_Unit] and Change Color
              • Unit Group - Remove Insanity_Unit from INS_Group
            • Else - Actions
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in INS_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions

The first trigger is using a custom Event that Bribe created to go along with his Unit Indexer system. It allows you to interact with a Unit the moment it's indexed OR de-indexed by the system. In this case I'm using the indexed part of the Event. This runs immediately after a new unit has come into play. At this stage the unit has already been accessed by the Unit Indexer system and has been assigned a unique Custom Value that no other unit currently has. It has also been added to a Unit Array variable (UDexUnits) which you can see me interacting with when I setup the Unit_OriginalOwner variable.

Long story short, I'm tracking the original owner of each newly created unit. We can then reference this Player at any time by using the variable Unit_OriginalOwner[] and supplying that unit's Custom Value inside of the [index].


If you continue to use the Unit Indexer system then here's something that's important to understand:

The Unit Indexer system will recycle unused Custom Values in order to keep things running smoothly. This means that when a unit dies it's Custom Value is made available again to a future unit. This can cause problems if we still have data saved at that Custom Value since the new unit will inherit all of this information.

For example, let's say that you were tracking how many times a Sorceress has casted the Slow ability. Maybe she gets rewarded after she casts it 5 times or something. Then let's say that you achieved this by using the Unit Indexer and an Integer array variable. Pretty simple stuff, you have a trigger that runs each time she casts the Slow ability and in the Actions you increase her Integer by 1:
  • Set SlowCounter[Custom value of (Casting unit)] = SlowCounter[Custom value of (Casting unit)] + 1
Now let's say that the Sorceress dies, her Custom Value gets recycled, and a newly created Sorceress is given this Custom Value. We've now encountered an issue. Our new Sorceress now has access to the old Sorceress' data. In other words, our new Sorceress has as many Slow counters as the old one did, giving her an unwanted advantage.

The solution here is rather easy. All we need to do is reset the data the same way I'm doing it in my UnitIndexEvent trigger. There's also an option for when a unit gets De-Indexed which happens right before the Custom Value gets put back into the system to be used at a later time. Bot hof these are valid options for resetting data.

All of this being said, it's not always necessary to reset things. You should only do it if it will otherwise cause problems like the one I described with the Sorceress. For instance, Heroes usually don't get Removed from the game so their Custom Values should remain the same throughout the entire game. As a result, this issue doesn't really apply to them at all since you have no fear of their Custom Value getting recycled.
 
Last edited:
Level 5
Joined
Jan 22, 2023
Messages
51
I actually went to pains and tried hashtables because seen them around in many triggers, spells overall (I'll also work with Unit Indexer, just wanted to try hashtables for the first time).
Spell works fine, but was wondering if everything is set up properly and won't cause any issues with time during gameplay
  • INS cast
    • Events
      • Unit - A unit Starts an effect of the Ability
    • Conditions
      • (Ability being cast) Equal to Insanity
    • Actions
      • Set INS_Owner = (Owner of (Target unit of ability being cast))
      • Unit Group - Add (Target unit of ability being cast) to INS_Group
      • Hashtable - Save Handle Of INS_Owner as 1 of 1 in INS_Table
      • -------- --------
      • Set Temppoint = (Position of (Target unit of ability being cast))
      • Unit - Create 1 Dummy for (Triggering Player) at Temppoint facing default building facing degrees
      • Custom script: call RemoveLocation(udg_Temppoint)
      • Unit - Add Insanity dummy to (Last created unit)
      • Unit - Order (Last created unit) to Human - Priest: Inner Fire (Target unit of ability being cast)
      • Unit - Add a 0.50 second generic expiration timer to (Last created unit)
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Insanity ) Equal to True
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to (Triggering Player) and Change Color
            • Else - Actions
      • Trigger - Turn on INS charm <gen>
  • INS charm
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • Set INS_Owner = (Load 1 of 1 in INS_Table)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Insanity ) Equal to False
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to INS_Owner and Change Color
              • Unit Group - Remove (Picked unit) from INS_Group
              • Unit - Remove Insanity buff from (Picked unit)
            • Else - Actions
              • Hashtable - Clear all child hashtables of child 1 in INS_Table
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in INS_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
Edit: I've put this in the wrong place
  • Hashtable - Clear all child hashtables of child 1 in INS_Table
Should it be in the second "if" then?
 
Level 39
Joined
Feb 27, 2007
Messages
5,023
  • Hashtable - Save Handle Of INS_Owner as 1 of 1 in INS_Table
  • The "1 of 1" is like a coordinate for the data you are storing in the hashtable. Since you have hardcoded (1,1) here, every cast of the spell will overwrite the data stored in the hashtable. Instead you will want to use the Handle ID of the targeted unit as one of those coordinates (probably the second one), which is what accomplishes the 'attaching' of data to it.
  • You will have to flush the correct data when you no longer need it, using the units handle id as the parent key you flush. Flushing the child directly works too if that's the only thing that's assigned under the parent (in this case it is).
  • It looks like your hashtable is uninitialized (I don't see INS_Table being assigned anywhere)
  • Unit - Order (Last created unit) to Human - Priest: Inner Fire (Target unit of ability being cast)
  • Unit - Add a 0.50 second generic expiration timer to (Last created unit)
  • Unit Group - Pick every unit in INS_Group and do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Picked unit) has buff Insanity ) Equal to True
        • Then - Actions
          • Unit - Change ownership of (Picked unit) to (Triggering Player) and Change Color
        • Else - Actions
  • Why are you dummy casting inner fire on the target that was charmed? Shouldn't the normal ability apply whatever buff you need?
  • Why are you picking units in INS_Group? All of the units in there have already been charmed and had their owner changed, so there is no need to interact with them. What this actually does is change the owner of all charmed units to be the triggering player; if an opposing player charms my unit A away from me into their control, when I charm any other unit B away from them, the owner of unit A will switch back to me; surely you can't intend this behavior.
  • Why do you need to check for units with the buff? You should know exactly which unit(s) have the buff already: the target of the ability that was cast. This sort of a choice might make sense if Insanity is supposed to work like Frost Nova (affect all units nearby the target) or a true aoe, but it doesn't seem like you're actually doing either of those things.
Finally, you're not checking if the unit has < 50% hp in the periodic trigger, only if it doesn't have the buff. And honestly 0.10 is way faster than it needs to be. You could get away with 0.3 just fine.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
Pyro beat me to the punch, lol. So my last post shows a 100% working method which I highly recommend looking at even if you wish to use a Hashtable for the saving of the data.

Also, a quick way to understand a Hashtable is to think of it as a 2-dimensional Array. That's an Array with two [indexes].

This line here:
  • Hashtable - Save Handle Of INS_Owner as 1 of 1 in INS_Table
Is essentially a 2d Array that looks like this:
  • Set INS_Table[1][1] = INS_Owner
Which if you understand Arrays it should quickly become apparent why this won't work. You'll be overwriting the data saved at indexes [1][1] each time ANY unit casts the spell.

Hopefully that helps. Regardless, your Hashtable usage is incorrect and there's issues that need to be addressed from earlier before we go any further. I would get it up and running using my triggers and then you can try to adapt it to use a Hashtable if you wish.
 
Last edited:
Level 5
Joined
Jan 22, 2023
Messages
51
  • Hashtable - Save Handle Of INS_Owner as 1 of 1 in INS_Table
  • The "1 of 1" is like a coordinate for the data you are storing in the hashtable. Since you have hardcoded (1,1) here, every cast of the spell will overwrite the data stored in the hashtable. Instead you will want to use the Handle ID of the targeted unit as one of those coordinates (probably the second one), which is what accomplishes the 'attaching' of data to it.
Will this do the trick?
  • Set INS_Owner = (Owner of (Target unit of ability being cast))
  • Set INS_Unit = (Target unit of ability being cast)
  • Custom script: set udg_INS_Handle = GetHandleId(udg_INS_Unit)
  • Unit Group - Add (Target unit of ability being cast) to INS_Group
  • Hashtable - Save Handle Of INS_Owner as 1 of INS_Handle in INS_Table
•INS_Handle is an integer

• Also the INS_Table is set in another trigger, forgot to paste it here
• Deleted the "If" action that was picking an unit and changing the owner in the first trigger. Forgot to delete it after Uncle first noted it out.

So this works in the case of this trigger? (Also should this 1 be set to INS_Handle? or left 1)
  • Hashtable - Clear all child hashtables of child 1 in INS_Table
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
  • Why are you dummy casting inner fire on the target that was charmed? Shouldn't the normal ability apply whatever buff you need?
  • Why are you picking units in INS_Group? ...
That depends on the ability, the base ability could be Channel.
But i think the general idea of this ability is that the caster takes control of the target so long as target is above 50% health and the target has the debuff - so if the debuff is dispelled, the mind control should be broken.

@Meronia this piece of code Pyro posted:
  • Unit - Order (Last created unit) to Human - Priest: Inner Fire (Target unit of ability being cast)
  • Unit - Add a 0.50 second generic expiration timer to (Last created unit)
  • Unit Group - Pick every unit in INS_Group and do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Picked unit) has buff Insanity ) Equal to True
        • Then - Actions
          • Unit - Change ownership of (Picked unit) to (Triggering Player) and Change Color
        • Else - Actions
The application of a buff on a unit is not instant, so the condition would evaluate to 'false' and not change ownership

Will this do the trick?
Yes, that's the correct way

So this works in the case of this trigger? (Also should this 1 be set to INS_Handle? or left 1)
  • Hashtable - Clear all child hashtables of child 1 in INS_Table
the '1' is the child data, while the INS_Handle is the parent. The action above clear all children data belonging to the parent, so no, it will not work the way you have it now. Instead, do
  • Hashtable - Clear all child hashtables of child INS_Handle in INS_Table

edit: I just noticed that the action for clearing hashtable has misleading name in the trigger above, but that seems to by typo on Blizz's side, if you check the description of the action, it says 'parent':
1677246304961.png
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,023
The application of a buff on a unit is not instant, so the condition would evaluate to 'false' and not change ownership
Are you certain? It might take a frame update to see the buff on the UI but the unit probably 'has' it instantly (as long as the caster is configured to instantly cast) since Inner Fire is not a projectile spell.
But i think the general idea of this ability is that the caster takes control of the target so long as target is above 50% health and the target has the debuff - so if the debuff is dispelled, the mind control should be broken.
Yes that was clear. They were iterating over the group in the cast trigger in addition to the periodic trigger, which was unnecessary.
 
Level 5
Joined
Jan 22, 2023
Messages
51
@Meronia this piece of code Pyro posted:
  • Unit - Order (Last created unit) to Human - Priest: Inner Fire (Target unit of ability being cast)
  • Unit - Add a 0.50 second generic expiration timer to (Last created unit)
  • Unit Group - Pick every unit in INS_Group and do (Actions)
    • Loop - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Picked unit) has buff Insanity ) Equal to True
        • Then - Actions
          • Unit - Change ownership of (Picked unit) to (Triggering Player) and Change Color
        • Else - Actions
The application of a buff on a unit is not instant, so the condition would evaluate to 'false' and not change ownership
Actually it's instant and changes owner, I've tested it
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
You are right. I think I got sidetracked by my own code.
Basically I had something like this:
  • Untitled Trigger 001
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Banish
    • Actions
      • Unit - Create 1 Dummy for Player 1 (Red) at some_location facing Default building facing degrees
      • Unit - Order (Last created unit) to Human Priest - Inner Fire (Target unit of ability being cast)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Target unit of ability being cast) has buff Inner Fire) Equal to True
        • Then - Actions
        • Else - Actions
The dummy is set properly and casts the inner fire, but the condition in the If/then/else always evaluated to false, so I got the wrong impression that the application of a buff is not instant.
The real problem was, that after this action finishes:
  • Unit - Order (Last created unit) to Human Priest - Inner Fire (Target unit of ability being cast)
the (Target unit of ability being cast) is nulled (i.e. it equals to "(No unit)").
Of course setting the (Target unit of ability being cast) into variable and then referencing the variable in the trigger fixed the issue
:goblin_yeah:
I will update my previous comment
 
Level 5
Joined
Jan 22, 2023
Messages
51
That's what I have so far
  • INS cast
    • Events
      • Unit - A unit Starts an effect of the Ability
    • Conditions
      • (Ability being cast) Equal to Insanity
    • Actions
      • Set INS_Owner = (Owner of (Target unit of ability being cast))
      • Set INS_Unit = (Target unit of ability being cast)
      • Custom script: set udg_INS_Handle = GetHandleId(udg_INS_Unit)
      • Unit Group - Add (Target unit of ability being cast) to INS_Group
      • Hashtable - Save Handle Of INS_Owner as 1 of INS_Handle in INS_Table
      • -------- --------
      • Set Temppoint = (Position of (Target unit of ability being cast))
      • Unit - Create 1 Dummy for (Triggering Player) at Temppoint facing default building facing degrees
      • Custom script: call RemoveLocation(udg_Temppoint)
      • Unit - Add Insanity dummy to (Last created unit)
      • Unit - Order (Last created unit) to Human - Priest: Inner Fire (Target unit of ability being cast)
      • Unit - Add a 0.50 second generic expiration timer to (Last created unit)
      • Unit - Change ownership of (Target unit of ability being cast) to (Triggering Player) and Change Color
      • Trigger - Turn on INS charm <gen>
  • INS charm
    • Events
      • Time - Every 0.30 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • Set INS_Owner = (Load 1 of INS_Handle in INS_Table)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) has buff Insanity ) Equal to False
            • Then - Actions
              • Unit - Change ownership of (Picked unit) to INS_Owner and Change Color
              • Unit Group - Remove (Picked unit) from INS_Group
              • Unit - Remove Insanity buff from (Picked unit)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in INS_Group) Equal to 0
        • Then - Actions
          • Hashtable - Clear all child hashtables of child INS_Handle in INS_Table
          • Trigger - Turn off (This trigger)
        • Else - Actions
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
So you're making a couple of mistakes with the Hashtable. Also, understand that even if you get it working this way it's still going to be buggy and allow players to permanently steal units. I address this problem in my 2nd post near the top.

Focusing on the Hashtables:

In INS charm you're referencing INS_Handle without setting it first. Therefore it has no relation to the (Picked unit) and will simply reference the last value it was given in the INS cast trigger.

Also, you're making the same mistake when Clearing all child hashtables. Additionally, that Action is in the wrong spot, it should be part of the whole Removing process since that's when we reset everything back to normal for the unit.

Here's the updated trigger:
  • INS charm
    • Events
      • Time - Every 0.30 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in INS_Group and do (Actions)
        • Loop - Actions
          • Set INS_Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (INS_Unit has buff Insanity ) Equal to False
            • Then - Actions
              • Custom script: set udg_INS_Handle = GetHandleId(udg_INS_Unit)
              • Set INS_Owner = (Load 1 of INS_Handle in INS_Table)
              • Unit - Change ownership of INS_Unit to INS_Owner and Change Color
              • Unit Group - Remove INS_Unit from INS_Group
              • Hashtable - Clear all child hashtables of child INS_Handle in INS_Table
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in INS_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
Again, you don't need to Remove the buff, it literally DOESN'T have it anymore. Your Condition confirms this.
 
Level 5
Joined
Jan 22, 2023
Messages
51
Again, you don't need to Remove the buff, it literally DOESN'T have it anymore. Your Condition confirms this.
My bad I didn't copy one line here that I have. It's:
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • ((Picked unit) has buff Insanity ) Equal to False
          • (Percentage life of (Picked unit)) Lesser than or Equal to 50.00
That's why I was putting "remove buff" for that second condition, I don't know if it's a good way but yeah

What exactly causes the thing you're saying, that players will be able to steal an unit permanently?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
That's a good solution, it's okay if you try to Remove a buff that doesn't exist, the game will simply ignore it.

Anyway, I've explained the stealing thing twice now and Pyrogasm explained it as well. Can you please read some of our earlier posts? My 2nd post shows you a 100% working solution.

But I believe all you need to do is prevent this Action from happening more than once on the same unit:
  • Hashtable - Save Handle Of INS_Owner as 1 of INS_Handle in INS_Table
So before running this Action you should use an If Then Else to check whether or not the unit has been targeted by this ability before. This can be done by trying to Load the value from the Hashtable or by some other simple method for "marking" a unit. If the unit isn't "marked" or isn't inside of the Hashtable then you know that you can safely Save it's data to the Hashtable.
 
Last edited:
Level 5
Joined
Jan 22, 2023
Messages
51
So before running this Action you should use an If Then Else to check whether or not the unit has been targeted by this ability before. This can be done by trying to Load the value from the Hashtable or by some other simple method for "marking" a unit. If the unit isn't "marked" or isn't inside of the Hashtable then you know that you can safely Save it's data to the Hashtable.
So should I use this condition to check if it's already stored? (sorry for being a dummy if that's a total folly from me)
  • (INS_Handle is stored as a C of INS_Handle in INS_Table) Equal to True
And about your Unit Indexer metod - Do you need a trigger to set indexes for all units? Haven't seen such thing in Bribe's tutorial/Unit indexer post. Because after copying your solution with unit indexing it doesn't work, doesn't store the owner
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,564
I think it should look something like that. If that doesn't work then try this:
  • Custom script: if LoadPlayerHandle(udg_INS_Table, GetHandleId(udg_INS_Unit), 1) == 0 then
  • Hashtable - Save Handle Of INS_Owner as 1 of INS_Handle in INS_Table
  • Custom script: endif
The default value of an Integer in your Hashtable will always be 0, therefore if the Unit hasn't been Saved in the Hashtable yet then it's associated value will be equal to 0. At least that's the idea, if that doesn't work then try replacing 0 with null.

And all you have to do is import the Unit Indexer into your map and it handles the rest for you. It's as simple as copy and pasting the folder.

The system does something along the lines of this:
Step 1: The Map Initialization event happens and the Unit Indexer system begins running.
Step 2: The system Picks through every unit that has been pre-placed on the map and indexes them (gives them a unique custom value).
Step 3: The system creates trigger(s) that actively detect any new units that come into play in order to index them. It does the same for de-indexing units that are removed from play.
Step 4: Lastly, the system runs a special Event which you can take advantage of if you'd like. This Event runs during Map Initialization but after the system has finished doing it's thing. This way you can start taking advantage of the system almost immediately.

If you're curious if the system is working or not, you can simply Display a text message of a unit's Custom Value:
  • Events
    • Player - Player 1 (red) selects a unit
  • Conditions
  • Actions
    • Game - Display (String(Custom value of (Triggering unit)) for 10.00 seconds
This will show you an Integer number equal to the selected unit's custom value. If each selected unit has a different number then you know it's working. At that point it would mean that you probably made a mistake in one or more of your own triggers.
 
Last edited:
Level 5
Joined
Jan 22, 2023
Messages
51
If you're curious if the system is working or not, you can simply Display a text message of a unit's Custom Value:
  • Events
    • Player - Player 1 (red) selects a unit
  • Conditions
  • Actions
    • Game - Display (String(Custom value of (Triggering unit)) for 10.00 seconds
This will show you an Integer number equal to the selected unit's custom value. If each selected unit has a different number then you know it's working. At that point it would mean that you probably made a mistake in one or more of your own triggers.
That works, so Unit Indexer is working properly!
Thanks for those advices, i'm happy it works. I tested this spell with multiple heroes and it works without any issues right now. Thank you guys!
 
Status
Not open for further replies.
Top