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

Hashtables and MUI

Level 13
Joined
Mar 4, 2009
Messages
1,156
1.)
will it leak if i save a point in hashtable like this
for example:
save "Target point of issued order" in hashtable

and than i clear the hashtable when needed
2.)
will it leak if i save point in hashtable like this
for example:
set POINT = "Target point of issued order"
save POINT in hashtable
call RemoveLocation(udg_POINT)

and than i clear the hashtable when needed

i cam understand the tutorial,thanks + Rep,can be made more simple
 
Level 13
Joined
Mar 4, 2009
Messages
1,156
1) Yes.

2) No, but it won't necessarily work. You only need to remove the location just before clearing the hashtable.

Save point into hashtable
Use it as many times you need to
...
Load the point into a variable and clear it
Flush the hashtable

oh :/
what are you saying

1.)
is it ok if i make it liek this
set POINT = "Target point of issued order"
save POINT in hashtable
call RemoveLocation(udg_POINT)
2.)
or like this
save some point in Hashtable
set POINT = (load HashTable´s Point)
call RemoveLocation(udg_POINT)
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
What I meant was a situation like this:

  • Spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Inferno
    • Actions
      • Set Temp_Loc_1 = (Target point of ability being cast)
      • Hashtable - Save Handle OfTemp_Loc_1 as (Key center) of (Key (Triggering unit)) in (Last created hashtable)
      • Custom script: call RemoveLocation(udg_Temp_Loc_1) <- don't do this
^Don't remove the location there.

  • Spell Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Group and do (Actions)
        • Loop - Actions
          • Set Temp_Unit_1 = (Picked unit)
          • Set Temp_Loc_2 = (Load (Key center) of (Key (Picked unit)) in Hash)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Temp_Unit_1 is alive) Equal to True
            • Then - Actions
              • -------- *use the location here, but don't clear it* --------
            • Else - Actions
              • Custom script: call RemoveLocation(udg_Temp_Loc_2)
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Hash
^That's how to use the location that you stored in the first trigger, in a looping trigger.
 
Level 13
Joined
Mar 4, 2009
Messages
1,156
What I meant was a situation like this:

  • Spell
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Inferno
    • Actions
      • Set Temp_Loc_1 = (Target point of ability being cast)
      • Hashtable - Save Handle OfTemp_Loc_1 as (Key center) of (Key (Triggering unit)) in (Last created hashtable)
      • Custom script: call RemoveLocation(udg_Temp_Loc_1) <- don't do this
^Don't remove the location there.

  • Spell Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Group and do (Actions)
        • Loop - Actions
          • Set Temp_Unit_1 = (Picked unit)
          • Set Temp_Loc_2 = (Load (Key center) of (Key (Picked unit)) in Hash)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Temp_Unit_1 is alive) Equal to True
            • Then - Actions
              • -------- *use the location here, but don't clear it* --------
            • Else - Actions
              • Custom script: call RemoveLocation(udg_Temp_Loc_2)
              • Hashtable - Clear all child hashtables of child (Key (Picked unit)) in Hash
^That's how to use the location that you stored in the first trigger, in a looping trigger.
edit:
ok i get it now...
i would like some other person to conform Maker´s theory just to be sure :D
 
Last edited:
Level 13
Joined
Sep 29, 2008
Messages
671
Why can't i edit the key handle id? There's nothing in it, the combo box wont drop down

Like this?
you meant this?:
newgenhash.gif


maybe you could try this:


I tried updating that Tesh and it worked for a while but suddenly it bugs again that's why i just use normal WE when using hastables now. but it might work for you hopefully... :D
 
Level 8
Joined
Oct 26, 2008
Messages
387
so if i get it right... because im kinda new in the triggering story, you could store any number of the same variable in the same hashtable and it wont bug the other triggers of spells for eg, because it is the same variable?

i mean you create a real variable named Real.

you save some values of it you need in other triggers in a hastable.
and then you just load it, so you can use the same variable over and over again in different triggers?
 
