Dynamic values storage
One note, this was called Paladon's integer array indexing system but after talking to PurplePoot he explained me why it cannot be named like that.
|Attention!»||This system is deprecated, meaning, it is outdated, no longer in use. Hanky's "Dynamic Indexing Template" is the latest standard on fulfilling the purposes of this system; using Hanky's indexing template over this one is recommendable.|
What is Dynamic values storage? It's and easy to use variable system used by spell makers to make Multi Unit instancable spells.
Why use it? It is easy and i found no other way than it, though other ways exist.
What do you need to use it - nothing it isn't a custom script or anything like that it is simply a variable based system.
Can you make any spell in GUI MUI with this - the answer is yes.
Okay without delay i will now introduce you how to set up before using the system.
For using the system itself you only need 1 integer array variable, example:
- index - this is the integer variable we are going to use for indexing
Now how does it work that is pretty easy once you trigger out the first spell with this system, we are going to use several arrays of the variable index
and i will explain the trigger below:
Now maybe you are asking yourself why are we using index and index for? Here is why:
-index variable we are going to increase and decrease whenever we initialize or finish the effect of the desired spell so if it is 0 when we begin to cast
it we turn on the loop gen which will be our periodic trigger while when the spell effect finishes we decrease it and if it is 0 again then there are no more instances
of our spells running and we can turn off the periodic trigger and reset the index variable.
-index variable we are going to use for storing variables like units/damage/locations,etc. We are only going to increase it and never decrease it, why?
Imagine you have 2 spells running at the same time and you decrease the index value and the second spells variables get mixed up with the first one.
So how to stop piling up of index value? Easy when the spell effect finishes and we decrease index variable we will if the index is equal to 0(that means no spell instances are running)
and we can reset the index to 0.
Now in loop triggers we are going to use index[n] variable where the n will vary from 2-y.
Why are we going to use index variable and not for example LoopIntegerA? Cause IntegerA can cause a strange blizzard bug and it's cleaner this way.
Now what we are doing in the trigger is we are going to cycle through each value of index variable using index variable, in plain words:
you have 3 spell instances running and now each second you want an effect to happen so we cycle through each spell casted and do it's action while not messing up the
other 2 spell instances by using the index through we stored them.
-Making a first MUI spell with Dynamic Values Storage method
Now the first MUI spell we are going to make is a DOT(damage over time) one.
We will base it on storm bolt and rename it to Heart Stab.
Then we prepare the necesary variables we have in mind:
- unit array variable - target // for storing the target into a variable
- unit array variable - damage_source // for gold/exp proper gain
- real array variable - dpi // damage per interval
- real array variable - duration // spell duration
- string variable - dpi_effect // string of our damage effect
- real array variable - damage_interval // damage interval in seconds
- real array variable - interval_check // this variable will always have a starting value of 0 cause we are going to use it for damage interval checking
Now the initial trigger setup:
That is it, we stored all the values we need into variables which we stored via integer index for future use and now we can make the loop trigger.
Now the most important thing we forgot, we didn't made it multi leveled, but with several modifications we can easily do that.
Spells without multi level support aren't good so if you wish to make MUI spells at least add multi level suport to them.
We are going to modify the values to our desire, i modifed them like this:
And now we set up the settings for a multi leveled spell, the next step is making the loop trigger.
First of all our damage_interval is a multiple of 0.25 so we are going to use a trigger which runs every 0.25 seconds.
Then we are going to cycle through the index values with index variable.
The loop trigger should look like this:
All parts of the trigger are commented if you don't understand something feel free to pm me or post your question here.
There is a demo map attached which contains the spell we made feel free to test it's MUI-ness and does it bug.
Now i am not talking about loop trigger or anything periodic, i am talking about loops used in spells. An example of loop would be:
Now what can we do with loops? We can easily set up several functions like creating units/special effects and instead of writing a bunch fo lines to create
a circle effect we just run a loop for the desired number of effects.
In this example i will show you how to use loops to make an Incendiary Blast spell.
I suggest everyone to use channel to make custom spells cause it is intended for that.
The spell idea will be:
- deals x damage to the target
- if the target dies it will create several fire particles flying away(we will use loops for this)
- upon fall the fire particles will deal damage in 150 AOE
Okay first of all we are gonna need a dummy unit. What is a dummy unit? It is a unit without a model or with a model acting like a missile.
The dummy we are going to use will use a custom model called dummy.mdx which has no model at all but has attachment points.
Upon importing we set the dummy to use it and we set up our dummy changing:
- it's abilities(i always add invulnerable and locust ability)
- it's name
- it's classification(if it is a worker)
- change it's attacks enabled to none if attack is enables
- change it's colision to 0
- change it's movement type to fly(recommended)
- change it's food cost to 0
The dummy is prepared and now we make our trigger.
I will comment all the variables i used in the trigger to make it easier to understand.
Now we have set up our initial trigger and used the loop function for creating missile/particles instead of coping the same thing 5 times.
This is quite usefull cause it shortens the time needed to do a lot of things.
Now that we have set up our initial trigger we supose the target unit has died so we have created the dummy and now we need to move it.
Be aware that the model dummy.mdx i used doesn't support Z angle changing but there is a one that does.
I won't complicate the spell with that but i am going to use a parabola function which i will try to explaing better to you.
Here is the parabola code we are going to use:
function ParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
The function takes the real h which represents the maximum height we want the missile to achieve.
The function takes the real d which represents the maximum distance we want the missile to be able to reach.
The function takes the real x which represents the current distance the missile has traveled.
Then the function calculates all the data we gave it and returns a height real.
It can also be done via GUI but it will be messy.
I will use a GUI version of parabola calculation.
Here is how the loop trigger will look like:
Now maybe you asked yourself why do we destroy special effects we create instantly? It prevents leaks but is still usefull cause it will make the speical effect play it's death animation.
Note: Some effects don't have death animation so they will play their whole animatiom(thunderclap for example) but this is most usefull for missile effects cause they all have death animations.
You may notice i used some custom scripts where i could have used GUI functions, why? I find it easier, it would be pain in GUI to calculate:
( 4 * udg_IB_loop_temp_real / udg_IB_loop_temp_real) * ( udg_IB_loop_temp_real - udg_IB_loop_temp_real ) * ( udg_IB_loop_temp_real / udg_IB_loop_temp_real )
I used custom scripts cause that is JASS codes in GUI, you can manipulate both GUI and JASS like this.
Also the most important thing about custom scripts is that you can't make a decent spell with locations and unit groups without them.
Why? You need them to clean leaks or it will affect the FPS.
Also you may notice i used point variables called IB_leak_point and IB_loop_leak_point and i didn't used indexes on them, only simple values.
I did that cause they are immediatly used and destroyed so there is no point in their indexing.
This also aplies to IB_temp_real and IB_loop_temp_real variables, but as reals cannot be destroyed and don't leak i just set their values to 0.
That concludes our loop part.
-Avoiding trigger overflow
What do i mean with this? I recently saw a map with 70-80 triggers and that was a system!
Now what did the maker of the system do, he made a trigger like this:
For each player and a 4 periodic triggers for each player.
Now to avoid that you can use array variables but what hapens when you use too much periodic triggers? It is uneficent.
To avoid that you can easily make a trigger that runs each 0.01 second and checks is the time to do actions now.
I wouldn't recommend doing this for all triggers but if you have a spell which uses multiple effects(example fading + location change) you can do the following:
And that is that, if all loop effects aren't active we just turn off the trigger and reset their indexes.
This concludes this part of the tutorial.
-PGS(Paladon's General System)
Not tested with latest versions of WC3, may cause issues.
The map contains 3 trigger which are used as the PGS.
Dynamic values storage with DIR system
- tree revival
- unit revival
- other stuff
First of all what is DIR system? Is an addition to the indexing system which makes the index used for actual indexing get recycled.
To impement it we are going to take example #1.
Now we are going to add several new variables:
- HS_dyn_index => Integer variable, not array
- HS_index_selected => Boolean variable, not array
- HS_index_is_empty => Boolean variable, array
First of all you should know how the the basics i wrote about in the upper section of the tutorial, if you don't know first read the upper part of the tutorial.
Now we are going to make some changes, first of all we won't be using HS_index for indexing, instead we are going to use HS_dyn for indexing.
The second boolean variable is going to be used to make sure that HS_dyn_index carries an value which is not already taken.
The HS_index_is_empty we are going to use in the loop trigger for checking if the array is free again.
Now after reworking the initial HS init trigger it looks like this:
The trigger is well commented but if you have any additional questions feel free ask in this thread or send me a private message.
Now we aren't finished we still need to dynamicaly free the index arrays when they aren't used we will do so in the loop trigger:
To test dynamic indexing recycling i have made a timer and a debug message in the demo map.
This way there is a possibility to exceed maximum array size and to do it you must:
- Cast the spell every 1 second
- If we take the spell lasts 15 seconds that means 15 instances per unit max
- So that means you will exceed the array limit if you have about 550 units casting the spell in the same time every single second
Possible but i think only in theory.
I think the tutorial may be aproved now that i fixed the issue and implanted Dynamic Index Recycling in the tutorial.
NOTE: The name of the map is MUI example 4 cause i deleted a part of my tutorial that had the MUI example 3 map.
Moyack for the parabola formula
Now this is where the tutorial ends for now. I may add more informations and chapters but for now this should do.
I hope this helped you^^