I'm turning what DSG said towards the practical side (instead of the theoretic side, as that is DSG's strong point).
An array is a variable that can store multiple values.
An example would be the variable "Hero", which stores a unit.
Hero[1] stores the hero of Player 1 (Red)
Hero[2] stores the hero of Player 2 (Blue)
Hero[3] stores the hero of Player 3 (Teal)
As you may begin to see, arrays are widely used for making things MPI (that means Multi-Player Instanceable, or being able to make a system works for ever player).
Any system that uses something of the hero, utilizes that arrayed variable.
Example: if you want to show the movement speed of the hero, you would do:
-
MS
-
Events
-
Player - Player 1 (Red) types a chat message containing -ms as An exact match
-
Player - Player 2 (Blue) types a chat message containing -ms as An exact match
-
Player - Player 3 (Teal) types a chat message containing -ms as An exact match
-
Conditions
-
Actions
-
Game - Display to (Player group((Triggering player))) the text: (Movement Speed: + (String((Current movement speed of Hero[(Player number of (Triggering player))]))))
If Blue said "-ms", then "Hero[(Player number of (Triggering player))]" will turn into "Hero[2]" and will thus show blue's movement speed.
If you know that every player can only have 1 unit either way, and that the cooldown of their spells is greater than the duration of that spell, then making things MUI can be a waste of time (as MPI is good enough).
It IS possible to make things MUI with arrays, but this is more complicated (and limited, but the limit is rather high, so that should not matter), so generally: people use hashtables nowadays.
An array is limited to 8192 indices (from 0 to 8191), meaning that Var[8191] = 5 works, but Var[8192] = 5 would not do anything.
Hashtables are much like dual-arrays (Var[X][Y]), but can take extremely high values and can take any value (real, integer, unit, ...).
Why is this useful? All objects in Warcraft have a special number assigned to them. That number is unique and individual: every unit on the map will have a different number, always.
So when you store the Unit's ID in the first array and use the second array as a quick-slot for specific values, you can make something MUI.
Example:
I cast a spell that should just damage the target after a certain time (a delayed strike).
Var [Unit ID] [0] can hold the timer
Var [Unit ID] [1] can hold the damage
Var [Unit ID] [2] can hold the caster (this is useful when dealing damage)
-
Test trig 1
-
Events
-
Unit - A unit Starts the effect of an ability
-
Conditions
-
Actions
-
Set HandleID = (Key (Target unit of ability being cast))
-
Set Damage = 100.00
-
Set Time = 5.00
-
Hashtable - Save Damage as HandleID of 0 in TestTable
-
Hashtable - Save Time as HandleID of 1 in TestTable
-
Hashtable - Save Handle Of(Triggering unit) as 2 of HandleID in TestTable
-
Unit Group - Add (Target unit of ability being cast) to TestGroup
(You don't particularly need the "Damage" and "Time" variables, you can set them directly in the Hashtable - Save [value]" as well, but if you want to upload your spell, you should create some kind of easy-to-edit system, so using variable like that is the easiest).
As you can see: the HandleID is the ID of the targetted unit. This number is very high and is different for every unit.
Because we need some kind of way to actually do anything with these values.
This is why we create a unit group and we add the unit who's ID we used to store the values in to that group.
Now the loop-trigger would look something like this:
-
Test trig 2
-
Events
-
Time - Every 0.03 seconds of game time
-
Conditions
-
Actions
-
Unit Group - Pick every unit in TestGroup and do (Actions)
-
Loop - Actions
-
Set HandleID = (Key (Picked unit))
-
Set Time = (Load 1 of HandleID from TestTable)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
Then - Actions
-
-------- The spell did not end yet --------
-
-------- We decrease the timer of this unit, because it has to end at some point --------
-
-------- Do not forget this! --------
-
Hashtable - Save (Time - 0.03) as 1 of HandleID in TestTable
-
Else - Actions
-
-------- Ending the spell --------
-
-------- Dealing damage --------
-
Unit - Cause (Load 2 of HandleID in TestTable) to damage (Picked unit), dealing (Load 0 of HandleID from TestTable) damage of attack type Spells and damage type Normal
-
-------- We remove the unit from the group so it won't loop anymore --------
-
Unit Group - Remove (Picked unit) from TestGroup
-
-------- This is necessary to clean up the unused hashtable slots --------
-
Hashtable - Clear all child hashtables of child HandleID in TestTable
I don't know what else I can say here... if anything is not clear, please say so.
Note that this can not be used if the cooldown is lower than the spell duration!
In that case, you can create a dummy unit and set HandleID to Key(last Created Unit), then save both the target and the caster in the hashtable.
Add the dummy unit to the group, loop through it and do anything as you would normally, but whenever you make any unit-related changes (move the unit, damage, ...), then you should use the value you stored in the hashtable as the target.
Anything else?