Level 13
Joined
Mar 4, 2009
Messages
1,156
so if i get it right... because im kinda new in the triggering story, you could store any number of the same variable in the same hashtable and it wont bug the other triggers of spells for eg, because it is the same variable?

i mean you create a real variable named Real.

you save some values of it you need in other triggers in a hastable.
and then you just load it, so you can use the same variable over and over again in different triggers?
hashtables is like a normal variable that can "transform" and by doing that it can store any type of value
normal variable can just store 1 type of value

so hashtable is like 2-d array variable that "transforms" in any type of variable by storeing values in it
so if you store real in hashtable than it will "transform" to real-type variable

example:
if you store integer 55 as 1 of 1 in Hash
and than if you store real 4.00 as 1 of 1 in Hash

Hash 1 of 1 is now a real-type variable and has value 4.00 stored in,integer 55 that was stored previously is removed from memory because real 4.00 took its place
 
Level 8
Joined
Oct 26, 2008
Messages
387
yes but if i store

real = 5 in 0 of 2 hash
real = 6 in 1 of 2 hash
real = 7 in 2 of 2 hash

then would i be able to use the real variable in three triggers ?
using the same variable in different triggers, as

real = load 0 of 2 hash wouldnt it take the value 5 ?
and then real = load 1 of 2 hash wouldnt it take the value 6 ?

so i shouldnt i be able to user just one real variable for many triggers without bugging them when they trigger at the same time?

or am i dreaming :p?
 
Level 13
Joined
Mar 4, 2009
Messages
1,156
by the way, how should I save unit groups?
you willl proably not need to have so much groups so you can just use one array unit group called "GROUP[X]"
thats real great thnx a lot dude, im just learning about triggers and i was going and going and creating like 4-5 variables for each spell i created and that got messy with all those useless variables :D :D :D
you will need some....

if you want to have only 1 Hash with few variables in whole game you can just use "shortcuts" and that would be
to make 1 array variable for each varaibale type
example:
N - array integer variable
RE - arrey real variable
HT - hashtable variable

actions:
set N[0] = (key triggering unit)
set N[1] = (load (key mana) of N[0] from HT)
set N[2] = (load (key health) of N[0] from HT)
set N[3] = (load (key kills) of N[0] from HT)
ser RE[0] = (load (key facing degreeses) of N[0] from HT)
----- to get kills of triggering unit you just need to use this -----
load N[0] of N[3] from HT
----- to increase kills use this -----
set HT N[3] of N[0] to (N[3] + 1)

now it is much easier to use those values multiple times (as you can see that i also used N[0] instead repeating "(key triggering unit)" every time

maybe i should mke it in editor ? :S
you should be able to understand it tough
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
Hashtable saving region... i always get a crash error, and with much other hashtable savings :S only works real,integer,point and boolean :'(
Can anyone say me what to do? or can i save region with script on to hashtable?

Save rect , not region. "Save Rect handle" is what saves regions.

Weird that those commands don't work for you. I think the only one that doesn't work for me is "Save region handle", and that's because Blizzard fudged up.
 
Level 1
Joined
Nov 7, 2010
Messages
3
Hey Mappers ;)
i think i've got the best fixed version! I called the Spell "Demisence" ;P. This is the best because:
1.) GUI needs more memory than Jass and this is Jass
2.) I used a Timer for the periodic event which get paused if no unit is in the group
3.)The Hashtable Value Transport (Load/Save) uses "lokal" variables! thats better because you have a 100% guarantee that it cant use the same variable at one time

Look yourself :D!

JASS:
function Hashtables_A1 takes nothing returns nothing
call InitHashtableBJ()
set udg_Demisence_Hashtable = GetLastCreatedHashtableBJ()
endfunction

function Demisence_C1 takes nothing returns boolean
if ( not (GetSpellAbilityId() == 'A000')) then
  return false
    endif
      return true
endfunction

