Welcome to Open Carnage

A resource for Halo 1 modding and tech, with unique means of rewarding individual content creation and support. Have a wander to see why we're worth the time! EST. 2012

TCK

Regular
  • Content count

    2,929
  • Joined

  • Last visited

  • Raffle Tickets

    0

Reputation Activity

  1. PopeTX28 liked a post in a topic by TCK in Modding in Halo CE is an Absolute Nightmare - Part 1   
    I would flat-out fall over dead if we had an H3 modding kit for H3PC.
  2. ST34MF0X liked a post in a topic by TCK in Scripting Guide   
    This tutorial is available as an rtf for distribution or more convenient reading: http://www.mediafire.com/download/q75239pqlf9iff3/Script+tut.rtf
     
     
    Scripting for Halo 1
    Scripting is necessary for any singleplayer mission you plan to make, from the basic firefight to the full-fledged campaign. Scripting can also be useful for multiplayer maps, and though this tutorial mentions singleplayer missions now and again, the content doesn't cover anything specific to singleplayer missions; so if you're planning to script multiplayer maps, this is still the tutorial for you. Halo uses a scripting language called Blamscript. If you've scripted for a game before, you've likely used a variant of Lua, which is common for modern games to include; in that case, for you the hardest part of learning Blamscript will be getting acquainted with the parenthetical syntax of Lisp, the language of which Blamscript is a variant. If you've never scripted before, that's okay - you're in a good place to start. Download the attached PDF to follow along with commands used in examples, as well as to study on your own in order to see what functions are possible and get an idea as to which you need in order to accomplish your goals.
    Halo Scripting Keywords list.pdf
     
     
    Setting up Your Files
    Every scenario will look to its mirror path in data to find a scripts folder. For instance a scenario under the path "tags\levels\b30\b30.scenario" will search for the folder "data\levels\b30\scripts" and look inside for script files. If this folder does not yet exist for your scenario, create it; inside that, you need to create a new text file (you may optionally have up to four different script files for the same scenario) and save it as a .hsc file (be sure to select "all file types" before saving, or it will save as .hsc.txt). The name does not matter.
     
    Now simply open the .hsc file with your favorite code editor (notepad will suffice if you don't have one). Of course remember not to use any sort of style formatting such as bold, italics, etc. (Though I can't imagine a code editor that allows such things, as notepad surely doesn't.)
     
    Every time you make a change to your script file, you need to save it, then in Sapien go to "File>Compile Scripts" (Ctrl+Shift+S is the key shortcut) and it will attempt to compile your script files. It will print any errors to the window, and also to debug.txt for more permanent reference.
     
    Now you're ready to learn how to write your script.
     
     
    Parenthetical Syntax and Block Form
    It's important to remember that everything is inside a set of parentheses. A set of parentheses is called a list, and the list structure is the base for the entire language of Lisp (Lisp was in fact named for "LISt Processing"). I will use the phrase "open a list" to refer to typing a beginning parenthesis. After opening a list, there are three things that may immediately follow: a declaration, a function, or a static call. This is my own terminology, as Halo does not specify the terminology to be used with Blamscript. Let's go over what I mean by each term respectively.
     
    Note the following: first, that the brackets "[ ]" are not part of any Blamscript code; anything contained in these brackets is simply a description of what should go there. Second, that a space is always seen as the end of one list element and beginning of another, unless it is contained within quotation marks. Last, that the semicolon ";" is used to denote comments in the code and any line starting with a semicolon will not be compiled as code. Use the semicolon to write yourself notes and remind yourself what different parts of your code are there to accomplish.

    Declaration:
    This is what you need to begin any block of code. When you open a list outside of any other lists, you are beginning a type of list which I will refer to as a block and you will make either 2 or 3 declarations to specify how to treat this particular block. Your first declaration will nearly always be either "script" or "global" to define the block type; a script is of course a series of commands to be executed in sequence, and a global is a variable. Your second declaration depends on your first. If you declare a script, you will then declare a script type. If you declare a global, you will declare a value type. We will go over both of these in later sections. As I said, the opening parenthesis before these declarations is the first parenthesis in any block; likewise the closing parenthesis denotes the end of the block. Here are examples of both block types:
    (global [value type] [global name] [value]) (script [script type] [script name]     [functions and arguments] ) The names of globals and scripts can be anything as long as they are unique, meaning they do not represent another function, global, or script. They must also be self-contained, meaning they either need to have no spaces (dashes or underscores are common substitutes) or be contained in quotation marks if they do have spaces. You'll notice that global blocks tend to be much shorter than script blocks. This is because a global only needs to hold one value, while a script may execute hundreds of commands. Also notice that the global is defined above the script. This is a convention that is needed for scripts to be able to "see" globals; typically you should define all your globals at the very top of your .hsc file before any script blocks. In more advanced situations, a global might need to reference another global in order to get a derived value; the latter must be above the former in the document just the same.

    Function:
    Functions will be used at the beginnings of lists contained in sequence in a script block once the block has been thoroughly declared, as demonstrated in above examples. A function is any built-in way that Halo provides for manipulating arguments. An argument is a single element of data contained within a list after a function is called in the list. To demonstrate both of these concepts, we'll use some of the most basic functions; which will be addition, subtraction, multiplication, and division respectively: + - * /
    (script [script type] math_and_more_math     (+ 3 8)     (- 8 2 1)     (* 80 6)     (/ 38 2) ) The arguments in the above examples are the numbers, plain and simple. A list that begins with a function as its first element will always look for arguments as the remaining elements. What is demonstrated by the subtraction list is that the number of accepted arguments may be exact, or may vary, depending on the function. These mathematical functions can accept any amount of arguments with a minimum of two arguments. This script would do nothing in-game, as these numbers do not mean anything relating to the scenario and are not applied to anything in the scenario. The mathematical operations would simply be processed and the results, for lack of use by any other functions, discarded. Let's look at a function that would relate to some concept in the scenario.
    (script [script type] doing_stuff_now     (object_create_anew box)     (object_teleport box spot) ) When executed, this script would cause the object named "box" in the scenario to spawn, destroying it first if it already exists. It would then teleport "box" to the cutscene flag named "spot." The order of these two lists reminds us that scripts are sequential. For instance, consider the following script:
    (script [script type] doing_stuff_wrong     (object_teleport box spot)     (object_create_anew box) ) This script would cause an exception error, assuming "box" did not already exist for some other reason. It would attempt to teleport "box" before creating it. If "box" did already exist, it would teleport "box" and then immediately destroy and respawn it. Functions are executed sequentially at a rate of 30 per second, meaning the delay between consecutive functions is negligible, and so at most you would see perhaps a flicker if the second situation were to occur, or more likely nothing at all.

    Static call:
    A static call is when a script is called to be executed like a function. "Static" is a script type, and we will discuss how to construct and use static scripts later on.
     
     
    Nesting
    Now that you understand parenthetical syntax and block form structuring of lists, we can move on to another crucial structuring technique: nesting. Nesting means to use a list as an element inside another list; indeed, block form is actually nesting, though we don't view it as that since lists are intended to be the elements of a list that has been declared a script.
     
    To better understand why nesting works, think about the order of operations in ordinary math; lists have an order of operations as well, better thought of as an order of evaluation. The order is simply to evaluate the deepest list before moving up to the next level. Consider this line:
    (= (ai_living_count cov1) 6) "=" is a function that, as implied, will return true or false depending on whether the two arguments given are equal. Knowing that two arguments are being compared, we can understand that this list:
    (ai_living_count cov1) is treated as one argument. The one argument that this list reduces to is whatever the living number of actors is in the encounter cov1. So if there are 8 actors alive in this encounter, the line is simply the "=" function comparing 8 and 6, and it would return false. This also shows us what is meant by "deepest." The concept isn't so confusing when you think of it this way: every time a function encounters a new beginning parenthesis, whatever is contained inside the set will be reduced to one value before any more arguments are considered. The depth to which you may need to nest in order to get desired values will vary greatly depending on what you are trying to accomplish. Repeatedly nesting lists to great depth can become tiring, and is one good use for globals. Look how a global may reduce the need to retype nested expressions:
    (global [value type] patrol_alive (ai_living_count cov1)) (script [script type] check_if_equal     (= patrol_alive 6) ) The global "patrol_alive" evaluates to whatever the living count is of cov1, eliminating the need to nest the function "ai_living_count" and its argument inside of the "=" function.
     
    The "if" function is a good example of a function built around nesting. "If" tests its first argument, then executes the second if the first is true. Additionally, it may be given a third optional argument which it will execute if its first is false. Here it is in action:
    (if (= (ai_living_count cov2) 4) (ai_erase cov2)) As you can see, this would not be possible without nesting. The argument being tested is the result of "=" comparing the living count of the encounter "cov2" and the number 4. If they are found to be equal, it becomes true, and "if" executes the next argument which is to delete the encounter. Otherwise, it does nothing. If we gave it a third argument, it would perform the third argument upon finding a false in the first.
     
    Some functions are built not just to support nesting, but to be nested themselves. The function "not" reverses its true or false input. So we can see that "not" wouldn't be very useful unless it's nested within another function as a value, as well as having a test nested within it as a value.
     
     
    Value Types
    There are lots of different value types, many of which you may never need. The most fundamental ones are described here.

    Short:
    A short is a plain number with no decimal places. Examples include 2, 3, -4, or even 393. Most of the values you will use are going to be shorts until you begin writing more advanced script. This value type is limited to 32,768 in either direction from 0.

    Long:
    A long is a number without decimal places which can be far bigger than a short. The range from 0 on a long is 2,147,483,648.

    Real:
    A real is a floating point value. All that means is that real is the value type needed to process decimals, up to 6 decimal places out. 9.000000 and -8.283 are both reals.

    Boolean:
    A boolean is either true or false. This value type is common to practically all coding languages.

    String:
    A string is a set of up to 32 characters contained within quotation marks. "I have all the guns" is a string, and it's important to know that strings are the only way spaces can be included within one element.
     
     
    Script Types
    The type of script determines when it executes. The names are mostly self-explanatory.

    Startup:
    A startup script runs at the start of the map, immediately, starting even before the player's view has loaded.

    Dormant:
    A dormant script does not run until another script (somewhere below it) wakes it, using the "wake" function and the dormant script's name as an argument, as shown below:
    (script dormant spawn_boxes     (object_create_anew box1)     (object_create_anew box2) ) (script startup go_ahead     (ai_place cov)     (wake spawn_boxes) ) The above script "go_ahead" will place the encounter "cov" and then wake the script "spawn_boxes" which will spawn two objects.
     
    Startup and dormant scripts only execute once, waking them again will not do anything.

    Continuous:
    Continuous scripts will cycle constantly, starting at the top again when they reach the bottom. These are the only scripts that can repeat themselves.

    Static:
    Static scripts, as mentioned earlier, are similar to functions. They can be executed any number of times, but do not execute themselves. They are called anywhere a function would be called. They are also the only script type that should be declared with three elements. In addition to the normal first two, these scripts should have a "return type" declared, which just means the value type returned by the script. The reason for this is that static scripts can be used as a different sort of global (which will be covered in my "Advanced Scripting" tutorial). The important thing to know is that it's good form to use a return type even if the static script is for doing things rather than finding a value; the return type "void" means there is none. Consider the following:
    (script static void place_vehicles     (object_create_anew hog1)     (object_create_anew hog2) ) (script startup map_setup     (object_create_anew box)     (place_vehicles) ) The script "map_setup" places "box" as its first function. Then its next function is the script "place_vehicles" meaning it executes that script. In this way, one use of static scripts is that they can take processes that are tedious to retype, but need to be done several times in different places in the script, and make it easy to reference all of it at once.
     
     
    Scripting Practically
    Knowing this new information, it's easy to see how dynamically you can make your scripts interact. Look at this basic example:
    (script dormant remove     (object_destroy hog1)     (object_destroy hog2) ) (script startup go_ahead     (object_teleport hog1 spot1)     (if (volume_test_object area1 hog2) (wake remove)) ) In the above example, the dormant script "remove" will not be woken unless "hog2" is found to be inside the trigger volume "area1." This means you can conditionally control entire sections of the script according to what's happening in the game. The most fun missions aren't scripted to be entirely straightforward.
     
    Keep in mind all of the different ways you can test for conditions, and don't be afraid to write large portions of script that are optional. The more ways a map can react to the player, the better. Anticipate everything that the player might do.
     
     
    Conclusion
    This concludes my basic scripting tutorial. I believe a beginner will have everything they need to get started by now. Once you've spent enough time practicing the concepts here, I hope you'll move on to my next tutorials for singleplayer maps: "Perfecting Your Encounters" which will tell you everything you need to know about making groups of AI work together; and "Advanced Scripting" which is full of anything I know about scripts that can be quite exciting but wasn't relevant to get you started.
  3. ST34MF0X liked a post in a topic by TCK in Scripting Guide   
    This tutorial is available as an rtf for distribution or more convenient reading: http://www.mediafire.com/download/q75239pqlf9iff3/Script+tut.rtf
     
     
    Scripting for Halo 1
    Scripting is necessary for any singleplayer mission you plan to make, from the basic firefight to the full-fledged campaign. Scripting can also be useful for multiplayer maps, and though this tutorial mentions singleplayer missions now and again, the content doesn't cover anything specific to singleplayer missions; so if you're planning to script multiplayer maps, this is still the tutorial for you. Halo uses a scripting language called Blamscript. If you've scripted for a game before, you've likely used a variant of Lua, which is common for modern games to include; in that case, for you the hardest part of learning Blamscript will be getting acquainted with the parenthetical syntax of Lisp, the language of which Blamscript is a variant. If you've never scripted before, that's okay - you're in a good place to start. Download the attached PDF to follow along with commands used in examples, as well as to study on your own in order to see what functions are possible and get an idea as to which you need in order to accomplish your goals.
    Halo Scripting Keywords list.pdf
     
     
    Setting up Your Files
    Every scenario will look to its mirror path in data to find a scripts folder. For instance a scenario under the path "tags\levels\b30\b30.scenario" will search for the folder "data\levels\b30\scripts" and look inside for script files. If this folder does not yet exist for your scenario, create it; inside that, you need to create a new text file (you may optionally have up to four different script files for the same scenario) and save it as a .hsc file (be sure to select "all file types" before saving, or it will save as .hsc.txt). The name does not matter.
     
    Now simply open the .hsc file with your favorite code editor (notepad will suffice if you don't have one). Of course remember not to use any sort of style formatting such as bold, italics, etc. (Though I can't imagine a code editor that allows such things, as notepad surely doesn't.)
     
    Every time you make a change to your script file, you need to save it, then in Sapien go to "File>Compile Scripts" (Ctrl+Shift+S is the key shortcut) and it will attempt to compile your script files. It will print any errors to the window, and also to debug.txt for more permanent reference.
     
    Now you're ready to learn how to write your script.
     
     
    Parenthetical Syntax and Block Form
    It's important to remember that everything is inside a set of parentheses. A set of parentheses is called a list, and the list structure is the base for the entire language of Lisp (Lisp was in fact named for "LISt Processing"). I will use the phrase "open a list" to refer to typing a beginning parenthesis. After opening a list, there are three things that may immediately follow: a declaration, a function, or a static call. This is my own terminology, as Halo does not specify the terminology to be used with Blamscript. Let's go over what I mean by each term respectively.
     
    Note the following: first, that the brackets "[ ]" are not part of any Blamscript code; anything contained in these brackets is simply a description of what should go there. Second, that a space is always seen as the end of one list element and beginning of another, unless it is contained within quotation marks. Last, that the semicolon ";" is used to denote comments in the code and any line starting with a semicolon will not be compiled as code. Use the semicolon to write yourself notes and remind yourself what different parts of your code are there to accomplish.

    Declaration:
    This is what you need to begin any block of code. When you open a list outside of any other lists, you are beginning a type of list which I will refer to as a block and you will make either 2 or 3 declarations to specify how to treat this particular block. Your first declaration will nearly always be either "script" or "global" to define the block type; a script is of course a series of commands to be executed in sequence, and a global is a variable. Your second declaration depends on your first. If you declare a script, you will then declare a script type. If you declare a global, you will declare a value type. We will go over both of these in later sections. As I said, the opening parenthesis before these declarations is the first parenthesis in any block; likewise the closing parenthesis denotes the end of the block. Here are examples of both block types:
    (global [value type] [global name] [value]) (script [script type] [script name]     [functions and arguments] ) The names of globals and scripts can be anything as long as they are unique, meaning they do not represent another function, global, or script. They must also be self-contained, meaning they either need to have no spaces (dashes or underscores are common substitutes) or be contained in quotation marks if they do have spaces. You'll notice that global blocks tend to be much shorter than script blocks. This is because a global only needs to hold one value, while a script may execute hundreds of commands. Also notice that the global is defined above the script. This is a convention that is needed for scripts to be able to "see" globals; typically you should define all your globals at the very top of your .hsc file before any script blocks. In more advanced situations, a global might need to reference another global in order to get a derived value; the latter must be above the former in the document just the same.

    Function:
    Functions will be used at the beginnings of lists contained in sequence in a script block once the block has been thoroughly declared, as demonstrated in above examples. A function is any built-in way that Halo provides for manipulating arguments. An argument is a single element of data contained within a list after a function is called in the list. To demonstrate both of these concepts, we'll use some of the most basic functions; which will be addition, subtraction, multiplication, and division respectively: + - * /
    (script [script type] math_and_more_math     (+ 3 8)     (- 8 2 1)     (* 80 6)     (/ 38 2) ) The arguments in the above examples are the numbers, plain and simple. A list that begins with a function as its first element will always look for arguments as the remaining elements. What is demonstrated by the subtraction list is that the number of accepted arguments may be exact, or may vary, depending on the function. These mathematical functions can accept any amount of arguments with a minimum of two arguments. This script would do nothing in-game, as these numbers do not mean anything relating to the scenario and are not applied to anything in the scenario. The mathematical operations would simply be processed and the results, for lack of use by any other functions, discarded. Let's look at a function that would relate to some concept in the scenario.
    (script [script type] doing_stuff_now     (object_create_anew box)     (object_teleport box spot) ) When executed, this script would cause the object named "box" in the scenario to spawn, destroying it first if it already exists. It would then teleport "box" to the cutscene flag named "spot." The order of these two lists reminds us that scripts are sequential. For instance, consider the following script:
    (script [script type] doing_stuff_wrong     (object_teleport box spot)     (object_create_anew box) ) This script would cause an exception error, assuming "box" did not already exist for some other reason. It would attempt to teleport "box" before creating it. If "box" did already exist, it would teleport "box" and then immediately destroy and respawn it. Functions are executed sequentially at a rate of 30 per second, meaning the delay between consecutive functions is negligible, and so at most you would see perhaps a flicker if the second situation were to occur, or more likely nothing at all.

    Static call:
    A static call is when a script is called to be executed like a function. "Static" is a script type, and we will discuss how to construct and use static scripts later on.
     
     
    Nesting
    Now that you understand parenthetical syntax and block form structuring of lists, we can move on to another crucial structuring technique: nesting. Nesting means to use a list as an element inside another list; indeed, block form is actually nesting, though we don't view it as that since lists are intended to be the elements of a list that has been declared a script.
     
    To better understand why nesting works, think about the order of operations in ordinary math; lists have an order of operations as well, better thought of as an order of evaluation. The order is simply to evaluate the deepest list before moving up to the next level. Consider this line:
    (= (ai_living_count cov1) 6) "=" is a function that, as implied, will return true or false depending on whether the two arguments given are equal. Knowing that two arguments are being compared, we can understand that this list:
    (ai_living_count cov1) is treated as one argument. The one argument that this list reduces to is whatever the living number of actors is in the encounter cov1. So if there are 8 actors alive in this encounter, the line is simply the "=" function comparing 8 and 6, and it would return false. This also shows us what is meant by "deepest." The concept isn't so confusing when you think of it this way: every time a function encounters a new beginning parenthesis, whatever is contained inside the set will be reduced to one value before any more arguments are considered. The depth to which you may need to nest in order to get desired values will vary greatly depending on what you are trying to accomplish. Repeatedly nesting lists to great depth can become tiring, and is one good use for globals. Look how a global may reduce the need to retype nested expressions:
    (global [value type] patrol_alive (ai_living_count cov1)) (script [script type] check_if_equal     (= patrol_alive 6) ) The global "patrol_alive" evaluates to whatever the living count is of cov1, eliminating the need to nest the function "ai_living_count" and its argument inside of the "=" function.
     
    The "if" function is a good example of a function built around nesting. "If" tests its first argument, then executes the second if the first is true. Additionally, it may be given a third optional argument which it will execute if its first is false. Here it is in action:
    (if (= (ai_living_count cov2) 4) (ai_erase cov2)) As you can see, this would not be possible without nesting. The argument being tested is the result of "=" comparing the living count of the encounter "cov2" and the number 4. If they are found to be equal, it becomes true, and "if" executes the next argument which is to delete the encounter. Otherwise, it does nothing. If we gave it a third argument, it would perform the third argument upon finding a false in the first.
     
    Some functions are built not just to support nesting, but to be nested themselves. The function "not" reverses its true or false input. So we can see that "not" wouldn't be very useful unless it's nested within another function as a value, as well as having a test nested within it as a value.
     
     
    Value Types
    There are lots of different value types, many of which you may never need. The most fundamental ones are described here.

    Short:
    A short is a plain number with no decimal places. Examples include 2, 3, -4, or even 393. Most of the values you will use are going to be shorts until you begin writing more advanced script. This value type is limited to 32,768 in either direction from 0.

    Long:
    A long is a number without decimal places which can be far bigger than a short. The range from 0 on a long is 2,147,483,648.

    Real:
    A real is a floating point value. All that means is that real is the value type needed to process decimals, up to 6 decimal places out. 9.000000 and -8.283 are both reals.

    Boolean:
    A boolean is either true or false. This value type is common to practically all coding languages.

    String:
    A string is a set of up to 32 characters contained within quotation marks. "I have all the guns" is a string, and it's important to know that strings are the only way spaces can be included within one element.
     
     
    Script Types
    The type of script determines when it executes. The names are mostly self-explanatory.

    Startup:
    A startup script runs at the start of the map, immediately, starting even before the player's view has loaded.

    Dormant:
    A dormant script does not run until another script (somewhere below it) wakes it, using the "wake" function and the dormant script's name as an argument, as shown below:
    (script dormant spawn_boxes     (object_create_anew box1)     (object_create_anew box2) ) (script startup go_ahead     (ai_place cov)     (wake spawn_boxes) ) The above script "go_ahead" will place the encounter "cov" and then wake the script "spawn_boxes" which will spawn two objects.
     
    Startup and dormant scripts only execute once, waking them again will not do anything.

    Continuous:
    Continuous scripts will cycle constantly, starting at the top again when they reach the bottom. These are the only scripts that can repeat themselves.

    Static:
    Static scripts, as mentioned earlier, are similar to functions. They can be executed any number of times, but do not execute themselves. They are called anywhere a function would be called. They are also the only script type that should be declared with three elements. In addition to the normal first two, these scripts should have a "return type" declared, which just means the value type returned by the script. The reason for this is that static scripts can be used as a different sort of global (which will be covered in my "Advanced Scripting" tutorial). The important thing to know is that it's good form to use a return type even if the static script is for doing things rather than finding a value; the return type "void" means there is none. Consider the following:
    (script static void place_vehicles     (object_create_anew hog1)     (object_create_anew hog2) ) (script startup map_setup     (object_create_anew box)     (place_vehicles) ) The script "map_setup" places "box" as its first function. Then its next function is the script "place_vehicles" meaning it executes that script. In this way, one use of static scripts is that they can take processes that are tedious to retype, but need to be done several times in different places in the script, and make it easy to reference all of it at once.
     
     
    Scripting Practically
    Knowing this new information, it's easy to see how dynamically you can make your scripts interact. Look at this basic example:
    (script dormant remove     (object_destroy hog1)     (object_destroy hog2) ) (script startup go_ahead     (object_teleport hog1 spot1)     (if (volume_test_object area1 hog2) (wake remove)) ) In the above example, the dormant script "remove" will not be woken unless "hog2" is found to be inside the trigger volume "area1." This means you can conditionally control entire sections of the script according to what's happening in the game. The most fun missions aren't scripted to be entirely straightforward.
     
    Keep in mind all of the different ways you can test for conditions, and don't be afraid to write large portions of script that are optional. The more ways a map can react to the player, the better. Anticipate everything that the player might do.
     
     
    Conclusion
    This concludes my basic scripting tutorial. I believe a beginner will have everything they need to get started by now. Once you've spent enough time practicing the concepts here, I hope you'll move on to my next tutorials for singleplayer maps: "Perfecting Your Encounters" which will tell you everything you need to know about making groups of AI work together; and "Advanced Scripting" which is full of anything I know about scripts that can be quite exciting but wasn't relevant to get you started.
  4. TCK liked a post in a topic by Kru in "Everything's fucking shit" Thread   
    Been trying for a few days to teach myself how to weld sheet metal and fuck me it's hard. Super good at making swiss cheese though.
  5. ST34MF0X liked a post in a topic by TCK in Scripting Guide   
    This tutorial is available as an rtf for distribution or more convenient reading: http://www.mediafire.com/download/q75239pqlf9iff3/Script+tut.rtf
     
     
    Scripting for Halo 1
    Scripting is necessary for any singleplayer mission you plan to make, from the basic firefight to the full-fledged campaign. Scripting can also be useful for multiplayer maps, and though this tutorial mentions singleplayer missions now and again, the content doesn't cover anything specific to singleplayer missions; so if you're planning to script multiplayer maps, this is still the tutorial for you. Halo uses a scripting language called Blamscript. If you've scripted for a game before, you've likely used a variant of Lua, which is common for modern games to include; in that case, for you the hardest part of learning Blamscript will be getting acquainted with the parenthetical syntax of Lisp, the language of which Blamscript is a variant. If you've never scripted before, that's okay - you're in a good place to start. Download the attached PDF to follow along with commands used in examples, as well as to study on your own in order to see what functions are possible and get an idea as to which you need in order to accomplish your goals.
    Halo Scripting Keywords list.pdf
     
     
    Setting up Your Files
    Every scenario will look to its mirror path in data to find a scripts folder. For instance a scenario under the path "tags\levels\b30\b30.scenario" will search for the folder "data\levels\b30\scripts" and look inside for script files. If this folder does not yet exist for your scenario, create it; inside that, you need to create a new text file (you may optionally have up to four different script files for the same scenario) and save it as a .hsc file (be sure to select "all file types" before saving, or it will save as .hsc.txt). The name does not matter.
     
    Now simply open the .hsc file with your favorite code editor (notepad will suffice if you don't have one). Of course remember not to use any sort of style formatting such as bold, italics, etc. (Though I can't imagine a code editor that allows such things, as notepad surely doesn't.)
     
    Every time you make a change to your script file, you need to save it, then in Sapien go to "File>Compile Scripts" (Ctrl+Shift+S is the key shortcut) and it will attempt to compile your script files. It will print any errors to the window, and also to debug.txt for more permanent reference.
     
    Now you're ready to learn how to write your script.
     
     
    Parenthetical Syntax and Block Form
    It's important to remember that everything is inside a set of parentheses. A set of parentheses is called a list, and the list structure is the base for the entire language of Lisp (Lisp was in fact named for "LISt Processing"). I will use the phrase "open a list" to refer to typing a beginning parenthesis. After opening a list, there are three things that may immediately follow: a declaration, a function, or a static call. This is my own terminology, as Halo does not specify the terminology to be used with Blamscript. Let's go over what I mean by each term respectively.
     
    Note the following: first, that the brackets "[ ]" are not part of any Blamscript code; anything contained in these brackets is simply a description of what should go there. Second, that a space is always seen as the end of one list element and beginning of another, unless it is contained within quotation marks. Last, that the semicolon ";" is used to denote comments in the code and any line starting with a semicolon will not be compiled as code. Use the semicolon to write yourself notes and remind yourself what different parts of your code are there to accomplish.

    Declaration:
    This is what you need to begin any block of code. When you open a list outside of any other lists, you are beginning a type of list which I will refer to as a block and you will make either 2 or 3 declarations to specify how to treat this particular block. Your first declaration will nearly always be either "script" or "global" to define the block type; a script is of course a series of commands to be executed in sequence, and a global is a variable. Your second declaration depends on your first. If you declare a script, you will then declare a script type. If you declare a global, you will declare a value type. We will go over both of these in later sections. As I said, the opening parenthesis before these declarations is the first parenthesis in any block; likewise the closing parenthesis denotes the end of the block. Here are examples of both block types:
    (global [value type] [global name] [value]) (script [script type] [script name]     [functions and arguments] ) The names of globals and scripts can be anything as long as they are unique, meaning they do not represent another function, global, or script. They must also be self-contained, meaning they either need to have no spaces (dashes or underscores are common substitutes) or be contained in quotation marks if they do have spaces. You'll notice that global blocks tend to be much shorter than script blocks. This is because a global only needs to hold one value, while a script may execute hundreds of commands. Also notice that the global is defined above the script. This is a convention that is needed for scripts to be able to "see" globals; typically you should define all your globals at the very top of your .hsc file before any script blocks. In more advanced situations, a global might need to reference another global in order to get a derived value; the latter must be above the former in the document just the same.

    Function:
    Functions will be used at the beginnings of lists contained in sequence in a script block once the block has been thoroughly declared, as demonstrated in above examples. A function is any built-in way that Halo provides for manipulating arguments. An argument is a single element of data contained within a list after a function is called in the list. To demonstrate both of these concepts, we'll use some of the most basic functions; which will be addition, subtraction, multiplication, and division respectively: + - * /
    (script [script type] math_and_more_math     (+ 3 8)     (- 8 2 1)     (* 80 6)     (/ 38 2) ) The arguments in the above examples are the numbers, plain and simple. A list that begins with a function as its first element will always look for arguments as the remaining elements. What is demonstrated by the subtraction list is that the number of accepted arguments may be exact, or may vary, depending on the function. These mathematical functions can accept any amount of arguments with a minimum of two arguments. This script would do nothing in-game, as these numbers do not mean anything relating to the scenario and are not applied to anything in the scenario. The mathematical operations would simply be processed and the results, for lack of use by any other functions, discarded. Let's look at a function that would relate to some concept in the scenario.
    (script [script type] doing_stuff_now     (object_create_anew box)     (object_teleport box spot) ) When executed, this script would cause the object named "box" in the scenario to spawn, destroying it first if it already exists. It would then teleport "box" to the cutscene flag named "spot." The order of these two lists reminds us that scripts are sequential. For instance, consider the following script:
    (script [script type] doing_stuff_wrong     (object_teleport box spot)     (object_create_anew box) ) This script would cause an exception error, assuming "box" did not already exist for some other reason. It would attempt to teleport "box" before creating it. If "box" did already exist, it would teleport "box" and then immediately destroy and respawn it. Functions are executed sequentially at a rate of 30 per second, meaning the delay between consecutive functions is negligible, and so at most you would see perhaps a flicker if the second situation were to occur, or more likely nothing at all.

    Static call:
    A static call is when a script is called to be executed like a function. "Static" is a script type, and we will discuss how to construct and use static scripts later on.
     
     
    Nesting
    Now that you understand parenthetical syntax and block form structuring of lists, we can move on to another crucial structuring technique: nesting. Nesting means to use a list as an element inside another list; indeed, block form is actually nesting, though we don't view it as that since lists are intended to be the elements of a list that has been declared a script.
     
    To better understand why nesting works, think about the order of operations in ordinary math; lists have an order of operations as well, better thought of as an order of evaluation. The order is simply to evaluate the deepest list before moving up to the next level. Consider this line:
    (= (ai_living_count cov1) 6) "=" is a function that, as implied, will return true or false depending on whether the two arguments given are equal. Knowing that two arguments are being compared, we can understand that this list:
    (ai_living_count cov1) is treated as one argument. The one argument that this list reduces to is whatever the living number of actors is in the encounter cov1. So if there are 8 actors alive in this encounter, the line is simply the "=" function comparing 8 and 6, and it would return false. This also shows us what is meant by "deepest." The concept isn't so confusing when you think of it this way: every time a function encounters a new beginning parenthesis, whatever is contained inside the set will be reduced to one value before any more arguments are considered. The depth to which you may need to nest in order to get desired values will vary greatly depending on what you are trying to accomplish. Repeatedly nesting lists to great depth can become tiring, and is one good use for globals. Look how a global may reduce the need to retype nested expressions:
    (global [value type] patrol_alive (ai_living_count cov1)) (script [script type] check_if_equal     (= patrol_alive 6) ) The global "patrol_alive" evaluates to whatever the living count is of cov1, eliminating the need to nest the function "ai_living_count" and its argument inside of the "=" function.
     
    The "if" function is a good example of a function built around nesting. "If" tests its first argument, then executes the second if the first is true. Additionally, it may be given a third optional argument which it will execute if its first is false. Here it is in action:
    (if (= (ai_living_count cov2) 4) (ai_erase cov2)) As you can see, this would not be possible without nesting. The argument being tested is the result of "=" comparing the living count of the encounter "cov2" and the number 4. If they are found to be equal, it becomes true, and "if" executes the next argument which is to delete the encounter. Otherwise, it does nothing. If we gave it a third argument, it would perform the third argument upon finding a false in the first.
     
    Some functions are built not just to support nesting, but to be nested themselves. The function "not" reverses its true or false input. So we can see that "not" wouldn't be very useful unless it's nested within another function as a value, as well as having a test nested within it as a value.
     
     
    Value Types
    There are lots of different value types, many of which you may never need. The most fundamental ones are described here.

    Short:
    A short is a plain number with no decimal places. Examples include 2, 3, -4, or even 393. Most of the values you will use are going to be shorts until you begin writing more advanced script. This value type is limited to 32,768 in either direction from 0.

    Long:
    A long is a number without decimal places which can be far bigger than a short. The range from 0 on a long is 2,147,483,648.

    Real:
    A real is a floating point value. All that means is that real is the value type needed to process decimals, up to 6 decimal places out. 9.000000 and -8.283 are both reals.

    Boolean:
    A boolean is either true or false. This value type is common to practically all coding languages.

    String:
    A string is a set of up to 32 characters contained within quotation marks. "I have all the guns" is a string, and it's important to know that strings are the only way spaces can be included within one element.
     
     
    Script Types
    The type of script determines when it executes. The names are mostly self-explanatory.

    Startup:
    A startup script runs at the start of the map, immediately, starting even before the player's view has loaded.

    Dormant:
    A dormant script does not run until another script (somewhere below it) wakes it, using the "wake" function and the dormant script's name as an argument, as shown below:
    (script dormant spawn_boxes     (object_create_anew box1)     (object_create_anew box2) ) (script startup go_ahead     (ai_place cov)     (wake spawn_boxes) ) The above script "go_ahead" will place the encounter "cov" and then wake the script "spawn_boxes" which will spawn two objects.
     
    Startup and dormant scripts only execute once, waking them again will not do anything.

    Continuous:
    Continuous scripts will cycle constantly, starting at the top again when they reach the bottom. These are the only scripts that can repeat themselves.

    Static:
    Static scripts, as mentioned earlier, are similar to functions. They can be executed any number of times, but do not execute themselves. They are called anywhere a function would be called. They are also the only script type that should be declared with three elements. In addition to the normal first two, these scripts should have a "return type" declared, which just means the value type returned by the script. The reason for this is that static scripts can be used as a different sort of global (which will be covered in my "Advanced Scripting" tutorial). The important thing to know is that it's good form to use a return type even if the static script is for doing things rather than finding a value; the return type "void" means there is none. Consider the following:
    (script static void place_vehicles     (object_create_anew hog1)     (object_create_anew hog2) ) (script startup map_setup     (object_create_anew box)     (place_vehicles) ) The script "map_setup" places "box" as its first function. Then its next function is the script "place_vehicles" meaning it executes that script. In this way, one use of static scripts is that they can take processes that are tedious to retype, but need to be done several times in different places in the script, and make it easy to reference all of it at once.
     
     
    Scripting Practically
    Knowing this new information, it's easy to see how dynamically you can make your scripts interact. Look at this basic example:
    (script dormant remove     (object_destroy hog1)     (object_destroy hog2) ) (script startup go_ahead     (object_teleport hog1 spot1)     (if (volume_test_object area1 hog2) (wake remove)) ) In the above example, the dormant script "remove" will not be woken unless "hog2" is found to be inside the trigger volume "area1." This means you can conditionally control entire sections of the script according to what's happening in the game. The most fun missions aren't scripted to be entirely straightforward.
     
    Keep in mind all of the different ways you can test for conditions, and don't be afraid to write large portions of script that are optional. The more ways a map can react to the player, the better. Anticipate everything that the player might do.
     
     
    Conclusion
    This concludes my basic scripting tutorial. I believe a beginner will have everything they need to get started by now. Once you've spent enough time practicing the concepts here, I hope you'll move on to my next tutorials for singleplayer maps: "Perfecting Your Encounters" which will tell you everything you need to know about making groups of AI work together; and "Advanced Scripting" which is full of anything I know about scripts that can be quite exciting but wasn't relevant to get you started.
  6. Tucker933 liked a post in a topic by TCK in "AWW YEAH" Thread   
    Congrats bruh.
     
    On this same note, I keep hearing from the GM of our store how he plans to make me GM after he leaves. Just a plan as long as it isn't happening but we expect it to happen.
  7. TCK liked a post in a topic by Tucker933 in "AWW YEAH" Thread   
    I haz job now.
  8. Pra3tor1an liked a post in a topic by TCK in Facebook or Twitter?   
    Devil's advocate: don't install either app on your phone because they both want all your info; but that's just me being an old stick in the mud.
  9. Daywu liked a post in a topic by TCK in Currently Playing   
    Bruh I'd play with you but we work opposite shifts usually. I'm off at like 11 most nights, 1 AM on Friday nights (Saturday mornings, whatever). What do you work Wednesdays?
  10. TCK liked a post in a topic by Tucker933 in How far can we go?   
    I recently came across this channel, with a lot of great videos for interesting topics ...but this video in particular stood out to me a bit, for how the perception of the Universe will differ in the distant future, before heat death is even on the horizon.
     
     
    Check out some of their stuff, or just this video, or whatever.
  11. TCK liked a post in a topic by WaeV in Google fires engineer who "crossed the line" with diversity memo   
    I think it's a distraction.
     
    The American left used to focus on both workers' issues and social issues. The 8 hour workday, the weekend, womens' suffrage, OSHA, and so on are all left-ish causes.
     
    But at some point along the 20th century, the left was replaced by Neoliberalism. It tried to find a "third way" between left and right. Well it ended up on the side of big business, anti-welfare, deregulation, privatisation, austerity and corporate trade. Why do you think so many banks donated to Hillary? You've got big oil on the right, big pharma on the left. It's all pretty much the same as economic positions are concerned.
     
    So, gutted of its populist pro-worker platform, the "left" doesn't have anything to fall back on except social arguments.
     
    Consider the following issues:
    Growing power of the "police state" (local and national) Stagnant wages and slow job growth Integrity of our voting system Now let's filter them through identity politics:
    Growing power of the "police state" (local and national) Black Lives Matter vs Blue Lives Matter Stagnant wages and slow job growth Female Wage Gap vs Reverse Sexism Integrity of our voting system "Democrats use illegal immigrants to vote" vs "Republics use voter suppression against blacks" It takes issues we ought to be agreeing on, and turns them into an identity war.
  12. TCK liked a post in a topic by WaeV in Google fires engineer who "crossed the line" with diversity memo   
    Indeed, the original essay did exactly this.
     
    He acknowledged there are other explanations for the gender gap in tech. His biggest sin was only citing sources in favor of his opinion, and implying those were powerful enough effects to explain the whole gap.
     
    It's very easy to invoke authority-by-science in an argument. It's a lot harder to actually practice good science.
  13. swamp liked a post in a topic by TCK in Google fires engineer who "crossed the line" with diversity memo   
    I don't get why social politics are so popular nowadays. I've gotten to the point where I know what I believe, I make judgments and presumptions based on it, and I alter my beliefs accordingly based on my observations compared to my initial judgment or presumption. That's what natural selection is all about. Presumption allows me to try to predict the future and when it fails, I try to presume better next time. It's important to note the difference between assumption (a baseless prejudgment) and presumption (a prejudgment based on previous experience).
     
    I don't let details like causation come into play for me anymore; correlation is enough. Being a woman may or may not be the cause of many differences I observe in women, but regardless of cause the correlation exists. A great example is in selecting a new shift manager at work, which is partly my job at this point: it's not that I view women as inherently incapable of management, it's that each woman or girl in my workplace (except one) has individually and independently invalidated themselves in my eyes for the position for similar reasons as mentioned by Solaris. They seem to be more interested in drama and gossip than in making the workplace efficient. That is not to say it is limited to only the women there, one of my closest male friends struggles with "talking shit" about people who make mistakes that make his job harder (a bit more work-related than the gossip/drama of which the girls are guilty but gossip/drama nonetheless); but men, on average in the workplace, seem to be more work-minded.
     
    My point in that paragraph being, do I care what causes this to happen? All I care about is the correlation that allows me to say to myself, "this seems to be the case with a lot of women," and that in turn allows me to formulate a way to deal with it ahead of time, if I see it approaching in the future.
     
    I was speaking to a girl who wanted to be shift manager and it got the point where I decided it would be professional of me to be flat with her - I told her what stopped me from promoting her, and that the only way she would be reconsidered is if she cut the gossip and showed that she could maintain professionalism for an extended period of time. No mention of her being female and that's the way it should be; actions are the judges of results and if there end up being no female managers as a result of correlation, it will simply be the result of that correlation.
  14. Tucker933 liked a post in a topic by TCK in There's a Simple New Way to Find Out if Hackers Already Have Your Password   
    I already heard my password was secure when this site said to enter my passwords to find out if anyone has found them out.
  15. TCK liked a post in a topic by WaeV in Google fires engineer who "crossed the line" with diversity memo   
    You can read the original document here: https://assets.documentcloud.org/documents/3914586/Googles-Ideological-Echo-Chamber.pdf
     
    I really like what he has to say about the dangers of echo chambers. It's a shame he had to bundle it with crappy arguments about gender.
     
    This about sums up my opinion:
     
    "Biology is partly responsible for differences between men and women": no arguments there.
    "These differences may explain why we don’t see equal representation of women in tech and leadership": I'm sure it's a factor but is unlikely to be the only/ultimate cause.
     
    People seem to forget that the number of women in programming has been decreasing over time -- we are actually losing ground:
     

  16. TCK liked a post in a topic by Solaris in Google fires engineer who "crossed the line" with diversity memo   
    The Census of 2013 did a study on the ratio of males versus females in the field of Nursing.
     
     
    The same questions can be asked as well. Why aren't males bending over backwards to get into nursing? They're simply not interested or invested in that field.
     
    This is my personal experience only (and personal biases), but you would think after many men confirming the same things or similar, it would be somewhat true to a degree (considering the Census is only as accurate as the people who report to the Census).
     
    Women like having jobs where they feel like their higher purpose is taking care of people and clients, do better at organization tasks and multi-tasking. Women are more social than men, flat out. It makes them feel good. They like socializing with coworkers more often than their male counter-parts socialize with each other (at least in STEM, engineering and technology specifically).
     
    It is very distracting for me, as a male, when I have a female counter-part talking my ear off about home or social drama in the workplace when I'm focused on a particular assignment. That's where I believe a lot of the divide is, is that males are a single track mind and keep to themselves, where women tend to be a jack of all trades, a master of none. This gives males the view that they are not responsible or knowledgeable enough to perform the duties that their male counter-parts are assigned.
     
    I tried, so hard, with one black female coworker to train her on a lot of the duties that I do as a SysAdmin, because she expressed to me multiple times she felt like the odd one out with the majority white male peers. I tried, time and time again, to stay on track with the training, but was more often then not taken off of track because home drama was brought into the mix. She couldn't retain any of the information I had given her, she would derail the topics at hand with nothing really important to what was going on and didn't seem all that invested in what I was trying to show her. I understand everyone has their problems, but there is a time and place for it. Women bring this to work with them and everyone suffers from it. It's toxic, makes the workflow inefficient and they don't seem to have an interest in the work or material like my male counter-parts do.
     
    It's easy to say "not all women," but statistically and from the ratios of personal experience, the majority is overwhelmingly this issue in specific. This may be an entirely different situation in another country, another industry, where women's culture is different and in rare cases where women have matured and become dedicated to the field they work in, but in the United States and working in Technology and Engineering, this is a common social problem in the work place. Women are not focused on their profession, but excel in areas where organization, socializing and multi-tasking is part of their daily duties.
     
    Now, this isn't me saying the previous statement is all women are good for in STEM. It's what I see as a trend in the field as of current. They can do some self inflection and talk amongst their peers wanting to get into STEM that there are specific requirements and expectations to make work flow efficient and find an area of expertise, but as of right now it's impossible to vouch for women in Technology and Engineering if women don't even want to be invested in it like their male counter-parts. Medical seems to be a different world with different expectations. You have to have matured to get into higher areas of that industry and show you are dedicated to the work you do. It is very competitive. In Technology and Engineering, not so much. The same culture and mindset needs to be brought into Technology and Engineering. The HR quotas for hiring women out of pity rather than merit for this industry is really hurting it, it's hurting women's image from bad eggs and it needs to get worse before it gets better. Women need to mature in this field, keep up with their male counter-parts to create a competitive environment and start setting an example for future women of this field.
     
    Edit: On a side note, don't get me wrong, there are bad egg males that absolutely hate the idea of women being in this field. Some shitty company cultures are also to blame. I have a coworker just like this. He's an asshole, downplays women whenever he can and luckily he's retiring soon (honestly should be fired for some of the comments he makes), but some companies refuse to do anything about this shitty behavior. Even if it was male versus male, it's looked at as "suck it up and grow some hairs on your chest" in this industry.
     
    tl;dr version: Lack of women in STEM is also women's cultural/social problems. Males cannot be 100% the blame of this.
     
    Also an interesting Census study: Ratio of men/women working in STEM regardless of the degree they obtained at a University or College.
  17. TCK liked a post in a topic by DiSiAC in "Everything's fucking shit" Thread   
  18. TCK liked a post in a topic by Iggy in The 13th Doctor Who is.........   
    Hey wait a minute that's why I watch it !!!!
  19. TCK liked a post in a topic by Calypso in Vegan cafe slammed for letting nude kids 'defecate on the floor'   
    You know, I'm tired of the diatribe against vegans. I'm vegan and frankly I'm kind of offended the attitudes you all purvey. Just because your stomach is a graveyard doesn't mean mine has to be.
    There's a picture that I once saw that finally made me make the jump from carni-whore to a state where I can be happy with my moral consumption. I'd like you all to see it, in the hopes that it will convince you too. It's horrifying, graphic; you will be shocked, but in the off chance one of you changes your ways I know my job will have been done.
    NSFW
     
  20. TCK liked a post in a topic by Pra3tor1an in "AWW YEAH" Thread   
    Me and wife are expecting our second child, I have informally called it the MKII for now.
  21. Pra3tor1an liked a post in a topic by TCK in Vegan cafe slammed for letting nude kids 'defecate on the floor'   
    I don't understand. Who walks into an establishment labeled "vegan" and doesn't expect at least one or two fucking insane people inside?
  22. Pra3tor1an liked a post in a topic by TCK in Vegan cafe slammed for letting nude kids 'defecate on the floor'   
    I don't understand. Who walks into an establishment labeled "vegan" and doesn't expect at least one or two fucking insane people inside?
  23. Pra3tor1an liked a post in a topic by TCK in Vegan cafe slammed for letting nude kids 'defecate on the floor'   
    I don't understand. Who walks into an establishment labeled "vegan" and doesn't expect at least one or two fucking insane people inside?
  24. Pra3tor1an liked a post in a topic by TCK in Vegan cafe slammed for letting nude kids 'defecate on the floor'   
    I don't understand. Who walks into an establishment labeled "vegan" and doesn't expect at least one or two fucking insane people inside?
  25. TCK liked a post in a topic by Sceny in "AWW YEAH" Thread   
    I'm honoured that you've decided to name your next child after me.