• 🏆 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] One Buff per Caster on target GUI Trigger

Status
Not open for further replies.
Level 4
Joined
Jul 26, 2017
Messages
66
Hello. Would like to know why this trigger does not work to keep the caster only have the buff on one target unit at a time,

  • Hunters Mark
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Hunter's Mark
    • Actions
      • Unit - Remove Hunter's Mark buff from (Load (Key marked) of (Key (Triggering unit)) in HashTable_SA)
      • Set tempLoc = (Position of (Triggering unit))
      • Unit - Create 1 dummy for (Owner of (Triggering unit)) at tempLoc facing 0.00 degrees
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Unit - Add dummy Hunter's Mark (Neutral Hostile) to (Last created unit)
      • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Target unit of ability being cast)
      • Hashtable - Save Handle Of(Target unit of ability being cast) as (Key marked) of (Key (Triggering unit)) in HashTable_SA
      • Custom script: call RemoveLocation(udg_tempLoc)

I cast the spell and the buff applies but when I cast it on a different unit the buff on the former target does not get removed.
 
Level 4
Joined
Jul 26, 2017
Messages
66
I added debug messages and target unit wasn't properly saved to the hashtable. I use the same hashtable for some other spells so it is initialized.

Also same Triggering unit.

What should I do about the saving error with the hashtable?
 
Level 4
Joined
Jul 26, 2017
Messages
66
It's the key string for the child hashtable triggering unit. I need it because you need two keys to refer to what you are saving? Or is there a better key to use to refer to the target?

BTW did some more debugging and checked that string(Key( Target Unit of Ability being cast)) returns 0
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
The child key is usually used to represent properties of the object represented by the parent key. These property keys can be any integer as long as the number is used consistently. For example child 0 could be used for this buff, while child 1 is used for something else.

Remember to clear these mappings after they are no longer needed. Failure to do so can be considered a leak and can result in degraded hash table performance.
 
Level 4
Joined
Jul 26, 2017
Messages
66
Making them key stings makes them easier to track esp when you use the Hashtable for many spells.
As per clearing the child hashtable, is it required if you just use the same key to store a different unit each time the spell is cast? Or does the unit handle leak somehow each time GetSpellTargetUnit(or something) function call?

Anyways I found the solution to make the trigger work:
I moved up the Save Handle Of(Target unit of ability being cast) as (Key marked) of (Key (Triggering unit)) in HashTable_SA action so that it is executed before creating the dummy unit to cast the spell and now it works as intended:

  • Hunters Mark
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Hunter's Mark
    • Actions
      • Unit - Remove Hunter's Mark buff from (Load (Key marked) of (Key (Triggering unit)) in HT_Target)
      • Set tempLoc = (Position of (Triggering unit))
      • Hashtable - Save Handle Of(Target unit of ability being cast) as (Key marked) of (Key (Triggering unit)) in HT_Target
      • Unit - Create 1 dummy for (Owner of (Triggering unit)) at tempLoc facing 0.00 degrees
      • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
      • Unit - Add dummy Hunter's Mark (Neutral Hostile) to (Last created unit)
      • Unit - Order (Last created unit) to Night Elf Druid Of The Talon - Faerie Fire (Target unit of ability being cast)
      • Custom script: call RemoveLocation(udg_tempLoc)
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
Making them key stings makes them easier to track esp when you use the Hashtable for many spells.
The problem is that due to the 32bit string hash algorithm there is a fair chance of hash collisions, where 2 different strings produce the same hash. I believe someone had a bug as a result of this. This is why vJASS had a special keyword that could be used to generate a unique integer with a human readable name.

Professional cryptographic hashes that are meant to always be unique are 160 bits or 256 bits instead of 32 bits to prevent this. Proper hash tables do use 32bit or even smaller hashes, but they always test the hashed object (the key) for equality as well so they are tolerant to hash collisions.
 
Level 4
Joined
Jul 26, 2017
Messages
66
The problem is that due to the 32bit string hash algorithm there is a fair chance of hash collisions, where 2 different strings produce the same hash. I believe someone had a bug as a result of this.

Wow I didn't know, in that case I would just have to use integers instead and keep track of which spell uses which integer separately since that would be the same if I follow your suggestion. Thanks for the tip!
Would you mind answering this question though?
As per clearing the child hashtable, is it required if you just use the same key to store a different unit each time the spell is cast? Or does the unit handle leak somehow each time GetSpellTargetUnit(or something) function call?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
Would you mind answering this question though?
Each mapping must be cleared otherwise it leaks. One can bulk clear all mappings for a specific parent key if clearing them individually is too complex or slow. One cannot bulk clear all mappings, that native is actually a destructor for the entire hash table.
 
Level 4
Joined
Jul 26, 2017
Messages
66
Each mapping must be cleared otherwise it leaks. One can bulk clear all mappings for a specific parent key if clearing them individually is too complex or slow. One cannot bulk clear all mappings, that native is actually a destructor for the entire hash table.
I'm still confused on what you mean by "each mapping" though? each time the unit handle is saved? or each time the saved unit handle is loaded?? does that mean I need to clear the child hashtable for the casting unit each time I'm done with using the saved unit handle and before saving a new unit handle?????????:vw_wtf:
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,199
I'm still confused on what you mean by "each mapping" though? each time the unit handle is saved? or each time the saved unit handle is loaded?? does that mean I need to clear the child hashtable for the casting unit each time I'm done with using the saved unit handle and before saving a new unit handle?????????
When a key to value mapping is no longer useful it must be removed. For each key to value mapping one adds to a hashtable, the hashtable's complexity is increased. Once the hashtable complexity passes a certain point certain operations on it will take longer. The only way to reduce its complexity is to clear/remove mappings. This is an important difference between an array and a hashtable since with arrays one does not need to worry about indices that are no longer useful as they do not raise complexity.
 
Status
Not open for further replies.
Top