function Demisence_T1 takes nothing returns nothing
local real Demisence_Angle      = LoadRealBJ(0, GetHandleId(GetEnumUnit()), udg_Demisence_Hashtable)
local real Demisence_Distance   = LoadRealBJ(1, GetHandleId(GetEnumUnit()), udg_Demisence_Hashtable)   
local real Demisence_Counter    = LoadRealBJ(2, GetHandleId(GetEnumUnit()), udg_Demisence_Hashtable)
if Demisence_Counter < 100.00 then 
call SetUnitPositionLoc(GetEnumUnit(), PolarProjectionBJ(GetUnitLoc(GetEnumUnit()), Demisence_Distance, Demisence_Angle))
call SaveRealBJ((Demisence_Counter + 1.00), 2, GetHandleId(GetEnumUnit()), udg_Demisence_Hashtable)
else
call FlushChildHashtableBJ(GetHandleIdBJ(GetEnumUnit()), udg_Demisence_Hashtable)
call GroupRemoveUnit(udg_Demisence_Targets, GetEnumUnit())
endif
endfunction

function Demisence_A2 takes nothing returns nothing
local timer Demisence_Timer = GetExpiredTimer()
call ForGroupBJ(udg_Demisence_Targets, function Demisence_T1)
if CountUnitsInGroup(udg_Demisence_Targets) == 0 then
call PauseTimer(Demisence_Timer)
else
call DoNothing()
endif
endfunction

function Demisence_A1 takes nothing returns nothing
local timer Demisence_Timer     = CreateTimer()
local real Demisence_Angle      = AngleBetweenPoints(GetUnitLoc(GetSpellAbilityUnit()), GetUnitLoc(GetSpellTargetUnit()))
local real Demisence_Distance   = 5.00
local real Demisence_Counter    = 0.00
call SaveRealBJ(Demisence_Angle, 0, GetHandleId(GetSpellTargetUnit()), udg_Demisence_Hashtable)
call SaveRealBJ(Demisence_Distance, 1, GetHandleId(GetSpellTargetUnit()), udg_Demisence_Hashtable)
call SaveRealBJ(Demisence_Counter, 2, GetHandleId(GetSpellTargetUnit()), udg_Demisence_Hashtable)
call GroupAddUnit(udg_Demisence_Targets, GetSpellTargetUnit())
if CountUnitsInGroup(udg_Demisence_Targets) == 1 then
call TimerStart(Demisence_Timer, 0.04, true, function Demisence_A2)
else
call DoNothing()
endif
endfunction

function InitTrig_INIT takes nothing returns nothing
local trigger Hashtables_M1     = CreateTrigger()
local trigger Demisence_M1      = CreateTrigger()
call TriggerRegisterTimerEventSingle(Hashtables_M1, 0.01)
call TriggerAddAction(Hashtables_M1, function Hashtables_A1)
call TriggerRegisterAnyUnitEventBJ(Demisence_M1, EVENT_PLAYER_UNIT_SPELL_CAST)
call TriggerAddAction(Demisence_M1, function Demisence_A1)
endfunction
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
^
Store GetEnumUnit into a variable and use the variable.

JASS:
call InitHashtableBJ()
set udg_Demisence_Hashtable = GetLastCreatedHashtableBJ()
endfunction
->
JASS:
set udg_Demisence_Hashtable = InitHashtable()


JASS:
function Demisence_C1 takes nothing returns boolean
if ( not (GetSpellAbilityId() == 'A000')) then
  return false
    endif
      return true
endfunction
->
JASS:
function Demisence_C1 takes nothing returns boolean
return GetSpellAbilityId() == 'A000'
endfunction


JASS:
local real Demisence_Angle      = LoadRealBJ(0, GetHandleId(GetEnumUnit()), udg_Demisence_Hashtable)
->
JASS:
local real Demisence_Angle      = LoadReal(udg_Demisence_Hashtable , GetHandleId(GetEnumUnit()), 0)
And store the handleId to a variable, and use the variable.

