================================================================================ == Scripting for the Rooms == ================================================================================ This is another brilliantly written tutorial for scripting events to occur in rooms. Yeehaw, hootenany, etc. Contents, in Order (Some sort of order, I guess) 1: Tutorial 2: Syntax Notes, READ 3: Function Listing 4: Variable index = true 5: Argument Listing ================================================================================ == Tutorial == ================================================================================ Okay, time to design scripts for your favourite room. Scripts let you force specific events to occur in the level that are not prebuilt by the room itself. You can spawn enemies, make explosions, change tiles, set bosses, all kinds of excitement. The way to get started is to create your room's .ssf file. In the Scripts\Rooms\ folder, create a file called areanumber.ssf, where area and number are the area text and room number, respectively. An example: Brinstar, room #1 = Brin01.ssf Capitalization is optional, like condoms! You can see the SMTC names for the levels in the editor. CRAT, BRIN, NORF, etc. 99 is the max rooms, so put a preceeding 0 if the number is less than 10. Now that we have our script file made, we should open it up (Notepad works fine) and start scripting. The first thing that should be in any script file that matters is this: On_Load { statements go here } On_Load means that everything after the { and before the } will be executed as the room is loaded. This is a good place to set things like Environment Values, lighting, or other crazy crap. After that, the rest of the script file is a series of if() statements and declarations. A typical script looks like this: //Code begins On_Load { env_rain = true } if(Samus.x >= 15) { env_rain = false } else { env_rain = true } //Code ends Some Notes on this. Each statement you make should end the line. Press enter after each statement, or the script will not read it. Only the first statement on a line is kept. GOT IT? First one only! Next, the {} braces keep items seperated from one another. When you use an if() statement, the stuff in the brackets is calculated, then what is between the {} braces is performed. This is elementary stuff, so pay attention. Lastly, the if statement is accompanied by an else statement. You don't always need an else, mind you. You use an else whenever the if statement is false and you want to do something. In this case, if Samus' X value is greater than or equal to 15, the rain turns off. Otherwise, the rain turns on. Another item of note, true is equal to 1, and false is 0. Saying env_rain = 1 is the same as saying env_rain = true. Just a heads up. Here's how the script works. After running through the On_Load events, the script is then checked over once every frame. Every time an applicable if or event is there, it executes it. You have complete control over what goes on in the game, so go nuts. Next, how to make Variables. Variables are things you declare outside the script that can be used in the script. A variable can hold one number, of any conceivable size. For more information on the upper and lower bounds, go look up floating point numbers on google. These numbers may hold decimals. You assign variable names in VarDefs.ssf. This should also be in your Scripts\Rooms folder. Open this file. You should see several lines that look like: BossFlag Crat1Weather And so on. This is how you define Variables. SMTC has set aside as many variables as you need, but you MUST define them in VarDefs.ssf. All of these can be accessed by saying their 'names' in the VarDefs file. BossFlag is one value, and you can use it like any weather or enemy variable. To create a new variables, just enter its name on a new line. Next up, arithmetic stuff. You can edit the value in a variable with the traditional = sign, but you're not limited there, oh no. You can use other stuff, like the +, -, *, and / signs, which are (in order) plus, minus, multiply, and divide. Example! BossFlag = BossFlag + 1 This will increase BossFlag by one, whatever one represents. You can also use: BossFlag += 1 This does the exact same thing, but is a lot quicker to type. Complex arithmetic is also possible: BossFlag += 1 * 15 + 2 This might be a good time to point out that MY SCRIPT ENGINE DOESN'T CARE ABOUT ORDER OF OPERATIONS. That's right, that statement will do this: BossFlag + 1 BossFlag * 15 BossFlag + 2 Just a heads up, you know. It does stuff left-to-right and it doesn't mess around. Likewise, don't put brackets in there, because they won't help. If you put brackets in, the script will go clean past them. Also, an operator must be preceeded and followed by at least one space. BossFlag += 1+1 is not acceptable. ================================================================================ == Syntax Notes == ================================================================================ Here's EXACTLY how the syntax should be for variable statements. variable operand value Spaces are critical. You can place as many spaces as you want before and after the words on the line. Ex: salty += 5 Is the same as salty += 5 For statements with multiple numbers in the value part of the line, like: salty += 5 + 5 The same rules apply. However, THIS is illegal: salty+=5 The script will think the variable's name is salty+=5, and will assume that there is nothing else on the line. Likewise, for the value part of the line: salty += 5+5 The script doesn't know what 5+5 is, since it thinks it is all one number. As a result, the script will add 5 instead of 10. The script only takes the first parts of the number until it hits something it doesn't understand(non-numerical) The accepted operators are: = Assign the variable to whatever value is += increase the variable by the value -= decrease the variable by the value *= multiply the variable by the value /= divide the variable by the value ^= multiply the variable by itself value number of times. If variable is 2, and value is 5, then the answer will be 2^5, or 32. For the value part of the line: The first part of the value must be a number, the second an operator, the third a number, and so on. The script will assume all the odd items are numbers, and the evens are operators. Syntax: variable operand number operator number operator number operator etc. Example: salty += 5 - 2 + 7 - 25 * 12 The accepted operators are + add - subtract * multiple / divide ^ exponent Note that brackets are not used, and order of operations is LEFT TO RIGHT. Regardless of what you put on the line, it's left to right, so deal with it. Note that only the first character of the operator is checked, so it could be: 5 +-*/^ 5, and the end result will have been 5 + 5 Acceptable values: A number is defined as the following [+/-][nnnnn][.nnnnn][e/E[+/-]nnnn] n is a number between 0 and 9. You can also use the E at the end to show exponents in the numbers. Example: -304.557e-18 is acceptable Though I wonder if anyone will actually use the full range of numbers. ================================================================================ == Function Fun == ================================================================================ A list of the functions available to you fellas? No kidding. Sprite(name, sprite, x, y, flipflag, time) Creates a sprite with those values, or modifies the values if the name is already used. Time refers to how long until the sprite is deleted. ModSprite(name, x, y, xspeed, yspeed, xaccel, yaccel, xforce, yforce) Change the speed forces on a sprite. The speed, accel, and force variables are all derivitives of one another: x is affected by xspeed, which is affected by xaccel, which is affected by xforce. This allows for some types of complex motion, like circling or slingshotting around. SpecialSprite(name, movetype, obeyclips) Cancels all x and y speeds and accellerations, then switches the sprite to a special pre-defined type of motion, such as localgrav. These are defined in the arguments section. UseTileAsColTable(tileno) Used for the program startup, modifies a tile into a colour remasking table. For advanced users only. The number is the same as the tile, the function does the rest. The function returns how many col remasks it made, and increases the memory array called CustomTileRemasks by 1. Remask_Tiles(name, tileno1, tileno2, RemaskTable, palette) Combined with the above, allows dynamic colour remasks of tiles. RemaskTable is the array position with the remask table, colno is which palette you want to use. Tileno1 is the first tile number you want to remask, tileno2 is the last. This function only needs to be called once to work, and if you want to stop remasking, call the Unremask function. You can call this multiple times on a tile but only the last one will remain active. It is also considered unwise to call it multiple times on a tile. Use the name to keep track of your remasks. Unremask(name) Disables dynamic recolouring for the indexed recolour. It is advised that you destroy the Remasks in the same order you created them if they overlap tiles. Calling it multiple times on a single remask does nothing. Cycle_Remask(name, tileno1, tileno2, RemaskTable, steprate, max, cycletype) Sets up automatic remask cycling. This is used in places like Norfair to make the tiles glow with heat. Steprate is how quickly to go from slot 1 to slot 2, slot 2 to slot 3, etc. Max is the number of steps in the cycle. Cycletype can be 0 (loop) or 1 (low-high, high-low, repeat). SetBG(index) Sets the background in this room to the index applied. See the accompanying file, bglist.txt for a list of all indexes available. Make sure to set a background each time you load a level, as the BG is cleared on init. SetBGScroll(int xnum, int xdenom, int ynum, int ydenom) X and Y scroll ratios, xnum/xdenom and ynum/ydenom. Normally, the background scrolls one pixel for every pixel Samus moves. This modifies that behavior. If you set the denominator or numerator to 0, the bg will not scroll at all. The behavior is: Every num pixels you move, the bg scrolls denom pixels. Whole numbers only please, SMTC does the rest. ================================================================================ == Variables Listing == ================================================================================ env_weather; This is the weather value. 0 is inactive, 1 is rain, 2 is snow. Weather particles function independently of custom particles. However, you cannot directly manipulate these particles, only by use of the weather options. env_weather_xspeed; When a rain/snow particle spawns, this is the xspeed it has. All weather particles have the same xspeeds and yspeeds. env_weather_yspeed; Ditto, but for the yspeed. env_weather_left; The left boundary of the weather spawn line. Weather particles always spawn between the left and right boundaries of this line at the specified height. env_weather_right; See above. env_weather_height; See above. env_weather_spawnrate; This is the rate at which weather particles spawn. A weather particle is terminated on contact with the walls or ground, and you may have up to env_weather_particlesallot at any one time. Experiment with the spawn rate to make sure you can get the rain smooth without running out of space. The spawn rate is a floating point value of up to 4 decimal places. Each frame, it increases the spawn_count. Each value over 1 will spawn one particle. Here's an example: If the spawnrate is .5, the count is 0. first frame: count = .5 second frame: A particle spawns, count = 0 third frame: count = .5 And so on. Spawnrate can be greater than one, in which case multiple particles may spawn in one frame. env_weather_spawntype; This allows you to determine where on the line the particles will spawn. The accepted values are the following: 0 = Random. Particles will spawn at a random spot on the line. 1 = Staggered. Particles will spawn at a random locations on the line, in incements of 1/10 the line's total length. This means that the first particle may spawn anywhere between 0 and 1/10, the second between 1/10 and 2/10, etc. 2 = Extremity Alternating. Particles will spawn alternating at random locations on the left half of the line, then the right, then left, etc. 3 = Wave alternating. Like extremety, however, the particles continually move closer to the center, then outwards, then center again. They do this in increments of (you guessed it) 1/10 of the line's total length. The first particle spawns between 0/10 and 1/10, the second between 9/10 and 10/10, the third 1/10 and 2/10, etc. env_weather_particlesallot; This determines the maximum number of particles you may have in the level at any one time. ================================================================================ == Argument Listing == ================================================================================ name: A unique name associated with the object. Every time you call the name, that object is loaded, assuming it is of the correct type. The names are not case sensitive. If the name does not exist, nothing will happen. Note: Do not use "NoName" for your sprites. This is a system name, it is reserved by SMTC and will mess up your access! sprite: One of the custom sprites that has been declared in SpriteDefs.ssf. x: X location on the screen. Lower is left, higher is right. y: Y location. Lower is top, higher is bottom. flipflag: Determines if the sprite is flipped or not, and how. Accepted values: 0 No flip 1 Vertical flip 2 Horizontal flip 3 Vertical and Horizontal flip time: How long until an event executes. -1 means the event never occurs. movetype: A special argument, this has several values that negate all current movement. they are: 1 LocalGrav: Object behaves under the same gravity Samus does, which is local to the room (standard: MaxFall speed = 5, Gravity = 1/8) 2 ImpactGrav: Object acts like Localgrav, but will bounce on impact. If clipping is not active, then it is identical to LocalGrav. obeyclips: A flag as to whether or not the object will react to clipping the environment, objects, or both. Objects are things like Samus, Enemies, or Samus' Ship, but NOT other sprites or beams. 0 Ignore everything 1 Ignore enemies 2 Ignore objects 3 Hit everything Notes about these arguments: Some of these cannot be negative, and the script will assign special values to negative numbers. -n Infinite: In some cases, never perform the event specified (see time above) -1 No Change: Leave the modifying value as is (x and y use this) -2 Samus' X Position: For following objects around Samus. Left side. -3 Samus' Y Position: Ditto. Top part. For -2, if you want the right side, it's +10 from the left. For -3, if you want the bottom, it's +48 from the top. -n means -anything, like -99. As long as it's negative but not one of the other special values, it will do its job as described. RELATIVE ARGUMENTS ARE NOT SUPPORTED AS OF THIS RELEASE!!!! Relative Arguments: To make an argument a relative value, simply type rel before the number. This is only really useful when using functions. Ex: Sprite("MySprite", -1, rel4, rel-5, -1, -1) The rel part before the number is disregarded, but the number is considered a relative value, not an absolute one. That means that the sprite will now move 4 to the right and 5 upwards, because it used: Sprite's X += 4, instead of Sprite's X = 4. These may be used to create mobile objects that follow AI routines inside your scripting, so knowing how to use rels is VERY important.