Script Language
The event file(s) for a particular scene are responsible for describing what can happen in that scene. This is accomplished through the use of the script language, which is based on execution of events contained within various threads.
Threads
A single thread is a list of events to be performed one at a time, in order. A thread can start another thread, which can cause multiple threads to be executing simultaneously. This is exactly what you want in many cases, since you will want some things to happen simultaneously.
Example thread:
foobar
{
wait(actor_in_room($actor0,"badplace")); //hero enters badplace
begin_thread(creepy_sounds); //handles the kraken sounds
begin_thread(seal_door); //door closes behind hero
begin_thread(release_the_kraken); //time to die
}
A thread starts off with its label, which is "foobar" in this instance. Inside the curly braces is the sequence of events that makes up this thread. Each event indicates what type of event it is ("wait" or "begin_thread" in this example). Then, inside the event's parentheses, are whatever parameters the event needs in order to know what to do. Each event is terminated with a semicolon (;).
Anything that appears after a double slash (//) is a comment. Comments have no effect upon the operation of the script. Rather, they are included in order to explain what's going on to someone reading the script.
Starting a the top of the list, each event will be executed in order. An event in the list is not performed until the previous event has terminated. Different events terminate under different conditions, and knowing when a given event will terminate is part of being able to use the script language effectively.
For example, the wait event doesn't terminate until the stuff inside its parentheses is true. In the foobar thread above, the first event will terminate only when the actor_in_room() test returns a TRUE, which happens when $actor0 enters the room called "badplace." At that point, the next event is executed, which will start the thread called "creepy_sounds." The begin_thread event terminates immediately, so the next event is executed at the same time.
Describing the thread as a whole, it waits until $actor0 is in the room "badplace", then immediately and simultaneously starts the threads named "creepy_sounds", "seal_door", and "release_the_kraken." These threads will be running concurrently. Note that each of these threads may begin other threads as well. The whole thing can get pretty complicated very quickly, and it takes some time getting used to the idea of keeping track of many things happening in parallel.
Startup
Starting threads is how the script writer will control what happens in the game, and he does that by putting events into threads. But since there has to be some way to get everything started, startup is reserved as a special thread name: all threads named startup will be initiated at the beginning of a scene. These threads will begin other threads under certain conditions, which will in turn begin other threads, and so on. It is up to the script writer to decide what will happen in the scene (what threads are in the event file), and when each thing happens (what conditions must exist for the thread to be started).
Here's a simple event file:
startup
{
palette_fader(0, 255, "fade_in", 4);
post_message("Welcome to the bear-fight!",3);
begin_thread(fight_the_bear);
wait(actor_compare($actor1,"ALIVE","=",0));
post_message("You have killed the bear!",4);
}
fight_the_bear
{
actor_objective($actor1,"COMBAT");
}
OK. The startup event is launched at the very beginning of this scene, and the first thing we do is cause the screen to do a fade-in that lasts for 4 seconds. When that is done, we put the message "Welcome to the bear-fight!" on the screen for 3 seconds. Then, we start the thread named fight_the_bear and then we wait for actor1's ALIVE setting to be equal to 0. This means we are waiting for actor1 to be dead. Presumably, actor1 has been set-up as a bear in this setting's scene
file (see the "Settings" document). After the bear is dead, another message gets printed.
Now, while this startup thread is waiting for the bear to be dead, the fight_the_bear thread is setting actor1's objective to COMBAT. This means that the bear will be in combat mode, looking to fight with the nearest enemy.
Initialize
Initialize is a special thread name, much like startup. The reason initialize exists is because the save_game event doesn't do a perfect job of storing all aspects of the game-state. Some things "slip through the cracks." So, the initialize thread name is used on those threads that should be started every time a level is loaded, even if it is from a save-game file. This contrasts with startup threads, which get started when a level is run from its very beginning.
Minke
This is a special syntax that is best explained through example. Instead of writing:
thread_1
{
event_1a();
begin_thread(thread_2);
event_1b();
}
thread_2
{
event_2a();
}
You could write instead:
thread_1
{
event_1a();
minke(thread_2)
{
event_2a();
}
event_1b();
}
Minke allows you to move a thread into the text of some other thread.
Since minke doesnt allow you to do anything functionally that you couldnt already do, why ever use it? Well, sometimes you have some activity that you are scripting as one logical unit, and you dont want to break it up because it would hurt the readability of your script.
Another time it is used is when you realize that the timing of an event termination is messing up the way you intended your script to work, and you want to easily fix it. An example follows.
Minke, cont.
door_opens
{
fixture_translate($door2.off,<0,100,0,$door2.off>,4); //door slides up
actor_objective($actor3,"COMBAT"); //actor3 fights
actor_objective($actor4,"COMBAT"); //actor4 fights
}
What you intended was that the door would open as the two creatures inside respond by going into combat mode. BUT, since the fixture_translate doesnt terminate until the door is done moving, and since the actor_objective(COMBAT) event doesnt terminate until the actor is dead, what you are going to get is much different. The door will open all the way, then only actor3 will go into combat mode. Then, when actor3 is dead, actor4 will go into combat mode. You could just re-write the event as:
door_opens
{
minke(door_slides_up)
{
fixture_translate($door2.off,<0,100,0,$door2.off>,4);
}
minke(fight_3)
{
actor_objective($actor3,"COMBAT");
}
actor_objective($actor4,"COMBAT"); //actor4 fights
}
and it would work the way you intended, since each thing would operate simultaneously as its own thread. Also, you can look at the whole thing as one unit rather than chase through several different threads to see what your script looks like.
Tests, Wait, If, and Else
The language allows the script to test various conditions. You already saw an example of this in the "foobar" script:
wait(actor_in_room($actor0,"badplace"));
Actor_in_room is referred to as a test. It doesnt really cause anything to happen, but instead checks on some condition and reports back to the script whether the condition is TRUE or FALSE. In this case, the wait event is using the test to determine when it should terminate and let the rest of the thread play itself out.
Tests can also be used in conjunction with if, which is subtly different from the wait event. Here is a sample use of if:
check_kobold_dead
{
if(actor_compare($actor4,"ALIVE","=",0)) // if the kobold is dead
{
begin_thread(start_siren);
actor_objective($actor5,"COMBAT"); // the other kobold attacks
}
}
When this thread is run, the actor_compare test is performed, checking to see if actor4 is dead. If so, then the events inside the ifs curly braces will be performed. If not, they will be skipped over.
This differs from wait in that wait will hold the thread still until its test is true, then it will allow the thread to continue. If, on the other hand, will check its test just the once, and immediately decide what to do next. If the test for an if is FALSE, the events in its curly braces just wont get performed, and the thread will move on.
Else is used in conjunction with an if. You can immediately follow the ending curly brace of the if with "else." Then, any events in the else's curly braces will get executed whenever the if was FALSE. For example:
check_kobold_dead
{
if(actor_compare($actor4,"ALIVE","=",0)) // if the kobold is dead
{
begin_thread(start_siren);
actor_objective($actor5,"COMBAT"); // the other kobold attacks
}
else //when the if's test is FALSE, the following stuff gets done
{
begin_thread(we_love_hero); // the kobolds love the hero
}
}
So, if actor4 is dead, the thread start_siren gets begun, and actor5 goes into COMBAT mode. If actor4 is not dead, the thread we_love_hero is begun, because of the else.
Entities and Fixtures
The descriptions of the various events will include references to entities and fixtures. Fixtures are physical parts of the world, like the terrain geometry, crates, levers, and such. The things referred to as entities are generally just going to be the things created with the rigid_activate or sprite_activite event. See that event for details.
Actors and $trigger
All creatures that appear in a scene are referred to as actors. In the quest, the .scn file from the setting's subdirectory will specify how many actors there are in a scene, assign each an ID number, and indicate the race and subtype of every actor. These actors are referred to within the script as $actor0, $actor1, $actor2,.... The number after the $actor is the same as the ID number for that actor in the .scn file. The "hero" that the player is controlling is $actor0.
In an arena fight, the 4 character "slots" represent who will be $actor0, $actor1, $actor2, and $actor3.
$trigger is a different sort of a reference to an actor, which can be used anywhere that $actor# would normally be used. $trigger is a changing reference, which always "points" to the actor who triggered the thread. This is useful when you want to write an event that does something to whomever just tripped a particular trigger polygon, or whomever just picked up a particular item. A couple of actual examples:
campfire_burn //gets started when campfire trigger polygon is tripped
{
damage($trigger,0.5); //campfire damages whomever stepped into it
}
herb_effect //gets started when a healing herb is picked up
{
actor_set($trigger,"HEAL",600); //healing herb heals whomever got it
}
List of Tests
Tests report either TRUE or FALSE, and are used in conjunction with if and wait. @ denotes a feature not in the release version.
actor_compare($actor#,"variable","comparison",#)
Tests a variable of an actor. The comparison entry must be either =, >, or <. As an example, actor_compare($actor0,"HIT_POINTS",">",1000) will report TRUE if actor0s HIT_POINTS is greater than 1000.
actor_in_room($actor#,"room_name")
Whether the actor is in the indicated room.
box_broken($fixture.off)
Whether the indicated fixture (not necessarily a box) has been smashed. This is often used to "put" stuff in boxes:
wait(box_broken($box23.off));
[followed by bringing an item into existence where the box used to be]
entity_valid($actor#) @
Whether the actor exists. Used in arenas to see if a particular actor slot is filled so that we dont try to do things to nonexistent actors.
maybe(probability)
Probability must be between 0 and 1, and indicates the probability of maybe reporting TRUE. Example: maybe(.3) reports TRUE 30% of the time,
and reports FALSE the other 70% of the time.
not(TEST)
This just inverts the test inside, causing a TRUE test to report FALSE, and vice versa. Example: wait(not(proximity($actor0,<430,50,85>,150)));
waits until actor0 is no longer within 150T of point <430,50,85>.
proximity($actor#,<location>,distance)
Whether the actor is less than the indicated distance from the location. Distance is given in Treyarchs (60T = 1 meter). Note that locations can be relative to a fixture or actor. In order to test whether actor0 and actor1 are within 3 meters of each other you could use: proximity($actor0,<0,0,0,$actor1>,180);
test_flag(flag_number,0 or 1);
There are 32 flags, numbered 0 through 31, that can be set to be equal to either 0 or 1 by using the set_flag event. Test_flag reports whether a given flag is equal to the indicated setting.
List of Events (@ indicates feature not in shipped original)
actor_action($actor#);
Makes actor "hit the action key." This can cause the actor to set off action-key-triggerable triggers or pick up (and use) an item.
actor_add(ID,"type",<location>); @
Intended for arenas, this adds an additional actor (beyond the ones that were selected in the set-up screen.) The new actor will be $actor#, where # is the ID number indicated. Type is the race and subtype of the new actor (see Characters doc). Location is where the actor starts off.
actor_add_item($actor#,"item_name");
The first one to search the actor's dead carcass will get the item. The item has to have been defined with add_item.
actor_award_point($actor#); @
Awards a "kill" to the actor. Used to keep score in arenas. The most common use is to award a kill when you kill another actor, but it can also be used more generally (to track points, time, golf strokes, etc.)
actor_break_tether($actor#);
Releases the actor from the tether (if any) he was constrained by.
actor_drop_luggage($actor#);
Causes the actor to drop any luggage he might be lugging.
actor_instant_sheathe($actor#,state);
The actor will do an "instantaneous" (un)sheathing (no reaching the hand back to place the weapon on his back, it just leaps into place.) The state determines whether the actor will be set to sheathed (1) or unsheathed (0) state.
actor_light_source_projectiles($actor#,brightness);
The actor's projectiles will be shadow-casting light sources. The brightness is a float, which was set to 1.7 all three times it was used.
actor_lock_position($actor#,<location>,constrain-Y);
The actor is locked to the location (bear in mind that locations can be relative to some object that is moving, so the actor could be locked relative to a moving object.) Constrain-Y is whether to also constrain the actor's "Y" (up-down) position: 1 is yes, 0 is no.
actor_look_at($actor#,"logic",<location>);
Sets the actor's looking logic. The two available logics are DEFAULT and LOCATION. The DEFAULT logic has the actor point his face at the nearest enemy, provided the range is sufficiently short. LOCATION instructs the actor to point his face at the specified location. The location parameter should only be included when using LOCATION logic.
actor_malor($actor#,<location>);
Instantly teleports the actor to the location. We should acknowledge here that MALOR was the name of the teleport spell from the computer game Wizardry, which many of us remember fondly from our grade-school days.
actor_noise($actor#,noise_index);
The actor makes the noise indicated by the noise_index. The noises associated to each noise_index are:
0-2: screams 3-5: exertions 6,7: death 8,9: footsteps
10: landing 11: falling 12:victory
actor_objective($actor#,...);
Change the objective of the actor in question. Each actor has a single objective that he is carrying out, and giving an actor a new objective causes him to forget all about his old objective entirely. Most objective events terminate once the objective is accomplished. When this happens, the actor changes his objective to WAIT_STILL.
OBJECTIVES:
"ADJUST_POSITION",<location>,facing
Move so as to end at location with the specified facing.
"COMBAT"
Hunt down and attack the nearest active enemy. If there are no active enemy, wait still until there are. Doesn't terminates.
"ENVIRONMENT_SCRIPT","script_name"
Perform a "move". Once done, change to wait_still. The move must appear in the .mvl (move list) file for the race of that actor as an environment move. (See Creatures document)
"FACE_OFF",distance
Face actor 0 and swing your weapon around occasionally while trying to maintain the specified distance between yourself and actor 0. This was used to make the kobold in the first level behave in a taunting manner while luring the hero into the ambush room. Does not terminate.
"GO_DIRECTLY_TO",<location>
Rotate to face the specified location, then walk straight towards it. This differs from GO_TO in that this does not use the pathfinding logic to seek a reasonable path to the destination, but rather marches straight toward it.
"GO_LUG",<location>,$fixture.off,bool
Go pick up the specified fixture at the given location. The bool indicates whether the pick-up is two-handed (1) or one-handed (0).
"GO_TO",<location>
Go to the location using the pathfinding logic.
"GO_TO_WHILE_SHEATHING",<location>
Like GO_TO, except put your weapon away while moving to the location.
"GO_TOUCH",<location>
Use the pathfinding logic to get into a position so that you can put your hand at the specified location.
"PATROL",speed_multiplier,number_of_points,<location>,<location>,...
Move to each specified location, in the given order. When done, cycle back to the beginning. Speed_multiplier should always no greater than 1, and is used to make the actor move at less than his top speed while patrolling. This objective does not terminate.
"SLEEP"
Fall down and don't move. This objective does not terminate.
"WAIT_FACING",<location>
Rotate your body so that you are facing the specified location.
"WAIT_STILL"
Stay.
actor_set($actor#,"variable_name",new_setting);
Each actor has a number of variables that can be altered (with actor_set) or compared to (with actor_compare, covered in the logical operators section). The variables that can be set are listed below:
ACTOR VARIABLES:
POSITION: In the form <X,Y,Z>; unit of measurement is Treyarchs.
VELOCITY: Given in the form <dX,dY,dZ>; in Treyarchs/second.
FACING: Given in "binrots", where 256 binrots = 360 degrees.
HIDDEN: 1(yes) or 0(no). Hidden characters do not render, and are unnoticed by the other characters.
PARALYZED: 1 or 0. No movement instructions go to the character.
FORCED_TO_CROUCH: 1 or 0. Character stays in a crouch as long as this variable is set to 1.
IS_SHEATHED: 1 or 0. Whether the character's weapon is stowed.
ALIGNMENT: An integer. Characters of dissimilar alignments will fight one another. At the start of a quest level, the hero is given alignment 0 and all other creatures are set to -1.
ALIVE: 1 or 0. Useful with actor_compare.
X: The character's X coordinate, given in Treyarchs. Y and Z work similarly.
ID: The character's ID number. The ID of actor2 is 2, for example. Really only useful when used with $trigger.
HEAL: Only useful with actor_set. Setting this to a number will heal the character by that amount.
RING_PROTECTION: Defaults to 0. Setting it to a number will add that much magical armor to the character.
RESCALE: The ratio of the characters current size to his normal size. Can be set, and the character will then rescale.
LAST_HIT: The ID of whoever last hit the character. -1 means nobody.
MAX_DAMAGE_TAKABLE: Sets a cap on how much damage the character can take in any one blow. A setting of 0 makes the character invulnerable to blows. A setting of -1 means no limit.
MAGIC_RESISTANCE: Defaults to 0. Setting it to a number will add that much magical armor effective only against projectiles.
MAGIC_POWER_FACTOR: Defaults to 1. This is a multiplier to the damage that the character does.
HIT_POINTS: The number of hit points the character has.
COSMETIC_BEHAVIOR: 1 or 0. If set to 1, the character will only move when in view of the camera. This keeps non-essential movement from wasting computing power.
ATTRIB: Any attribute of the character may be set by using a different syntax from the normal actor_set. By using actor_set($actor#,"ATTRIB","attribute_name",new_setting); you may change a character's attribute. See the Attributes document for details.
actor_set_tether($actor#,<location>,radius);
Forces the actor to stay within radius Treyarchs of the location.
actor_sheathe($actor#);
The actor will sheathe his weapon.
actor_unlock_position($actor#);
Cancels the effect of a previous actor_lock_position.
add_item($tag,"item_type",<location>);
Adds an item of the specified type at the location. Note that adding an item does not cause the item to actually appear; you need to add a sprite_activate event to make a visible sprite. Add_item only handles the functional aspects of an item. The tag parameter specifies which sprite to cleanup after the item has been taken.
add_malor_dest(<location>);
Adds the location to the list of the teleportation cheat's destinations.
add_speaker("speaker","speech_file",$actor#);
See speaker_say for comments on speakers. This event establishes a speaker that uses the indicated speech file. The actor parameter indicates where the speaker's voice should be coming from.
add_tentacle("race",<location>,<bounds>,<bounds_flags>,facing);
Creates a tentacle. Tentacles are not treated as $actors, but are rather added through the use of this event. Race indicates which subdirectory to use for the tentacle's information. Location and facing denote the tentacle's position and orientation. Bounds and bounds_flags establish boundaries on the tentacle's movement. The three bounds_flags correspond to the three dimensions (X,Y,Z.). If a bounds_flag is set to 1, then the tentacle must try to stay in a place where its position along that dimension is greater than the corresponding number in the bounds parameter. If a bounds_flag is -1, the tentacle must stay less than the bounds number. A bounds_flag of 0 indicates that the tentacle is unconstrained in its movement along that dimension.
Example: add_tentacle("watr",<0,750,-3820>,<0,800,-4000>,<0,1,-1>,0);
creates a tentacle of type "watr" at 0,750,-3820. It will strive to keep its Y position above 800, and its Z position below -4000.
add_to_room("room_name",$fixture.off);
Establishes a fixture's starting room. This is for the benefit of the renderer, which only considers things that are in rooms sufficiently close to the camera.
associate_actor($actor#,"animation_name");
Some animations involve actors. This lets the code know that the indicated actor receives movement instructions from the animation.
associate_projectile_to_actor($actor#,"projectile_file",ammo_count);
Arms the actor with the projectile. Ammo_count of -1 means unlimited.
attach_animation_to_fixture($fixture.off,"animation_name");
Causes the place where the animation will be played to move along with the specified fixture. This is used to make the hero's getting into/out of the crate animations maintain position on the moving raft in level 2.
attach_fixture_to_fixture($attached_fixture.off,$base_fixture.off);
Whenever the base_fixture moves or reorients, the attached_fixture will move and reorient along with it. Attached is "glued" to the base.
attach_trig_set_to_fixture($fixture.off,"trigger_file");
Every trigger in the specified trigger file will move and reorient to maintain the same relative position to the fixture whenever it moves or reorients. This was used for the trigger for the crate on the raft.
begin_thread(thread_label);
Starts every thread that has the specified label. Note: although the language supports naming multiple threads with the same label, and then starting all of them at the same time, it is probably cleaner to keep each thread with a unique label and just use multiple begin_threads in order to start many threads at once.
camera_malor(<location>,<focal_point>);
Causes the camera to instantly leap to the specified location, oriented in such a way as to be pointing at the specified focal point.
camera_set_intelligence("camera_logic");
There are two camera logics. "chuq" logic is the default, and is the responsive camera that moves with the hero and obeys bounding rules and such. "marky" cam is a stupid camera that just follows instructions given it by the script language. If you want to override the camera in the script, you must set the logic to "marky" first.
change_fixture_room($fixture.off,"room_name");
Changes the room that the rendering engine considers the fixture to be in. The renderer will only consider items that are in rooms that are sufficiently close to the camera. Most times, fixtures will manage their own room locations without any problem. There are certain instances where you may need to override this, though.
continuous_sound("sound_file",<location>,volume,loops,booms,[flags]);
Makes a sound play at the specified location. Full volume is 32767, and lesser numbers make it quieter, all the way down to 0=silent. Loops specifies whether the sound will loop (1=YES, 0=NO.) Booms specifies whether the sound is more persistent over distance than normal sounds (1=YES, 0=NO.) Flags allows you to set the flags that change the way the sound is handled. The lowest-bit flag is "force streaming." A sound will load into memory and play from there if it is shorter than a certain size. This flag will force a smaller sound to stream. The next bit is "allow duplicates," which will permit multiple instances of that sound to play at once, normally prohibited. The last bit is "prohibit streaming," which is needed when you are allowing duplicates. Note that bits read from right to left. The flags entry can be omitted if you don't want to set any. That's best in most cases.
The differences between continuous and instant sound is the relationship between the sound and the event. With a continuous_sound, the event does not terminate until the sound stops playing. If you kill the thread with the continuous_sound, the sound will stop as well. In the case of a looping sound, the sound never stops playing, so the event will not terminate. The only way to stop the sound is to kill the thread that contains the continuous_sound with a kill_thread event.
With instant_sound, however, the event just tells the program to play a sound now without waiting for the sound to end. The event terminates immediately so the rest of the thread will play out, but the sound will play on no matter what. It is impossible to stop an instant_sound before it is done playing. This is why the loops setting was always set to 0 for instant_sounds used in the DBTS scripts: a looping instant-sound would play without any possibility of shutting it off.
damage($actor#,damage);
Inflicts the specified amount of damage to each of the indicated actor's limbs. The limbs won't actually get severed as a result of this, so the per-limb thing isn't really useful. But what it does do is make the actor take quite a lot more damage than the number specified.
define_item_type("item_name","sprite",thread,eatable,instant,key);
Defines a new type of item. Must appear in an initialize thread. Sprite is the picture that will appear in the message bar when that type of item is picked up. Thread is the thread to be started when that type of item is picked up. Eatable controls whether the hero will put the thing in his mouth when he finds it. Instant is unused. Key controls whether to run the thread when someone carrying this item falls out of the world, which avoids the dead-end that can occur if a key-carrier somehow falls out of the geometry. The last three parameters use (1=YES, 0=NO.)
delay(time);
Takes the indicated time, in seconds, to terminate.
destroy_breakable($fixture.off);
Causes the fixture to break (must have been declared breakable).
difficulty_multiplier(difficulty_level,multiplier);
Sets the difficulty multiplier for the score calculated at the end of the level. Difficulty_level is a number from 0 (squire) to 3 (lord).
do_port_lever();
Wow, I can't believe this is still in there. This is a kludge that was built for the first level in the quest. If $trigger is a kobold, it plays the animation "kobold_switch_pull." If it is the hero, it plays the animation "hero_switch_pull." There are better ways of accomplishing this now, but I guess we didn't bother to change the script since it worked just fine.
entity_deactivate($tag)
Makes the entity go away.
entity_lock_position($tag,<location>)
Locks an entity into a particular position, which is most often relative to some fixture. This makes the entity maintain its relative position to that fixture no matter how the fixture moves around or reorients.
entity_rotate($tag,rot1,rot2,rot3,time);
Rotates an entity around its own origin (see Modeling document.) There are three axis of rotation; therefore, you must specify the amount of rotation (in degrees) about each axis. A time is specified in seconds. A time of 0 is allowed, which indicates that the rotation should happen instantly.
fixture_auto_leveling($fixture.off);
Removes any X-axis twist that might be caused by rotating the fixture. This was made to keep the cart top from tipping side-to-side throughout all the rotations that it goes through during the cart ride at the end of level 3.
fixture_deactivate($fixture.off);
Causes the fixture to no longer exist. Not only does it no longer appear, but it doesnt affect movement, either. This was used to remove invisible shields, cause the skeleton sprites to disappear when we replaced them with real skeletons, and when the machine blew up.
fixture_fall($fixture.off);
Makes the fixture fall as if it were affected by gravity. The falling will stop when the fixture lands on a surface.
fixture_pendulum($fixture.off,<axis>,<pivot>,period,init,length);
Makes the fixture move in a pendulum-like fashion, swinging back and forth endlessly. The axis is the vector of rotation. Pivot is the point around which the pendulum rotates. Period controls how much time it takes for the pendulum to complete a cycle of rocking back and forth. Init indicates where in the rocking cycle the pendulum will begin. Length is the radius of the pendulum's rotation, in Treyarchs.
fixture_rotate($fixture.off,rot1,rot2,rot3,time);
See entity_rotate, but the rotations are given in radians rather than degrees. And, as the name implies, this is for fixtures.
fixture_rotate_about_axis($fixture.off,rot,<location>,<vector>,time);
This event rotates a fixture around a specified axis. The location specified is a point on the axis. The vector describes a direction from that point. This is a ray in space. Extend it out to a line and you have the axis of rotation. The amount of rotation is given in radians, and the time is in seconds.
This event was useful in allowing fixtures to rotate however we wanted them to. Fixture_rotate is limited to rotating about the fixtures origin, which is not always what you want. The parameters were often figured by finding two points on the axis desired, then using one of them as the location parameter, and the difference between the two points as the vector parameter.
fixture_translate($fixture.off, <location>,time);
Moves the fixture (orientation remains constant) with constant velocity so that its origin winds up at the location in the specified time.
instant_sound("sound_file",<location>,volume,loops,booms,[flags]);
See continuous_sound explanation.
kill_thread(thread_label);
Kills every thread that has the specified label. See begin_thread for note on using the same label for multiple threads. Killing a thread while it is performing an event will cause the event to abort. Note that already-started minkes inside a killed thread are unaffected, since they are really separate threads. Remember that a minke is equivalent to a begin_thread.
level_name("text");
Sets the level name for the end-of-level score sheet.
load_animation("anim_file","name",relocatable);
Loads the indicated .vue file, and assigns it a name so that it can be referenced within the script. Relocatable should always be set to 1.
load_scene("scene_file","movie_file","stats_picture");
Used in the quest event files for loading the next level. The movie-file indicates which movie should be played between levels. If no movie is desired, use an empty text string. ("") Stats_picture specifies the background bitmap to be used for the end-of-level scoresheet. Loading scene "end_quest" will go to the Quest-ending stats page, followed by the credits, then to the main menu. Loading scene "terminus" causes the game to just terminate back to the main menu.
loop_animation("anim_name",start_frame,end_frame);
Sets the looping markers for the animation. Note that this event does NOT cause the animation to start playing. It just sets two markers. Whenever an animation is playing and it finished the frame that was marked as the end_frame, it next plays the start_frame. Animations start off without these markers set, and using stop_loop_animation will clear the markers.
make_breakable($fixture.off,"shard_type");
Makes the fixture breakable, so that it can be broken either by a weapon hitting it (hitting its origin, really,) or by a destroy_breakable event. Shard_type is which subdirectory in the shards folder to use.
make_breakable_pair($fixture.off,$replacement.off,"shard_type");
Works like make_breakable, except that when the fixture is broken, it is replaced with the replacement fixture. This was used for the webs.
make_hinged_door($fixture.off,thread,time,<vector>,rot);
Declares the fixture to be a hinged door. Whenever a door is made, it will start off locked. When unlocked (with the unlock_door event), it will wait until someone gets near it and presses the action key. Then it will open. The door may also be opened with an open_door event. Whenever a door opens, it begins the thread indicated. This is useful for having it make sound or alerting monsters inside.
Hinged doors rotate about the axis that passes through the door's origin and is parallel to the specified vector. The only vector we used was <0,1,0>, which follows the Y axis (straight up+down,) but you could make other sorts of hinged doors. Rot specifies the rotation, in radians, and time is the time, in seconds, it takes to open.
make_sliding_door($fixture.off,thread,time,<location>);
See make_hinged_door for info on doors. Sliding doors move with constant velocity so that the origin winds up at the specified location in the indicated time (in seconds.)
marky_cam_set_focus(<location>);
The camera logic must have already been set to "marky" for this event to make any sense. This tells marky cam what location it should be pointing at. Since locations can be given relative to a fixture or actor, you can have marky cam point at a moving fixture or actor by giving it a focus location relative to that object. For example, marky_cam_set_focus(<0,30,0,$actor0>); would make the camera track a point that was 30Treyarchs (1/2 meter) above the head of actor0.
Marky cam will change its orientation only as quickly as the camera attribute MAX_FOCUS_SPEED, changable with modify_camera_attribute.
marky_cam_set_pos(<location>);
The camera logic must have already been set to "marky" for this event to make any sense. This tells marky cam what location it should be moving toward. Marky cam will only move as fast as the camera attribute MAX_MOVE_SPEED, changable with modify_camera_attribute. Again, the location can be given relative to a fixture or actor.
modify_camera_attribute("attribute_name",new_setting);
There are various camera attributes that can be modified. MAX_MOVE_SPEED & MAX_FOCUS_SPEED are the only two we altered in script.
MAX_MOVE_SPEED controls the maximum speed that the camera will move at, even when the spot it wants to go to is far away. The default is 1200, which is in Treyarchs per second. MAX_FOCUS_SPEED controls how quickly the camera is willing to move the point that it is focussing on. Default is 2400, given in Treyarchs per second.
There are other camera attributes, all of which are listed in data\misc\camera.att (the default attribute file.) Change at own risk.
music(track_number,loops);
Starts the indicated music track. The looping parameter can be omitted, in which case the default is for the music to loop.
new_body($actor0,$new_body#);
Gives the hero control of a new body. Was used for shaman mask effect.
The new body actor and actor0 will swap positions, and then the user will be given control over the new body actor.
nop();
Stands for "no operation." This event terminates in one "tick." It is useful anywhere you want the script to "pause" a bit before continuing.
For example, the program will hang up if you make a "tight loop" anywhere. A tight loop is a thread that can call itself without any delay. It will sit there and do it infinitely. So, a nop(); somewhere in there will cause it to pause a "tick" before it restarts. Following is an actual thread where we had to use a nop(). Whenever actor0 is in "301orcvm" and not sheathed, this would be a tight loop without the nop:
wait_ambush_3
{
wait(actor_in_room($actor0,"301orcvm"));
if(actor_compare($actor0,"IS_SHEATHED","=",1))
{
begin_thread(drop_down_3);
}
else
{
nop(); // NEED THIS to avoid a tight loop
begin_thread(wait_ambush_3);
}
}
old_body($actor0,$new_body#);
This just "undoes" what new_body did, giving the hero his old body back.
open_door($fixture.off);
The fixture must have been made a hinged or sliding door with one of the make_TYPE_door events. This opens it, and so begins the door's thread.
palette_fader(0,255,"fade_type",time);
There are two fade types: fade_in and fade_out. The time that the fade takes to complete is given in seconds.
particle_spray(<location>,<vector>,<R,G,B>,count,duration,fade,[flags]);
This creates a spray of particles to emanate from the specified location. The vector specifies the direction and velocity in which the particles will tend to fly out. R,G,B specifies a color for the particles; the code will pick the closest color from the palette. Count is the number of particles to be created. Duration is how long the particles will last, in frames (18frames = 1second.) Fade is how many frames elapse between decreases in particle brightness level.
The flags are (from right to left):
An unused flag
"Fades" - Whether the particles fade as they age
"Big" - Creates big particles
"Trace" - Particles leave a trace behind them
Another unused flag
"Bright" - Makes the particles brighter
"Line" - Makes little line-segments rather than particles
"Rand Age" - Randomizes the age of the particles at the start
"No Kick" - The particles don't get a random velocity "kick"
play_animation("animation_name");
Starts the indicated animation. Any actors associated to the animation will move as specified in the animation.
polygon_set_anim($fixture.off,poly#,frame,rate,direction);
Alters the parameters for the animation on the specified polygon of the fixture. The polygon must be textured with a .ban fine (the way textures are animated.) Poly# designates which polygon of the fixture is being changed. Rate is the new animation rate, in frames per second. Frame is the frame to start with. Direction theoretically alters the direction that the animation will run in. A rate of 0 can be used in order to swap one still texture for another: just change which frame is being played with the frame parameter.
post_message("text",time);
Puts the text on the screen for the indicated time in seconds.
regional_sound_event("sound_file",<play_location>,volume,booms,loops,
<sphere_center1>,radius1,<sphere_center2>,radius2,...);
The first several parameters are just like those for instant_sound and continuous_sound. After those parameters, however, is a sequence of sphere_center coordinates and radii measurements. These define a set of spheres that in turn defines a volume of space. The regional sound will play at the play_location (seems like it should always be on top of the hero), with a volume that depends upon how far the hero is from the nearest point in the volume. What this is for is a large area that is collectively making some noise - like a river or a large pool of lava. You want the volume to be dependent upon how close the hero is to the thing as a whole, not just some point in it.
reset_flags();
Sets all flags to 0. Do this in startup in every script where you are wanting to use flags, just to be sure they are all in a known state to start off with.
rigid_activate($tag,"rigid_file","material",<location>,<something>,rot1,rot2,rot3,[flags]);
Creates a new entity made of polygons. The only reason to add something this way instead of modeling it and adding it the normal way (through the .ter file) is that this is the only way to add a weapon into the geometry. The spears for the spear traps, the spinning blades, and the pendulum blades were all done this way. The material is for collision sounds, and must one of the acceptable material names (see Creatures document.) Location is where the origin of the rigid will be. Rot1, rot2, and rot3 can be used to change the orientation of the rigid. The unit on the rotations for this event is Binrots. (256B = 360 degrees.)
rope_trap_event($actor#,<location>,length,"rope_file",thread);
Triggers a rope trap. The designated actor will be pulled up into the rope trap. Location is where the rope is tethered, and length is how long it is. Rope_file is the .off file for the rope that be stretched out to the proper length. Thread is the label of the thread to be begun when the target of the trap has been cut free from the rope-trap.
save_game("file_name","text_description");
Writes the current game-state to the indicated file. The text description appears in the notice that a game has been saved and as a label when the user is loading previously saved games.
score_slot(slot#,"text",points,max_points);
The contents of the score_slots are used to fill in the information on the end-of-level scoring screen. Each slot has an ID number, some descriptive text, a number of points to be awarded the player, and the maximum number of points that the slot could have been worth. This event overwrites whatever information the score_slot may have contained previously. The way this was used was to initialize each score_slot with some default information, and then overwrite that information whenever some circumstance arose that required a slot to be amended.
Note: a slot with max_points of 0 is a "bonus" scoring item.
set_entity_room($tag,"room_name");
Whenever an entity is created with rigid_activate, it's proper room must be supplied with this event or else the renderer will ignore it.
set_fixture_rot($fixture.off,so3_parameter1...);
Just don't do it. Don't. Really. It uses an so3 to change the orientation of a fixture, and you have to some kind of mad genius to have any chance of messing with this at all. "You might get interesting shear effects by using non-orthonormal matrices." Right. Whatever.
set_flag(flag_number,0 or 1);
Sets the value of the indicated flag (numbered 0 through 31) to 0 or 1.
set_max_kills(number);
Sets the maximum number of kills for the level, which is reported on the end-of-level scoring screen. This number will be overridden by a subsequent set_max_kills event.
set_trigger("trigger_name",thread);
Associates the thread to the specified trigger. Triggers are defined and named in .off files in the setting's subdirectory. When a trigger sends the signal that it has been tripped, the associated thread is begun. "none" is used in the thread parameter to indicate that no thread is associated to the trigger. This is used to turn a trigger off under certain conditions, or to initialize it as having no associated thread (presumably, the script would associate a thread to such a trigger under certain circumstances.)
set_who_can_break($fixture.off,who)
Controls what sort of creature is able to break the fixture. Who is:
0 - Everyone (e.g. most crates, webs, etc.)
1 - Hero Only (e.g. the rope on the raft of level 1)
2 - Non-Hero Only (e.g. the Big Box the hero can hide in on level 1)
3 - No-One
speaker_say("speaker","speech_label",priority);
This event allows things that actors are supposed to say to enter into a queue so that you never have the effect of an actor saying more than once thing at once. Use of this requires that the speaker was added with an add_speaker event. Exception: the hero is an automatically-defined speaker, who uses the data/misc/speech.lst file as his speech list. So long as he is not already speaking, the speaker will say the speech that was assigned the indicated speech_label in the speaker's speech list. If he is already speaking, his current speech will be interrupted if the new speaker_say event has a priority setting that is higher than the current speech has. Otherwise, the new speech will go into the queue of things for the speaker to say when he's done with his current speech.
sprite_activate($tag,"sprite_file",<dimensions>,<location>,<velocity>,
[flags]);
Creates a sprite in the game world at the specified location and assigns it the indicated tag for identification. Dimensions is the sprite's apparent size along the X, Y, and Z axes, respectively. Velocity is the velocity vector of the sprite (this was always <0,0,0>.)
This is used most often in conjunction with add_item. The sprite_activate event creates the visual aspect of an item, whereas add_item defines its functional elements.
stop_loop_animation("animation_name");
This clears the loop markers for an animation. It does NOT stop an animation that is currently playing. Rather, it will stop it from looping. See loop_animation for details.
toggle_flag(flag_number);
If the indicated flag is 1, sets it to 0. And vice versa.
trigger_gets_last_hit($actor#)@;
This assigns the $trigger pointer to whomever last hit the indicated actor. This is used to find out who should be awarded the kill when someone dies in an arena fight. This event is immediately followed with "actor_award_point($trigger);".
ultimate_evil($actor#);
Does the ultimate evil on the indicated character.
unlock_door($fixture.off);
Yup. That's what it does. See make_hinged_door for details on doors.
by Treyarch