JASS:
call SetUnitPositionLoc(GetEnumUnit(), PolarProjectionBJ(GetUnitLoc(GetEnumUnit())
Leaks, use coordinates.

JASS:
call FlushChildHashtableBJ(GetHandleIdBJ(GetEnumUnit()), udg_Demisence_Hashtable)
->
JASS:
FlushChildHashtable()



JASS:
call ForGroupBJ(udg_Demisence_Targets, function Demisence_T1)
->
JASS:
call ForGroup(...)

JASS:
if CountUnitsInGroup(udg_Demisence_Targets) == 0 then
call PauseTimer(Demisence_Timer)
else
call DoNothing()
endif
endfunction
->
JASS:
if CountUnitsInGroup(udg_Demisence_Targets) == 0 then
call PauseTimer(Demisence_Timer)
endif
endfunction
Instead of using CountUnitsInGroup, you could update an integer that keeps up with the number of units in the group.

JASS:
local real Demisence_Angle      = AngleBetweenPoints(GetUnitLoc(GetSpellAbilityUnit()), GetUnitLoc(GetSpellTargetUnit()))
Leaks.


Didn't correct the rest, I hope you get the idea :)
 
Level 11
Joined
Oct 13, 2005
Messages
233

JASS:
if CountUnitsInGroup(udg_Demisence_Targets) == 0 then
call PauseTimer(Demisence_Timer)
else
call DoNothing()
endif
endfunction
->
JASS:
if CountUnitsInGroup(udg_Demisence_Targets) == 0 then
call PauseTimer(Demisence_Timer)
endif
endfunction
Instead of using CountUnitsInGroup, you could update an integer that keeps up with the number of units in the group.
Here's a more efficient option:
JASS:
if FirstOfGroup(udg_Demisence_Targets) == null then

Perhaps I've missed something, but I don't see how this is related to the tutorial, especially considering the fact that this is in JASS. Perhaps a better location for most of these questions would be the Triggers & Scripts forum? :p
 
Level 5
Joined
Oct 24, 2007
Messages
90
Very useful tutorial :)
I would definitely use this, but now that I understand vJass I prefer to go with that.

Will this still work if the same unit recieves the spell twice? Wouldn't the values overwrite themselves? For example, if a unit casts a HoT to another unit and, before the first spell is finished completely, another unit HoTs the same unit that was HoTed in the beginning. Will that work?
 
Last edited:
Level 10
Joined
Jan 18, 2010
Messages
79
I think it's a great tutorial but lacking a bit in information...

For example, if you save a value of 1, then save another with the same value, the previous will be overwritten.

Pretend a Paladin with "Heal Over Time" is fighting a Death Knight with "Damage Over Time" (the exact opposite of your spell). Now, the Paladin will cast "Heal Over Time" on himself and the duration will be saved of 0. Now, the Death Knight casts "Damage over Time" on the Paladin and the duration will be saved of "0". Won't the Paladin's spell stop healing him?

Also, do points and other things that leak need to be assigned to a variable and then destroyed, or is clearing the child hashtable enough?


Yeah...it doest overwrite the Paladin's Heal Period with DeathKnight's Damage Period. You could solve this easily by storing "Damage Period" as 1, and "Healing Period" as 2. The other Data as other integer.
 
Level 2
Joined
Feb 3, 2011
Messages
24
Nice, some things i get but still. No wonder, it's me lol. One Hint, if you're a N00B at- /experiencing triggering like me, you should read it 2 - 3 times if you dont get it.

+ Does anyone know how i can do this with a triggered spell?: --->
-Level 1: Deals 100 dmg + stuns for 2.5 secs
-Level 2: Deals 200 dmg + stuns for 3 secs
-Level 3: Deals 300 dmg + Stuns for 4 secs
Basicly i want to know How you increase damage (stun time, Heal time, so on) with a triggered spell.
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
+ Does anyone know how i can do this with a triggered spell?: --->
-Level 1: Deals 100 dmg + stuns for 2.5 secs
-Level 2: Deals 200 dmg + stuns for 3 secs
-Level 3: Deals 300 dmg + Stuns for 4 secs
Basicly i want to know How you increase damage (stun time, Heal time, so on) with a triggered spell.

Kind of offtopic but here we go.



Create a dummy unit with no model and give it locust ability. Then create an ability based on Storm Bolt. Make it do zero damage. Add to neutral allowed targets. Use this trigger:

  • Untitled Trigger 074
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to *your ability*
    • Actions
      • Set p1 = (Position of (Triggering unit))
      • Unit - Cause (Triggering unit) to damage (Target unit of ability being cast), dealing (100.00 x (Real((Level of (Ability being cast) for (Triggering unit))))) damage of attack type Spells and damage type Normal
      • Unit - Create 1 Dummy for Neutral Passive at p1 facing Default building facing degrees
      • Unit - Set level of *summy ability* for (Last created unit) to (Level of (Ability being cast) for (Triggering unit))
      • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Target unit of ability being cast)
      • Unit - Make (Last created unit) Explode on death
      • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation(udg_p1)
 
