The 1.5 patch has brought upon us many useful new features. One of which is the new Data category "User types". I believe these act as an excellent alternative to declaring big records/arrays in script.
This guide is intended as an simple and straightforward guide to User types and it's potential uses. This tutorial aims to make clear how to create custom User Types, and read them with triggers. Once you are able to read them, using them to perform other functions should be pretty straightforward.
This guide however, does not intend cover field modifications or saving to banks. I personally believe these two functions should be pretty straightforward once you've learned how to use the user data functions (Field reading in particular)
Should you prefer a more comprehensive guide on the user of User type's which teaches similar concepts to that covered in this guide, zeldarules28 has done an excellent job right here.
Why User types?
They are comparable to SQL tables (databases), whereby each instance is comparable to the record in the table
You have the freedom to decide what your fields are and how they are initialized
Their instances can be modified in game (If their flag is set)
User types can be directly saved to banks (Save User Type Trigger),
whereby only modified records/fields are saved to optimize bank usage.
Localized initialization of script variables makes it much easier to modify values when balancing your map
Known caveats
New instances cannot be added in game, only pre-declared instances may be added.
Does not allow boolean fields (So we use int 0 and 1 as replacement)
We currently do not have much information on any technical limitations User Types may have.
Reading from User Types may be slower than reading from local variables in Triggers/Script (In theory)
Some potential uses
Save data tables
Hero data tables
Tower defense wave data tables
Dialog item display data tables
Item data tables
There are many other ways User types can be used, these are just a few of them. Play around and innovate for best results.
Additional notes
I do not support the use of XML for the creation of user types here as I feel the GUI simplifies the process very nicely
Thats great! But how to we use them?
For my example, I will be spawning a few units for TD waves.
First we create them with DATA:
1a) Open up your data editor (Hotkey: F7)
1b) Click on Detail view (Hotkey: Ctrl + 2) as it is the easiest to work with (IMHO)
This is an optional step
2) Open up a User Types tab
3) Create your User Type
Right click > Create new User Type. Give it a name that will help you identify it easily. I've chosen 'data_wave'. Do not check 'Defines default values' as this will prevent you from adding new instances. Click Okay!
4) Define your fields
Right click @ fields and add new field. For those of you who are familiar with SQL table creation through a GUI, this process is similar.
Specify the following fields
Id: Self-explanatory, give it an Id that will make it easy for you to identify
Type: The variable type
Value count: The array size (I left it as 1)
Editor column: This is important, it must be a non-zero unique number or you will not be able to see it in the instances table.
Modifiable flag: Flag this if you want to be able to modify this field with script. Not doing so will cause data to ignore attempts by the script to mod these values.
At this point we will consider every other option to have little novelty, thus we will leave them at their default values.
With a few extra fields added:
5a) Optional step: Define default values.
Double click on the defaults (or modify), and specify the value of all your fields. This is not necessary but it helps greatly if you plan to have many instances with identical vales. The screenshots below depict this process.
5b) Add your instances:
Just click the add button. Modifying fields is as simple as double clicking and setting them as seen earlier in the previous step (5a). I've added 3 instances for this example. Remember to specify an Id of your choice. I prefer using integers as it makes it easier to iterate them later with script.
6) Optional step: Give your user type a description, This description will appear when you callback the user type name in the trigger editor.
Then we read/use them with TRIGGERS/SCRIPT:
I'm assuming here you opened up a new map for the tutorial. The steps below refer to the screenshot above.
1) Open up your trigger editor, delete the melee initialization, we won't be needing it.
2) Create a new trigger with an event of your choice. I chose "When spacebar is pressed"
3) Create a few buffer local variables. These should match those in your User Type.
Notes:
The use of local variables here is to buffer our data and improve script readability.
One of the limitations discovered with the User Type functions here is that they did not allow instance ID's to be called directly via a number (i_Wave), thus I was forced to use custom script to set it. (Please refer to the example if this is not clear.)
4) Perform your actions:
I've chosen to iterate through the User Types and spawn the monsters whenever the event fires. This process is done by simply buffering the fields of the current instance into the buffer local variables and using them to perform actions. I've also added a condition which causes actions to be skipped if they are no longer any instances to read.
5) Run the script!
You can find my example attached. Just press spacebar and it will spawn the units.
Conclusion:
This is not the conclusion you are looking for. Happy Mapping!
FAQ's
Any plans for a modification or banking tutorial? None at this point of time, as I do not have enough experience with banks.
Modifying fields is very straightforward though, Just use "xxxxx"
Feel free to ask any questions. I'll update this section if anything trivial comes up.
I couldn't get the "User Instance From Reference" function to work for the life of me, and I'm guessing you had a similar experience.
Your usage of IntToString() then to get the instance from an integer should be in bold with rainbow highlights. Why no mention of it?
EDIT: Never mind, you did.
EDIT 2: Hm, but you can already get an instance from an index. I might be missing something but what's the point?
No worries. I haven't tried User Instance From Reference yet, Will probably give it a try later.
As for the instance from an index:
In many programming languages, we use 0 indexing for our arrays. This means that array[0] returns the first element. Instance from an index uses 1 indexing, with 0 being reserved for the default instance.
It's just a matter of preference. For example, if I wanted to have a while loop that iterates through 10 instances and stores them into an array.
With 1 indexing:
inti=1;int[10]j;// 0 Indexed arraywhile(i<=10){j[i-1]=UserTypeGetInt(Indexi);//Just a pseudocode}
With 0 indexing
inti=0;int[10]j;// 0 Indexed arraywhile(i<10){j[i]=UserTypeGetInt(Idi);//Just a pseudocode}
I personally find the latter easier to type and debug, as i don't need to add a -1 offset every time I reference my array(s).
Introduction
The 1.5 patch has brought upon us many useful new features. One of which is the new Data category "User types". I believe these act as an excellent alternative to declaring big records/arrays in script.
This guide is intended as an simple and straightforward guide to User types and it's potential uses. This tutorial aims to make clear how to create custom User Types, and read them with triggers. Once you are able to read them, using them to perform other functions should be pretty straightforward.
This guide however, does not intend cover field modifications or saving to banks. I personally believe these two functions should be pretty straightforward once you've learned how to use the user data functions (Field reading in particular)
Should you prefer a more comprehensive guide on the user of User type's which teaches similar concepts to that covered in this guide, zeldarules28 has done an excellent job right here.
Why User types?
Known caveats
Some potential uses
There are many other ways User types can be used, these are just a few of them. Play around and innovate for best results.
Additional notes
Thats great! But how to we use them?
For my example, I will be spawning a few units for TD waves.
First we create them with DATA:
1a) Open up your data editor (Hotkey: F7)
1b) Click on Detail view (Hotkey: Ctrl + 2) as it is the easiest to work with (IMHO)
2) Open up a User Types tab
3) Create your User Type Right click > Create new User Type. Give it a name that will help you identify it easily. I've chosen 'data_wave'. Do not check 'Defines default values' as this will prevent you from adding new instances. Click Okay!
4) Define your fields Right click @ fields and add new field. For those of you who are familiar with SQL table creation through a GUI, this process is similar.
Specify the following fields
At this point we will consider every other option to have little novelty, thus we will leave them at their default values.
With a few extra fields added:
5a) Optional step: Define default values. Double click on the defaults (or modify), and specify the value of all your fields. This is not necessary but it helps greatly if you plan to have many instances with identical vales. The screenshots below depict this process.
5b) Add your instances: Just click the add button. Modifying fields is as simple as double clicking and setting them as seen earlier in the previous step (5a). I've added 3 instances for this example. Remember to specify an Id of your choice. I prefer using integers as it makes it easier to iterate them later with script.
6) Optional step: Give your user type a description, This description will appear when you callback the user type name in the trigger editor.
Then we read/use them with TRIGGERS/SCRIPT:
1) Open up your trigger editor, delete the melee initialization, we won't be needing it.
2) Create a new trigger with an event of your choice. I chose "When spacebar is pressed"
3) Create a few buffer local variables. These should match those in your User Type.
Notes:
4) Perform your actions:
I've chosen to iterate through the User Types and spawn the monsters whenever the event fires. This process is done by simply buffering the fields of the current instance into the buffer local variables and using them to perform actions. I've also added a condition which causes actions to be skipped if they are no longer any instances to read.
5) Run the script!
You can find my example attached. Just press spacebar and it will spawn the units.
Conclusion:
This is not the conclusion you are looking for. Happy Mapping!
FAQ's
None at this point of time, as I do not have enough experience with banks. Modifying fields is very straightforward though, Just use "xxxxx"
Feel free to ask any questions. I'll update this section if anything trivial comes up.
Thank you for this, it was quite helpful.
I couldn't get the "User Instance From Reference" function to work for the life of me, and I'm guessing you had a similar experience.
Your usage of IntToString() then to get the instance from an integer should be in bold with rainbow highlights. Why no mention of it?
EDIT: Never mind, you did.
EDIT 2: Hm, but you can already get an instance from an index. I might be missing something but what's the point?
No worries. I haven't tried User Instance From Reference yet, Will probably give it a try later.
As for the instance from an index: In many programming languages, we use 0 indexing for our arrays. This means that array[0] returns the first element. Instance from an index uses 1 indexing, with 0 being reserved for the default instance.
It's just a matter of preference. For example, if I wanted to have a while loop that iterates through 10 instances and stores them into an array.
With 1 indexing:
With 0 indexing
I personally find the latter easier to type and debug, as i don't need to add a -1 offset every time I reference my array(s).