My project currently has 2 large triggers controlling an AI Player's actions. One to control unit spawns and buffs. The other to say when to increase what and when.
But because these triggers are tied together so closely, with one controlling all of the variables in the other, I'm going to end up with a lot of Global variables. Two sets of intVariables that control the number of each unit type to make and what upgrade level the individual unit types receive (Max#)(UPGLVL), and another UnitTypeVariable that will be changed to actually change the unit types based on upgrades (zergling>raptor/swarmling etc.)
I've been learning the triggers themselves fairly well, but I'm trying to find a way to control my data a bit more. I'm assuming I need to add three records, then have the triggers call upon those records somehow. But records and arrays are not my strong suit. Arrays, as I understand it, are more for randomization. Which is not what I want.
I guess my question is are Records what I'm looking for, and how do I call upon them effectively? I've put a bit of time in doing what I have, and I don't want to muck it up now just trying to make it look pretty.
Records are a good way to organize a lot of variables that belong together and reduce the amount of clutter in the variable picker. The variables are usually of different types and/or for different functionality. For example, you could name a record "Settings" and store in it variables like "Lock Camera <Boolean>", "Rounds To Win <Integer>" and "Wave Spawn Point <Point>". Records are particularly useful for storing dialog and dialog item variables.
Arrays are for storing multiple values of the same type for the same purpose, such as a bunch of buttons that would be used in a custom list box. Often you'll want to use arrays when you have multiple players and use the player numbers as indexes. Sometimes you don't know exactly how many array elements you'll need but that you probably won't need "more than 100", and in those cases you'd have another variable of type integer to track how many elements there are. Other times you know exactly how many elements you need. You can even use integer constants to set the size of an array, so you could easily change things later.
To use records, you need to first create a record, then create a variable and set its type to "- Record" and then pick your record. If there's only one record in your map, it'll be picked automatically.
Records are similar to data tables, in that they can both act sort of like associative arrays. However, records are preferable because you can directly interact with them in the GUI, whereas data tables require that you manage the names yourself using presets. Data table functions may also perform a little bit slower than record variables. The advantage of data tables is that you can store an arbitrary amount of variables at different points in time in the game, and they can be used to pass data to triggers using generic events. Records are the best choice if you know (almost) exactly how many variables you need of each type.
You can also nest records inside other records to create entire hierarchies of records. To do this, records lower in the hierarchy (or inside other records) must appear first in the trigger list or you'll get a compiler error.
You can also have arrays inside records and record arrays.
What I took from that is that yes, I need records. Jargon Jargon Jargon. Lol.
It's actually a very definitive explanation and better than I've seen so far, but my mind is still trying to put the information into a "does not compute" Variable under the Record "Things I don't understand" of my brain. :P
Here's the end all beat all question. What order should a map be built in? I built just enough of the terrain to start testing triggers and data to make a Proof of Concept that I could actually make things work.
Now that I know it can work, I have a lot of terraining to do, a lot more data to edit(upgrades/abilities/etc.), and a lot of new trigger sequencing to do as well as a streamlining of my current triggers. Is it best to simply do one thing to completion (i.e. completely finish my map terrain) and then move on to the next thing, or is it common to be jumping back and forth, do a section of terrain, then making sure all the data for that section is complete, making sure all triggers pertaining to that section are in place and up to date, etc?
I'm having a lot of fun making my vision come to life, but I keep feeling like I'm doing too much here, not enough there.
if you finish terrain you will come to the point where something is wrong and you have to change it again. just make everything playable and then polish it with completion.
btw all of my maps have an record called player and an array (index = player number) of this record.
More than anything I just need to make up my mind. Or at least keep notes of what I'm trying to accomplish. Everything I want to add is going to stretch this map out further and further.
EDIT: I'm not saying stretching the map out is a bad thing, but the larger I make it, the faster the pace I need so that a single game doesn't take two hours. I'm wanting this to be a fun idea to do once or twice, not a drawn out affair that make the player not want to play it again or attempt any sequels I MIGHT make in the future.
Example, with my decision to include unique unit upgrades, I now need to decide if those upgrades should be squeezed into the already existing areas as far as unlocking them for the player goes, or if I should expand the existing conditions so that too much isn't thrown at the player at once.
In the very second "Level", banelings are introduced. The player then has to wait until a certain number are defeated before they can be integrated into the swarm, allowing them to be used. The next such event for Roaches would be at level 5, but now I have to figure out if I want to throw in raptors and the ability for the player to upgrade to them at level 4 and have two new things at nearly the same time, or if I should push the roaches back to allow breathing room for the player to pick and choose things at a more natural place.
I have some nice unique upgrades in mind for the player to choose from, but I don't want them to feel rushed in the decision making process.
To use records, you need to first create a record, then create a variable and set its type to "- Record" and then pick your record. If there's only one record in your map, it'll be picked automatically.
The next time you write this sentence, sir or madam, please make sure it's BOLD, ITALICIZED, AND IN CAPS.
Somehow I read your post four times without noticing this very important information, and it was the one sentence that was tying me up. I was trying to make records with my variables inside, but then trying to find a way to call them in functions and expressions without setting up variables to be those records. I'm sure that feature allows you to do awesome things by changing the record that's called upon for some god know's why reason, but it was tripping me up for two days.
Your explanation was spot on, and I thank you for the help. I'm just frustrated with myself that it took so long to figure out.
I notice that you still want help with when to use arrays.
Let's say you have a bunch of variables named, player 1 hero, player 2 hero, etc., not only does this make calling them hard, but you have create a whole bunch of different variables, instead it's much easier to create 1 array called player hero[8]. You can create an array by checking the array box when you've selected a variable, you can then either set its size to a number of your choice, or a constant. The size of the array determines how many values it can hold.
Note that you can set record variables as arrays, allowing for you to store a bunch of player specific data.
I notice that you still want help with when to use arrays.
I'm going to fool around with arrays eventually, but I've learned I need to limit the number of things I'm trying to teach myself each day. lol.
I've finally figured out records (a bit), but I have a few questions about controlling variables in general.
If I make a record and set up a local variable to be that record, then have my trigger change the value of one of the variables inside the record, will that change be permanent, or will it last only until the trigger ends and it wipes?
Event> Unit dies
Local Variable "Record of Deaths"
if unit type, modify unit type in "record of deaths" plus 1
If a have 3 records for numbers, and want record 1 variables to be expressions of values pulled from records 2 and 3 (variable 1a = (variable 2a * variable 3a), would I need to nest record 3 inside record 2, and then nest record 2 inside record 1?
Is there not simply an option to mark a variable as "hidden" so that it doesn't show up again until it's no longer marked hidden? This would make things so much easier.
Records are only blueprints, not the variables themself.
That means whenever you set a variable (local or not) to be a certain record, you dont create a shortcut to access the record as if it was some central variable-hub, but instead your new variable (or record-object) has now "split" into all the variables you set up inside your record. But this doesnt mean that those variables it just split into hold the same values as other objects from the same record.
Therefore, your local variable will be terminated at the end of the trigger, with all the information lost. And for the same reason record objects dont nest if you do stuff like recordObjectA.valA = recordObjectB.valA * recordObjectC.valA
And one way I WANT to use arrays, which I think I can, is to set up a record array. I think. I have 3 records (2 will be local, 1 global)
One is a list of zerg unit types. Two is the burrowed version of the same unit types. The global is a record of integers (kills) matching those same unit types.
In the above example, can I not ask for the assigned number of Record one, assign a local variable to the same assigned number of record 2, and modify the same assigned number of record 3? Without the 30 long string of If Then Else statements I'm currently using?
You cannot mix different types of values in arrays and each record definition effectively creates a new, separate type.
Once you create a variable of a certain record type, you can treat it like any other variable except you cannot pass it into or return it from actions/functions or directly assign them to other variables. The variable picker will then offer you the record variable whenever it detects that one of the variables inside the record (or any nested records) matches the type of value you're editing. If your record doesn't contain any text variables, then it will not appear when you look for variables to use when setting a dialog item's text, for example.
I recommend you try things out more yourself, it's really not that complicated.
Arrays are just lists of values of the same type. They can be ordered or unordered (but you have to make sure they remain ordered or implement a sorting algorithm yourself - and there are some examples for that provided by Blizzard in the Built-in library). Just like records, you cannot pass them directly into or out of functions or assign them directly. That's it really.
Arrays are just lists of values of the same type. They can be ordered or unordered...
Which is what makes me think that should work... It seems like there should be a way to detect item 12 on list one and return item 12 on list two. And in theory, modify item 12 on list three.
Getting/setting array elements is as easy as with any other variable. You just specify the index after the variable name.
To check for values in the array, you use the For Each Integer action to count from 0 to (number of array elements - 1) and an If Then Else action to compare each value in the array to the value you want to find.
You give the For Each Integer action an integer variable and it changes the value of that variable as it counts through the numbers. You then use that variable as the index into the array.
Unfortunately, not with what I had in mind. I understand the application to integer arrays, but what I'm trying to do is create a short hand "list" for comparing a triggering unit type from list a (a record of unit types) and changing a local variable to the matching unit type from list b (an identical record with the same unit types, just burrowed).
I already have a series of if than else statements to do that now, but I'm just trying to see if it's possible.
Surprised this thread went on as long as it did. You can min max all day, but here's the jist of things. Arrays are good for storing many values of the same data type relating to one subject. Records are good for storing many values of different data types relating to one subject.
If the only thing you want to do is compare unit types, then use arrays.
In such a scenario you can set up some sort of code to compare the index. Index[2] relates to a hydralisk on both arrays. You really only need a record when things get more complex and you are comparing many data types.
that would actually be index[1] as arrays are still zero based in SC2, blizzard just sets GUI array sizes to SIZE+1 since so many people didn't know this.
My project currently has 2 large triggers controlling an AI Player's actions. One to control unit spawns and buffs. The other to say when to increase what and when.
But because these triggers are tied together so closely, with one controlling all of the variables in the other, I'm going to end up with a lot of Global variables. Two sets of intVariables that control the number of each unit type to make and what upgrade level the individual unit types receive (Max#)(UPGLVL), and another UnitTypeVariable that will be changed to actually change the unit types based on upgrades (zergling>raptor/swarmling etc.)
I've been learning the triggers themselves fairly well, but I'm trying to find a way to control my data a bit more. I'm assuming I need to add three records, then have the triggers call upon those records somehow. But records and arrays are not my strong suit. Arrays, as I understand it, are more for randomization. Which is not what I want.
I guess my question is are Records what I'm looking for, and how do I call upon them effectively? I've put a bit of time in doing what I have, and I don't want to muck it up now just trying to make it look pretty.
Records are a good way to organize a lot of variables that belong together and reduce the amount of clutter in the variable picker. The variables are usually of different types and/or for different functionality. For example, you could name a record "Settings" and store in it variables like "Lock Camera <Boolean>", "Rounds To Win <Integer>" and "Wave Spawn Point <Point>". Records are particularly useful for storing dialog and dialog item variables.
Arrays are for storing multiple values of the same type for the same purpose, such as a bunch of buttons that would be used in a custom list box. Often you'll want to use arrays when you have multiple players and use the player numbers as indexes. Sometimes you don't know exactly how many array elements you'll need but that you probably won't need "more than 100", and in those cases you'd have another variable of type integer to track how many elements there are. Other times you know exactly how many elements you need. You can even use integer constants to set the size of an array, so you could easily change things later.
To use records, you need to first create a record, then create a variable and set its type to "- Record" and then pick your record. If there's only one record in your map, it'll be picked automatically.
Records are similar to data tables, in that they can both act sort of like associative arrays. However, records are preferable because you can directly interact with them in the GUI, whereas data tables require that you manage the names yourself using presets. Data table functions may also perform a little bit slower than record variables. The advantage of data tables is that you can store an arbitrary amount of variables at different points in time in the game, and they can be used to pass data to triggers using generic events. Records are the best choice if you know (almost) exactly how many variables you need of each type.
You can also nest records inside other records to create entire hierarchies of records. To do this, records lower in the hierarchy (or inside other records) must appear first in the trigger list or you'll get a compiler error.
You can also have arrays inside records and record arrays.
What I took from that is that yes, I need records. Jargon Jargon Jargon. Lol.
It's actually a very definitive explanation and better than I've seen so far, but my mind is still trying to put the information into a "does not compute" Variable under the Record "Things I don't understand" of my brain. :P
Here's the end all beat all question. What order should a map be built in? I built just enough of the terrain to start testing triggers and data to make a Proof of Concept that I could actually make things work.
Now that I know it can work, I have a lot of terraining to do, a lot more data to edit(upgrades/abilities/etc.), and a lot of new trigger sequencing to do as well as a streamlining of my current triggers. Is it best to simply do one thing to completion (i.e. completely finish my map terrain) and then move on to the next thing, or is it common to be jumping back and forth, do a section of terrain, then making sure all the data for that section is complete, making sure all triggers pertaining to that section are in place and up to date, etc?
I'm having a lot of fun making my vision come to life, but I keep feeling like I'm doing too much here, not enough there.
if you finish terrain you will come to the point where something is wrong and you have to change it again. just make everything playable and then polish it with completion. btw all of my maps have an record called player and an array (index = player number) of this record.
@FunkyUserName: Go
More than anything I just need to make up my mind. Or at least keep notes of what I'm trying to accomplish. Everything I want to add is going to stretch this map out further and further.
EDIT: I'm not saying stretching the map out is a bad thing, but the larger I make it, the faster the pace I need so that a single game doesn't take two hours. I'm wanting this to be a fun idea to do once or twice, not a drawn out affair that make the player not want to play it again or attempt any sequels I MIGHT make in the future.
Example, with my decision to include unique unit upgrades, I now need to decide if those upgrades should be squeezed into the already existing areas as far as unlocking them for the player goes, or if I should expand the existing conditions so that too much isn't thrown at the player at once.
In the very second "Level", banelings are introduced. The player then has to wait until a certain number are defeated before they can be integrated into the swarm, allowing them to be used. The next such event for Roaches would be at level 5, but now I have to figure out if I want to throw in raptors and the ability for the player to upgrade to them at level 4 and have two new things at nearly the same time, or if I should push the roaches back to allow breathing room for the player to pick and choose things at a more natural place.
I have some nice unique upgrades in mind for the player to choose from, but I don't want them to feel rushed in the decision making process.
The next time you write this sentence, sir or madam, please make sure it's BOLD, ITALICIZED, AND IN CAPS.
Somehow I read your post four times without noticing this very important information, and it was the one sentence that was tying me up. I was trying to make records with my variables inside, but then trying to find a way to call them in functions and expressions without setting up variables to be those records. I'm sure that feature allows you to do awesome things by changing the record that's called upon for some god know's why reason, but it was tripping me up for two days.
Your explanation was spot on, and I thank you for the help. I'm just frustrated with myself that it took so long to figure out.
I notice that you still want help with when to use arrays.
Let's say you have a bunch of variables named, player 1 hero, player 2 hero, etc., not only does this make calling them hard, but you have create a whole bunch of different variables, instead it's much easier to create 1 array called player hero[8]. You can create an array by checking the array box when you've selected a variable, you can then either set its size to a number of your choice, or a constant. The size of the array determines how many values it can hold.
Note that you can set record variables as arrays, allowing for you to store a bunch of player specific data.
Still alive and kicking, just busy.
My guide to the trigger editor (still a work in progress)
I'm going to fool around with arrays eventually, but I've learned I need to limit the number of things I'm trying to teach myself each day. lol.
I've finally figured out records (a bit), but I have a few questions about controlling variables in general.
If I make a record and set up a local variable to be that record, then have my trigger change the value of one of the variables inside the record, will that change be permanent, or will it last only until the trigger ends and it wipes?
Event> Unit dies
Local Variable "Record of Deaths"
if unit type, modify unit type in "record of deaths" plus 1
If a have 3 records for numbers, and want record 1 variables to be expressions of values pulled from records 2 and 3 (variable 1a = (variable 2a * variable 3a), would I need to nest record 3 inside record 2, and then nest record 2 inside record 1?
Is there not simply an option to mark a variable as "hidden" so that it doesn't show up again until it's no longer marked hidden? This would make things so much easier.
Records are only blueprints, not the variables themself.
That means whenever you set a variable (local or not) to be a certain record, you dont create a shortcut to access the record as if it was some central variable-hub, but instead your new variable (or record-object) has now "split" into all the variables you set up inside your record. But this doesnt mean that those variables it just split into hold the same values as other objects from the same record.
Therefore, your local variable will be terminated at the end of the trigger, with all the information lost. And for the same reason record objects dont nest if you do stuff like recordObjectA.valA = recordObjectB.valA * recordObjectC.valA
@BigDonRob: Go
And one way I WANT to use arrays, which I think I can, is to set up a record array. I think. I have 3 records (2 will be local, 1 global)
One is a list of zerg unit types. Two is the burrowed version of the same unit types. The global is a record of integers (kills) matching those same unit types.
In the above example, can I not ask for the assigned number of Record one, assign a local variable to the same assigned number of record 2, and modify the same assigned number of record 3? Without the 30 long string of If Then Else statements I'm currently using?
You cannot mix different types of values in arrays and each record definition effectively creates a new, separate type.
Once you create a variable of a certain record type, you can treat it like any other variable except you cannot pass it into or return it from actions/functions or directly assign them to other variables. The variable picker will then offer you the record variable whenever it detects that one of the variables inside the record (or any nested records) matches the type of value you're editing. If your record doesn't contain any text variables, then it will not appear when you look for variables to use when setting a dialog item's text, for example.
I recommend you try things out more yourself, it's really not that complicated.
Arrays are just lists of values of the same type. They can be ordered or unordered (but you have to make sure they remain ordered or implement a sorting algorithm yourself - and there are some examples for that provided by Blizzard in the Built-in library). Just like records, you cannot pass them directly into or out of functions or assign them directly. That's it really.
Which is what makes me think that should work... It seems like there should be a way to detect item 12 on list one and return item 12 on list two. And in theory, modify item 12 on list three.
Of course you can!
Getting/setting array elements is as easy as with any other variable. You just specify the index after the variable name.
To check for values in the array, you use the For Each Integer action to count from 0 to (number of array elements - 1) and an If Then Else action to compare each value in the array to the value you want to find.
You give the For Each Integer action an integer variable and it changes the value of that variable as it counts through the numbers. You then use that variable as the index into the array.
@temhawk: Go
I'm not getting anywhere. Can you show me an example code?
Does this help? http://peeeq.de/gui.php?id=3885
@temhawk: Go
Unfortunately, not with what I had in mind. I understand the application to integer arrays, but what I'm trying to do is create a short hand "list" for comparing a triggering unit type from list a (a record of unit types) and changing a local variable to the matching unit type from list b (an identical record with the same unit types, just burrowed).
I already have a series of if than else statements to do that now, but I'm just trying to see if it's possible.
@BigDonRob: Go
Surprised this thread went on as long as it did. You can min max all day, but here's the jist of things. Arrays are good for storing many values of the same data type relating to one subject. Records are good for storing many values of different data types relating to one subject.
If the only thing you want to do is compare unit types, then use arrays.
arr unitTypeDefault = {zergling, hydralisk, ultralisk};
arr unitTypeBurrowed = {burrowedZergling, burrowedHydralisk, burrowedUltralisk};
In such a scenario you can set up some sort of code to compare the index. Index[2] relates to a hydralisk on both arrays. You really only need a record when things get more complex and you are comparing many data types.
@ZMilla93: Go
Glad to know it's possible, but I'm just shot on the idea. Maybe one day after I know what I'm doing, I'll write something out just to prove I can.
@ZMilla93: Go
that would actually be index[1] as arrays are still zero based in SC2, blizzard just sets GUI array sizes to SIZE+1 since so many people didn't know this.
Still alive and kicking, just busy.
My guide to the trigger editor (still a work in progress)
@BigDonRob: Go
Ha Ha Mother Lovin Ha!