Level 2
Joined
Feb 3, 2011
Messages
24
Kind of offtopic but here we go.



Create a dummy unit with no model and give it locust ability. Then create an ability based on Storm Bolt. Make it do zero damage. Add to neutral allowed targets. Use this trigger:

  • Untitled Trigger 074
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to *your ability*
    • Actions
      • Set p1 = (Position of (Triggering unit))
      • Unit - Cause (Triggering unit) to damage (Target unit of ability being cast), dealing (100.00 x (Real((Level of (Ability being cast) for (Triggering unit))))) damage of attack type Spells and damage type Normal
      • Unit - Create 1 Dummy for Neutral Passive at p1 facing Default building facing degrees
      • Unit - Set level of *summy ability* for (Last created unit) to (Level of (Ability being cast) for (Triggering unit))
      • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Target unit of ability being cast)
      • Unit - Make (Last created unit) Explode on death
      • Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation(udg_p1)

THX,btw !
Since you seem to know this how to do increased dmg for how many yards/meters it goes. and you could use hashtable for it right_?
 
Last edited:
Level 5
Joined
Mar 28, 2009
Messages
70
I can't wrap my head around how you're using Handles :( How are you able to store your Handles as "Key - Picked Unit" and "Key - Target Unit of Ability" in your example Healing spell??

EDIT: found my answer. I'm using JNGP. Will JNGP support these handles in Jass?
 
Level 5
Joined
Mar 28, 2009
Messages
70
Sorry, my Jass knowledge is pretty limited, I didn't understand.

Thanks for the help tho
 
Level 13
Joined
Jun 9, 2009
Messages
1,129
omg :/ :/ Here is trigger :&
  • GUI GetHandleId
    • Events
    • Conditions
    • Actions
      • Set YourVariable = (Triggering unit)
      • -------- This is unit variable --------
      • -------- You also need an integer --------
      • -------- To get handle id --------
      • Custom script: Set udg_GUIHandle = GetHandleId(udg_YourVariable)
      • -------- Code above --------
is that so freakin hard ?
 
Level 7
Joined
May 13, 2011
Messages
310
Wow this was really helpful, much simpler than I expected hashtables to be. Just got a few questions though:

What version of Warcraft/WE do you need to use hashtables?

I was reading the comments on this page and I was getting a bit worried. I use NewGen all the time now, but from what I've read it appears I need to use Custom Script/JASS to use hashtables with NewGen. I mean, I can use JASS, but not being able to use hashtables in GUI would be a bummer.
Is that correct? Or did I misunderstand?

If anyone could answer that'd be choice (sweet) :thumbs_up:
 
Level 7
Joined
May 13, 2011
Messages
310
Lemme get this straight... to get the handle ID of something with JNGP, I have to use JASS (namely GetHandleID()), but apart from that I can use GUI to work with hashtables (creating, clearing, etc).

Is that right?
 
Level 7
Joined
May 13, 2011
Messages
310
Sweet, that's awesome. So I guess I can just use the GUI way of getting a handle's ID in the normal WE if I want, otherwise I can just be lazy and use custom script.

Thanks guys!
 
Top