JJ2+ • AngelScript readme

Introduction

Arguably one of the biggest advances JJ2+ brings to JJ2 is the introduction of AngelScript. The AngelScript website describes it as "an extremely flexible cross-platform scripting library designed to allow applications to extend their functionality through external scripts." What this means for you as a level designer is that you can write code in a C/C++-like scripting language — anywhere from two or three to potentially hundreds of lines — that will directly alter the level, characters, and other objects within JJ2. AngelScript lets you change tiles without setting up trigger scenery, change the palette without cycling to a new level with a different tileset, force players to be Spaz without setting up elaborate systems of springs and sucker tubes, reverse players' gravity, create enemies from nowhere, and so much more.

(Note, however, that JJ2's AngelScript implementation is all but exclusively local in its domain. If a level is being run in an online server, essentially the only AngelScript code that will be passed on to the rest of the server is changing a local player's health/character, firing bullets, and chatting. Pretty much everything else is local to the instance of JJ2 calling the AngelScript code in the first place, and levels should be designed accordingly. (Of course, this is not a concern for Single Player levels.) Fortunately, everyone in the server will be running the same AngelScript code, making for somewhat more equal experiences than one might otherwise expect.)

This document does not teach you the syntax of AngelScript, which has a dedicated online manual for this very purpose, but rather tells you a) how to call AngelScript functions within JJ2 and b) how to change things within JJ2 once a function has been called. To begin with, open an old level or begin a new level that you would like to add some AngelScript functionality to, and take note of the filename (e.g. myLevel.j2l). Next create a plain text file (in Notepad or some similar editor, or a code syntax highlighter program that supports AngelScript if you have one) and save it to your JJ2 directory, giving it the same filename as the level but with the extension .j2as instead of .j2l. Thus: myLevel.j2as for myLevel.j2l, castle1.j2as for castle1.j2l, plus-gemtest.j2as for plus-gemtest.j2l, etc. This new .j2as file is where all the code for this particular level will live. (There is no way to share chunks of code across multiple .j2l files other than copying and pasting them.)

Next you will need to define one or more functions in the .j2as file for JJ2+ to call. Let's say that you're making a Single Player level and want to change the level's music, but not to either boss.j2b nor boss2.j2b, which are the only filenames the Activate Boss event would allow you. With AngelScript, this couldn't be simpler. Write the following in myLevel.j2as:

void onFunction0() {
  jjMusicLoad("tubelec.j2b");
}

Finally you need to set up to the level to call onFunction0. For this, you will need to edit your JCS.ini to include the following entry for 207 in the [Events] group:

207=Text |+|Trigger|Text| |TextID:8|Vanish:1|AngelScript:1|Offset:8

The boolean parameter "AngelScript," when set to 1, will call a function from within the level's corresponding .j2as file. Which function it calls is determined by the "TextID" parameter, which ranges from 0–255. TextID=3,AngelScript=1 will call onFunction3; TextID=150,AngelScript=1 will call onFunction150; and so on. In this case, each time a local player touches a Text event with TextID=0,AngelScript=1, JJ2+ will try to load and play the music file "tubelec.j2b."

The jjMusicLoad function is actually something of a special case, because it will not load a new music file if the file requested is already the currently playing music file. Thus hitting a Text event with TextID=0,AngelScript=1 multiple times will not have any undesirable effect like restarting the music. However, plenty of other functions do have cumulative effects, and it is not always desirable for a player to call the same function more than once, e.g. if there's a whole column of identical Text events to ensure that the player hits at least one of them while passing through an area. This is where the boolean "Vanish" parameter comes in handy. Unlike when AngelScript=0, when AngelScript=1, Vanish=1 disables the entire onFunction# function from being called by any Text events anywhere in the level. You can reenable, for example, onFunction5 by writing jjEnabledASFunctions[5] = true; in another AngelScript function or by calling the global function jjEnableEachASFunction, but unless you do one of those things, the function will remain disabled for the rest of the level. (It is still possible to call a disabled function directly from another function in the .j2as file, but not from another Text event.)

Finally the "Offset" parameter of Text events provides an optional one-byte parameter to the AngelScript function. The function for a given TextID, e.g. 5, can be defined one of four different ways, and in each case the "Offset" parameter is parsed accordingly. Note that if the AngelScript parameter is of type int8 — a signed 8-bit integer — then Offset will be interpreted as a JCS parameter of type -8, instead of type 8. Note also that if you define multiple AngelScript functions with the same name, JJ2+ will not know which one to call. This is undefined behavior and the result may vary across JJ2+ releases, so don't do it.

void onFunction5() {}
void onFunction5(bool paramName) {}
void onFunction5(uint8 paramName) {}
void onFunction5(int8 paramName) {}

The contents of your .j2as file must all be syntactically correct AngelScript. Any error in or outside of any function will prevent any and all AngelScript from running in the level. To get information about such errors, you will need to add a line AngelscriptDebug=True to the [General] group of plus.ini. (AngelscriptDebug defaults to false.) Information about errors and warnings will then be displayed in the chatlogger window, assuming the window has fully loaded by the time the error occurs. It is also possible to send your own debugging information using the global function jjDebug(string text), though, as with any other AngelScript function, it will only work if everything is formatted correctly.

Besides this, there are a number of game event functions which, if defined in a .j2as file, will be called at various points. Each takes no parameters and has no return value, and while more shall surely be added later, here are the ones available so far:

void onLevelLoad()
This function is called once, at the beginning of the level, and never again. If your level's tileset has a red textured background but you want a blue one, this is the place to change its colors. If you want the level to start with water at a certain height without placing Water Level events all around every start position, this is the place for that. And so on.
void onLevelReload()
This function is only ever called in Single Player, where it is called every time the player dies, after everything in the level has been reinitialized. Since a great number of things get reset in Single Player when the player dies, this is your chance to make sure some things stay the same.
void onMain()
Unlike the above two functions, which are very rare, this function is called absolutely constantly. It is important to understand that JJ2 measures time in "ticks," which number 70 to a second. (Correspondingly, when setting the duration for a sugar rush or somesuch, you will need to multiply by 70 to get the desired number of seconds.) The global property jjGameTicks will tell you how many ticks have elapsed at any given point. onMain is fired once per tick, and allows you to check constantly whether a given property has changed, move an object in a circle, or whatever else you find desirable.
void onPlayer()
This function can be called even more often than onMain: it is called once per tick per local player. If you're playing splitscreen with two players, for instance, it will be called two times per tick. This is a useful distinction solely because of the global property jjP (or p for short), which is updated to the current player every time onPlayer is called. If you want to prevent blaster from ever being used in a level, for instance, void onPlayer() { p.noFire = (p.currWeapon == WEAPON::BLASTER); } will do that for you, whereas void onMain() { p.noFire = (p.currWeapon == WEAPON::BLASTER); } will only work for one of the (potentially numbering more than one) local players. To check which jjPLAYER is being invoked during any given onPlayer, use p.localPlayerID.
jjP/p is also updated every time a onFunction# function is called, and points to the player who touched the Text event that called it.
void onPlayerTimerEnd()
This function is something of a special case. By default, when a Player Timer runs out (see the jjPLAYER section below), this function will be called with p/jjP pointing to the player whose timer just ran out. However, a single level may have multiple timer sections with different purposes -- one where you die for not doing something quickly enough, one where you warp after a certain delay, and so on -- so it is also possible to change the name of the function called using the jjPLAYER method timerFunction. Thus onPlayerTimerEnd is simply the default function name, not the only one you are allowed to use for this purpose.

The rest of this document is divided into three sections. First there are sections for all the available classesjjPAL and jjPALCOLOR for palettes, jjPLAYER for player characters, and jjOBJ for ingame objects — that you may create and manipulate, and also full lists of their properties and methods. Second are two lists, one of global properties and one of global functions. Like the classes, all global properties and functions begin with the letters "jj," with the sole exception of p, the shorter alias for jjP. This is a guarantee of backwards compatibility from future versions of JJ2+. While new global properties and functions will undoubtedly be added to AngelScript in future releases of JJ2+, as long as you don't begin any of your own properties and functions with "jj," there will be no naming conflicts and your scripts will continue to function correctly.

Finally there is an appendix which contains the various enums used by certain properties, methods, and functions. Each enum is nested within its own dedicated namespace, and both the name of the namespace and all the values of the enum are in all caps. Such enums may be the sole options for the properties and parameters that use them. For example, to configure the level so that water and ambient lighting can coexist, you will need to set the global property jjWaterLighting to WATERLIGHT::GLOBAL. You do not set it to 1 (a number), or GLOBAL (a variable that doesn't exist in the main namespace), or "GLOBAL" (a string), or CHAR::JAZZ (another enum value), etc. As well, certain arrays are indexed by enums rather than (or as well as) by integers; for example, you access a player's number of red gems through jjPLAYER.gems[GEM::RED], not jjPLAYER.gems[1], although jjPLAYER.ammo[WEAPON::BOUNCER] and jjPLAYER.ammo[2] are both acceptable. Depending on the commonality of an enum and the number of different values it has, either its values will be listed whenever it comes up in a property/method/function or they will be listed in full in the appendix at the bottom of this file. Like any other data type, enums may be used as parameters in your own defined functions, so long as you remember to attach the namespace to the enum name.

It is perfectly understandable if much of this seems overwhelming at first. You are advised to look through the example levels provided in your JJ2+ download, many of which include examples of AngelScript in action. Even if the specific properties being affected in a given level do not interest you, that level can still serve as an example as how AngelScript is written generally. And if all else fails, head to the JazzJackrabbit Community Forums to ask for help. Good luck!

Classes

class jjPAL

This is the class used by each level's ingame palette, used for drawing pretty much everything besides 16-bit water and textured background fade colors, which can be changed by the global function groups jjSetWaterGradient and jjSetFadeColors respectively. As such, changes made here can be very far-reaching and dramatic. Palette-editing in AngelScript follows essentially a two step process: first, make all the changes you desire to a (non-const) jjPAL object, and second, call that object's apply() function to make it be the current palette in use by the game. Here's a basic example:

void onLevelLoad() {
  jjPAL newPal;
  newPal.load("Castle1.j2t");
  newPal.gradient(190,0,255, 0,0,147, 112, 8); //change the colors of the knight statues
  newPal.apply(); //the game will now use a slightly-modified version of the Castle1 palette
}

In the simple example above, it would not actually be needed to declare a new jjPAL object. Instead, you could use jjPalette, which contains the current palette actually in use by the game. When you call apply() on any other jjPAL object, you copy its contents to jjPalette. Editing it directly is good for cumulative changes, but if you'd like to revert back to a previous state, you'll need a second jjPAL object. Alternatively, you could save the current state by copying it to a second jjPAL object using the assignment operator, e.g. jjPAL myPal = jjPalette;.

There is also a const jjPAL, jjBackupPalette, which maintains the palette that came with the tileset and will never change.

jjPALCOLOR color[256]
At its heart, a palette is a collection of 256 colors, and you can access them individually through the color array. In fact, you could if you chose reproduce nearly every jjPAL method here by directly altering the colors, but the methods are here to save you time, so don't do that. The details of jjPALCOLOR objects are listed below this section, though most basically you just use their properties red, green, and blue.
void apply()
Causes the contents of this jjPAL object to be the current colors in use by the game, and by extension jjPalette.
Note that this function does a fair bit of housekeeping behind the scenes to make sure everything is propertly converted to the new palette — there's a difference between myPal.apply(); and jjPalette = myPal; — and so it should always be called after doing any edits, even if you've been making the edits directly to jjPalette. Failure to do so can have unpredictable consequences.
void copyFrom(uint8 start, uint8 length, uint8 start2, jjPAL& source, float opacity)
Overlays length colors from source onto the current palette, beginning at start on this palette and start2 on source. If opacity is below 1.0, the new colors will only partially replace the old.
void fill(uint8 red, uint8 green, uint8 blue, uint8 start, uint8 length, float opacity = 1.0)
void fill(uint8 red, uint8 green, uint8 blue, float opacity = 1.0)
Replaces a series of length colors beginning at start with the color red,green,blue. If opacity is specified and below 1.0, the new color will only partially replace the old ones, making for a tinting effect. Leave out the start and length arguments to fill (or tint) the entire palette.
void gradient(uint8 red1, uint8 green1, uint8 blue1, uint8 red2, uint8 green2, uint8 blue2, uint8 start = 176, uint8 length = 32, float opacity = 1.0)
Replaces a series of length colors beginning at start with a gradient beginning with red1,green1,blue1 and ending with red2,green2,blue2. If opacity is specified and below 1.0, the new colors will only partially replace the old, making for a tinting effect.
The default values for start and length will set a gradient for the colors used by water and (in most tilesets) textured backgrounds.
bool load(string& filename)
Loads a palette from the specified file. If the file extension is ".j2t", will treat it as a tileset file and will try to access the palette stored in the file. Otherwise, tries to treat it as a palette file saved in "Color Map" format in Palsuite, and if that fails, simply reads the first 1024 bytes of the file. Returns false if the file cannot be found in either the main game folder or the cache subfolder, or if the file is fewer than 1024 bytes long; otherwise true.
void reset()
Loads the original colors used by the tileset. There is no non-stylistic difference between myPal.reset(); and myPal = jjBackupPalette;.

class jjPALCOLOR

The basic units of jjPAL objects. At their heart, they're just tiny collections of RGB values, but methods for playing with the HSL values are also provided in case you don't mind using up a little bit more processing power. Alphabetical order is ignored in favor of traditional order in the list below

uint8 red
How red this palette color is.
uint8 green
How green this palette color is.
uint8 blue
How blue this palette color is.
uint8 getHue()
The hue of this palette color.
uint8 getSat()
The saturation of this palette color, where 0 is grayscale and 255 is most saturated.
uint8 getLight()
The lighting of this palette color, where 0 is black and 255 is white.
void setHSL(int hue, uint8 sat, uint8 light)
Changes the entire color to a brand new one derived from the given HSL values. Due to the complexity of the calculations involved, you can only change all three values at a time, so if you want to leave, for instance, saturation constant, you'll need to read the old value through getSat() and then use that as the sat parameter.
hue is an int instead of a uint8 because it's a loop instead of a scale. 2, 257, 513, -254, etc., are all equally valid and all mean the same hue.

class jjPLAYER

If you're writing some AngelScript for Jazz Jackrabbit 2, one of the most natural things to want to affect is Jazz Jackrabbit himself! Or Spaz, or Lori, or so on, as they case may be. For this there is the dedicated jjPLAYER object jjP, or simply p for short. Following the firing from a Text event of an onFunction#() function, jjP/p will be set to the player who touched the Text event. Moreover, while onMain() fires once per gametick, onPlayer() fires once per local player per gametick, updating the referent of jjP/p each time. In other, non-player specific functions, jjP/p's referent may be unpredictable and should not be relied upon unless there is only one local player at all.

In some cases you'll want access to some player other than the one who triggered a function. For this, there are two global arrays: jjPlayers[32] and jjLocalPlayers[4]. While JJ2/AngelScript shouldn't actually crash if you try to access a player that doesn't exist in the game, it may not give you the most useful results, so the global properties jjPlayerCount and jjLocalPlayerCount should also be kept in mind. Additionally, jjPLAYER objects have boolean isActive and isLocal properties to help you figure out which jjPLAYER objects to affect with a given section of code.

(Of course, since AngelScript is predominantly local in its domain, the isLocal=false jjPLAYER objects are mostly only useful for reading values, not writing, and even then only a few of those values — xPos, yPos, currWeapon, and so forth — will actually be locally accurate. Trying to set, say, jumpStrength for a non-local jjPLAYER won't do you any good.)

For the most part, properties and methods of jjPLAYER objects are familiar from regular JJ2. The antiGrav, noclipMode, and noFire booleans are all new, but are only single properties and thus not too complicated. What merits discussion is the Player Timer, a new feature available in all game modes but Race (where it would interfere with the lap times). Put loosely, a Player Timer is a player-specific on-screen countdown which, once its time runs out, sets p/jjP to the player whom it belonged to and then calls a certain AngelScript function. The most important methods are timerStart() and timerFunction(), which respectively begin the Player Timer (and set how long it will last) and set the effect of the Player Timer running out. Explaining the Player Timer in detail is not the function of this document, however, so see plusTimerEx.j2l/.j2as for a fuller explanation and examples.

bool alreadyDoubleJumped
Whether it is currently possible for the player to double jump, assuming they're Spaz and currently in the air.
int ammo[WEAPON::Weapon]
int ammo[9]
How much ammo the player has of each ammo type. Possible constants appear in the appendix below, or you may use simple 1-indexed numbers instead (all values besides 1-9 will evaluate to WEAPON::CURRENT).
Note that JJ2+ prevents the use of weapons without corresponding +3/+15/powerup events in the level while in online servers. To remedy this, hide some such ammo-providing event somewhere in the level.
bool antiGrav
Whether the player falls up (true) or down (false).
(For the record, this mode is something of a work-in-progress. Plenty of events — notably objects that you stand on, like crates and swinging platforms — don't work very well with it yet. However, future revisions should be at least backwards compatible with what works already, so don't hold off on using it for that reason unless it truly can't do yet what you need it do.)
int ballTime
If greater than 0, how much longer (in ticks) the player will be tucked into a ball.
int boss
The object ID of the jjOBJ whose energy is shown in the boss health meter, or 0 if inapplicable.
More specifically, the boss health meter will show the energy of the jjOBJ as a percentage of its initial health as described in its entry in jjObjectPresets. If you create a Tuf Turtle enemy, give it 100 health, and assign a jjPLAYER's boss its object ID, JJ2 will still assume the Tuf Turtle started out at 4 health, not 100. On the other hand, if you write jjObjectPresets[OBJECT::TUFTURT].energy = 100; first, then the boss health meter will work as you might want it to.
const CHAR::Char charCurr
The player's current character (CHAR::JAZZ, CHAR::SPAZ, CHAR::LORI, CHAR::BIRD, or CHAR::FROG). This is a read-only value &mdash, because you should use morphTo or another related method to change it instead.
CHAR::Char charOrig
Which character the player began the level as (CHAR::JAZZ, CHAR::SPAZ, or CHAR::LORI), aka the character that the Revert Morph event switches them to.
int coins
How many coins the player has.
If you want to require the player to have a certain number of coins to do something, like with coin warps, consider using the more elaborate testForCoins method instead.
const int currTile
A shortcut value, always equalling xPos/32 + yPos/32*65536. Since both xPos and yPos are easily accessible properties, it really only makes sense to use currTile to compare against previous values of currTile, i.e. to see if the player has moved or not.
uint8 currWeapon
Which ammo type the player currently has selected. Possible constants appear in the appendix below, or you may use simple 1-indexed numbers instead (all values besides 1-9 will evaluate to WEAPON::CURRENT).
int direction
Which direction the player is facing.
int fastfire
The waiting time between shots, as decreased by Fastfire events or the JJFIRE cheat code. Starts out at 35 — half a second — and decreases to a minimum of 6 (from Fastfire events) or 1 (JJFIRE).
FLIGHT::Mode fly
Possible values are FLIGHT::NONE, FLIGHT::FLYCARROT, or FLIGHT::AIRBOARD. There is no support for copters or Cheshire2 events just yet.
int food
How much food the player has eaten.
Setting this to 100 will not cause a sugar rush. Use the startSugarRush method instead.
int8 frozen
0 if unfrozen; otherwise, constantly counts down towards 0.
int gems[GEM::Color]
How many gems the player has collected. Possible values of GEM::Color are GEM::RED, GEM::GREEN, GEM::BLUE, and GEM::PURPLE.
uint8 health
How many hearts the player has remaining. If you set this in an online server, all other players will be notified of the change.
int invincibility
How much longer the player will be invincible. (Does not work in servers.)
const bool isActive
Does this jjPLAYER object correspond to an actual player in the game, local or otherwise?
const bool isLocal
Is this jjPLAYER object controlled by this instance of JJ2?
float jumpSpeed
How high the player jumps. Defaults to -10.
uint8 lighting
The player's current level of ambient lighting, as affected by the Set Light and Reset Light events.
int lives
In single player or cooperative mode, how many lives the player has remaining.
const int localPlayerID
Which local player the player is, in case of splitscreen. 0-3.
bool noclipMode
Whether the player is currently in Noclip Mode, as caused by Sucker Tube events with the "BecomeNoclip" parameter set to 1. Setting this to true could be dangerous if the level design is not prepared for it.
bool noFire
Whether the player is currently allowed to shoot bullets. Hides the current weapon/ammunition display while true.
const int platform
The object ID of the object the player is currently standing on, or 0 if inapplicable.
const int playerID
In online play, which number the player is in the server's list of players. 0-31.
bool powerup[WEAPON::Weapon]
bool powerup[9]
Whether each ammo type is powered-up or not. Possible constants appear in the appendix below, or you may use simple 1-indexed numbers instead (all values besides 1-9 will evaluate to WEAPON::CURRENT).
Note that JJ2+ prevents the use of powered-up weapons without corresponding powerup events in the level while in online servers. To remedy this, hide powerup events somewhere in the level.
const bool running
Is the player currently running? Detects the run key, capslock (if there is only one local player), and the /run <on|off> command.
int score
The player's current score. JJ2 only increments this in multiples of 50 (or 10 if you count the unpatched Butterfly enemy), but that's up to you.
int shieldTime
How much longer (in ticks) the player's shield will last, or 0 if the player doesn't have a shield.
int shieldType
Which shield the player currently has, assuming the player has a shield at all.
const bool teamRed
True if the player's on the red team, false if the player's on the blue team (or not in a team game).
bool timerPersists
Should dying disable the Player Timer (false) or have no effect on it (true)?
const TIMER::State timerState
The current state of the Player Timer (TIMER::STOPPED, TIMER::STARTED, or TIMER::PAUSED), for comparisons only. Use the corresponding timerStart, timerStop, timerPause, and timerResume methods to set this instead.
int timerTime
How many ticks are left on the Player Timer.
const int warpID
If this number is higher than 0, the player is currently warping, and it will equal the ID of the Warp event plus one, a range of 1-256.
It is often wise to make sure this property equals 0 before calling a warp method, lest the player be locked into a constant loop of beginning to warp but never finishing it. Something like if (conditionsForWarping && p.warpID == 0) p.warpToID(25);. Performing this check is however unnecessary for fast warps, or warps triggered by Text events, since that code is only called when the player first enters the tile.
float xAcc
Horizontal acceleration in pixels, positive or negative.
float xOrg
If this or yOrg are non-zero, where the player should respawn after death.
float xPos
Horizontal location in pixels.
float xSpeed
Horizontal speed in pixels, positive or negative.
float yAcc
Vertical acceleration in pixels, positive or negative.
float yOrg
If this or xOrg are non-zero, where the player should respawn after death.
float yPos
Vertical location in pixels.
float ySpeed
Vertical speed in pixels, positive or negative.
void activateBoss(bool activate = true)
Activates all bosses and disables the player's sugar rush if applicable. Unlike the Activate Boss event, does not change the music track. (Use jjMusicLoad for that instead.)
Setting activate to false will attempt to deactivate bosses, but this mostly only results in the boss health meter going away. The jjPLAYER object's boss is left unchanged unless you change it manually, and bosses do not stop moving around.
void cameraFreeze(float xPixel, float yPixel, bool centered, bool instant)
Fixes the camera in place, like when encountering a Robot Boss, until the corresponding cameraUnfreeze method is called. If instant is left false, the camera will take roughly half a second to scroll to its target. If centered is left false, the camera will position itself so that xPixel,yPixel is in the top left corner of the screen; otherwise, that position will be in the very center.
void cameraUnfreeze()
If cameraFreeze has been called, undoes the effect and lets the camera freely follow the player once again.
int fireBullet(WEAPON::Weapon gun = WEAPON::CURRENT, bool depleteAmmo = true, bool requireAmmo = true, DIRECTION::Dir direction = DIRECTION::CURRENT)
int fireBullet(uint8 gun, bool depleteAmmo = true, bool requireAmmo = true, DIRECTION::Dir direction = DIRECTION::CURRENT)
Causes the player to fire, using either the specified ammo type or the current one. The return value will be the object ID of the new bullet, unless the weapon is RF or Pepper Spray. This action is visible for all players in an online server.
Possible gun constants may be found in the appendix at the bottom of the page, or you may use simple 1-indexed numbers instead (all values besides 1-9 will evaluate to WEAPON::CURRENT).
If depleteAmmo is false, the method will not affect how much of the ammo type the player has remaining.
If requireAmmo is false, the player can fire a bullet of that type even if they don't have any ammo of that type.
Possible values for direction are DIRECTION::RIGHT, DIRECTION::LEFT, DIRECTION::UP, and DIRECTION::CURRENT.
void freeze(bool frozen = true)
Freezes the player for the same length of time as the Freeze Enemies pickup, or unfreezes the player if frozen is set to false.
void kill()
Kills the player instantly.
void limitXScroll(uint16 left, uint16 width)
Works like a Limit X Scroll event with the corresponding Left and Width parameters. Remember that these are measured in tiles, not pixels.
CHAR::Char morph(bool rabbitsOnly = false, bool morphEffect = true)
Cycles the player's character to the next on the list, just like the JJMORPH cheat: Jazz-Spaz-(Lori-)Bird-Frog. Or if rabbitsOnly is true, skips bird and frog and acts like a morph monitor instead. Returns the player's new character: CHAR::JAZZ, CHAR::SPAZ, CHAR::LORI, CHAR::BIRD, or CHAR::FROG.
CHAR::Char morphTo(CHAR::Char charNew, bool morphEffect = true)
Sets the player's character to charNew, possible values CHAR::JAZZ, CHAR::SPAZ, CHAR::LORI (in TSF), CHAR::BIRD, or CHAR::FROG.
bool offsetPosition(int xPixels, int yPixels)
Instantly moves the player xPixels pixels to the right and yPixels pixels down. The camera instantly readjusts itself to follow, as does the glowing trace following the player while running. The best way of creating seemlessly looping levels.
CHAR::Char revertMorph(bool morphEffect = true)
Reverts the player to the character they were when they began the level, just like the Revert Morph event.
void showText(uint8 textID, uint8 offset)
Works like a Text event with the corresponding TextID and Offset parameters.
void showText(string text)
Displays text on the player's screen like from a Text event.
bool startSugarRush(int time = 1400)
Gives the player a sugar rush lasting time ticks, unless bosses have been activated already, in which case the method returns false.
bool testForCoins(int numberOfCoins)
If the player has at least numberOfCoins coins, depletes their coins by numberOfCoins and returns true. Otherwise displays a warning onscreen that they need more coins to continue. Basically the same as a coin warp event, but you get to choose the result.
bool testForGems(int numberOfGems, GEM::Color type)
If the player has at least numberOfGems type-colored gems, depletes their type gems by numberOfGems and returns true. Otherwise displays a warning onscreen that they need more gems to continue. Basically the same as a coin warp event, but you get to choose the result, and it's for gems instead of coins.
Possible values of type are GEM::RED, GEM::GREEN, GEM::BLUE, and GEM::PURPLE.
void timerFunction(string functionName)
When the Player Timer hits zero without being stopped artifically, the AngelScript function void functionName() will be called, and p/jjP will equal the player whose Player Timer just expired. This defaults to "onPlayerTimerEnd", aka void onPlayerTimerEnd(). It is up to you to define this function and decide what should happen to the player.
TIMER::State timerPause()
Pauses the Player Timer and returns TIMER::PAUSED.
TIMER::State timerResume()
Resumes the Player Timer and returns TIMER::STARTED.
TIMER::State timerStart(int ticks, bool startPaused = false)
Begins the Player Timer (and optionally pauses it) with ticks ticks remaining on the clock. Returns TIMER::STARTED or TIMER::PAUSED, depending.
TIMER::State timerStop()
Stops the Player Timer and returns TIMER::STOPPED.
bool warpToID(uint8 warpID, bool fast = false)
Warps the player to a Warp Target event with the specified Warp ID, instantly if fast is true or using the standard warp effect if fast is false.
bool warpToTile(int int xTile, int yTile, bool fast = false)
Warps the player to the specified tile, instantly if fast is true or using the standard warp effect if fast is false.

class jjOBJ

Objects — enemies, pickups, platforms, light sources, and so forth — are one of the most inescapably complex parts of the JJ2 engine. It would not have done to release an AngelScript-enabled JJ2+ with no way of editing objects, but nor was it possible to include right away all the tools needed to make it anything close to straightforward. So this is a compromise: some little control, and some little guidance. Expect to see significant improvements in this area in subsequent JJ2+ releases, but for now, here's what you've got to work with.

The most important global property is jjObjects[], a list of all the potential objects in the game. To obtain a jjOBJ to play with, you'll need to specify one of the entries in jjObjects[], e.g. jjOBJ@ o = jjObjects[1]. The global property jjObjectCount is useful for looping through the contents of jjObjects[]. When performing such a loop, it is important to test that a given jjOBJ has a true isActive property, since deleted objects may leave traces of themselves in memory and these traces can only be distinguished from currently-extant objects using isActive. To narrow your results, comparing the eventID class to specific OBJECT::Object constants is also useful, e.g.

jjOBJ@ o;
for (int i = 1; i < jjObjectCount; i++)
{
  @o = jjObjects[i];
  if (o.isActive && o.eventID == OBJECT::NORMTURTLE)
  {
    o.state = STATE::KILL;
  }
}

Besides a loop invoking jjObjectCount, object IDs can also be obtained through the jjPLAYER property platform, which gives the ID of the object the player is standing on (if any), the jjPLAYER property boss, which gives the ID of the object whose health is displayed in the boss health meter on that player's screen (if any), and the jjOBJ property creator, which in some cases refers back to another object which created that one. Usually creator equals 0, but occasionally — for example, enemy bullets or objects created by generators — it will point to an object, though you should still remember to check isActive to make sure the object's creator hasn't already been destroyed. It's also important to check creatorType whenever one checks creator, since if it equals CREATOR::PLAYER, then creator will point to a jjPLAYER in jjPlayers instead of a jjOBJ in jjObjects.

The final reliable way to obtain an object ID is the global function jjAddObject(OBJECT::Object eventID, float xPixel, float yPixel, uint16 creatorID, CREATOR::Type creatorType), which returns the ID of the object it adds so that you can then look it up in jjObjects and set some of its properties. The last two parameters can be — and usually are — left out, but you're free to do as you like.

As ever, note that AngelScript's scope is all but exclusively the JJ2 copy on your computer, even if you're in an online server, and jjAddObject and the various jjOBJ properties are no exception to this. If one player fires a slice of AngelScript that creates a morph monitor, the other players will not see any morph monitor until and unless they too fire the same slice of code. Likewise, changing the xPos and yPos of a pinball bumper will only be recognized by the local players, not by anyone else in the server. These details are of course of no concern for single player levels, but should be kept in mind for multiplayer design.

Certain of these properties — curFrame in particular — will constantly be set by the object itself, so trying to change them manually will have little effect. Others, such as state or lightType, will have immediate and possibly enduring effects. There are also a significant number of properties whose function (if any) varies from object (i.e. eventID) to object; these should be better explained in future iterations of JJ2+, but you're welcome to experiment in the meantime.

Finally: there are also nearly 256 proto-objects stored in the global array jjOBJ objectPresets[256]. These do not correspond to objects currently active in the game, but are instead the value-collection prototypes from which all in-game objects are initially derived. Whenever jjAddObject is called using, say, OBJECT::GREENGEM, the created object will get its initial values for points, curAnim, var[0], and more from jjObjectPresets[OBJECT::GREENGEM]. The contents of jjObjectPresets are reset every level, so it is totally safe for you to decide that, e.g., you'd really rather if all Skeleton enemies were lightning-fast and took nineteen hits to destroy instead of three (jjObjectPresets[OBJECT::SKELETON].energy = 19; jjObjectPresets[OBJECT::SKELETON].xSpeed = 5;).

int age
How long since the object was created.
int animSpeed
How fast the object animates. Not always used, since animations have their own internal framerate values.
This property is also used to store the amount of damage a bullet does to enemies, e.g. 1 for normal blaster, 2 for normal seekers, or 3 for certain shield bullets.
int counter
A general purpose property, usually used for counting up or down to some future event.
uint8 counterEnd
A general purpose property, most commonly used for how long a bullet will exist before exploding.
int creator
Returns the object ID or player ID of the object's creator, depending.
const CREATOR::Type creatorType
Equals CREATOR::OBJECT if the object was created by another object, CREATOR::PLAYER if it was created by a player, or CREATOR::LEVEL if it was added directly from the event map.
If the object was created by a Generator object specifically, then creatorType will equal CREATOR::LEVEL, but creator will equal the object ID of that Generator object, rather than 0.
int16 curAnim
The current animation the object takes its frames from. While it is possible to set this property manually, in practice you should use the determineCurAnim method instead.
uint curFrame
The overall current frame displayed to the screen to represent this object, taking into account both curAnim and frameID. While it is possible to set this property manually, in practice you should use the determineCurFrame method instead.
int8 direction
Which way the object is facing. Generally, direction >= 0 is right and < 0 is left.
uint8 doesHurt
Presumably related to what happens when the player touches the object.
int8 energy
How many more shots the object can take before being destroyed.
uint8 eventID
e.g. 158 for a peach, 43 for a bomb, 243 for an airboard, 1 for a blaster bullet, and so on. Is a uint8 for maximum flexibility, but you should probably set/compare it to OBJECT::Object constants instead most of the time, if for no other reason than readability.
While this value is not strictly constant/read-only, changing it can lead to unpredictable and undesirable effects, since this is the only truly reliable way of knowing what kind of object a given jjOBJ really is, and JJ2 queries it very frequently. The effects can vary from a food pickup playing the wrong sound effect when collected to, say, a red spring simply not working at all when touched. You have been warned.
int8 frameID
The object's current frame within a single animation set, e.g. which direction the Tube Turtle faces while it rotates in place.
uint8 freeze
0 if the object is unfrozen, otherwise counts down to 0.
const bool isActive
Does this jjOBJ correspond to a real object, or is it just the abandoned memory of one?
uint8 justHit
Whether object was shot recently.
int16 killAnim
Which animation the object uses while being destroyed.
int8 light
The intensity of the light produced by the object.
LIGHT::Type lightType
The type of light produced by the object. Possible values are NONE, NORMAL, POINT, POINT2, FLICKER, BRIGHT, LASER, RING, and RING2.
STATE::State oldState
If the object is frozen, what state it was in before it was frozen. Possible constants are listed in the appendix at the end of this file.
uint16 points
How many points a player will gain for destroying the object.
int8 noHit
This property has something to do with how the object interacts with players and bullets, but we don't know all the details.
uint8 objType
This property controls, to a point, how the object is handled by JJ2, but we don't know all the details.
int special
A general-purpose variable, means different things for different objects.
STATE::State state
The current state of the state machine that is the object. Possible constants are listed in the appendix at the end of this file.
int var[11]
A series of general-purpose variables, used for different things by different objects. In general, earlier values are more likely to be used than later ones.
float xAcc
Horizontal acceleration in pixels, positive or negative.
float xOrg
Original horizontal location in pixels.
float xPos
Current horizontal location in pixels.
float xSpeed
Horizontal speed in pixels, positive or negative.
float yAcc
Vertical acceleration in pixels, positive or negative.
float yPos
Current vertical location in pixels.
float yOrg
Original vertical location in pixels.
float ySpeed
Vertical speed in pixels, positive or negative.
int16 determineCurAnim(uint8 setID, uint8 animation, bool change = true)
int16 determineCurAnim(ANIM::Set setID, uint8 animation, bool change = true)
Determines the value of the curAnim corresponding to Set ID setID and Animation animation as seen in Jazz Sprite Dynamite. (0-indexed.) If change is specified as false, this serves as essentially a static method, calculating the proper curAnim value but not actually setting this particular jjOBJ's curAnim to that value.
You are allowed to use a simple uint8 to specify the setID, but an ANIM::Set constant is strongly recommended, since the values for certain sets differ between 1.23 and 1.24. The full list of constants can be found in the appendix at the bottom of this file.
uint determineCurFrame(bool change = true)
Determines the value of the curFrame corresponding to this jjOBJ's current curAnim and frameID values. If change is specified as false, this calculates the proper curFrame value but does not actually set this particular jjOBJ's curFrame to that value. You are only so likely to get much use from this method, though, since most objects set curFrame constantly on their own.

Global Properties

Note: to be convenient, the arrays of layer properties are all 1-indexed. For example, the X speed of layer 4 (the sprite layer) is jjLayerXSpeed[4] and not jjLayerXSpeed[3].

const jjPAL jjBackupPalette
The tileset's original palette. See the jjPAL documentation above for further details.
int jjEcho
The current degree of echo, as set by the "Echo" event.
bool jjEnabledASFunctions[256]
Usually all true. When a Text event is touched with AngelScript=1,Vanish=1, the jjEnabledASFunctions[#] bool for that Text event's TextID value will be set to false and the corresponding onFunction# will be uncallable by other Text events until the bool is set to true again.
const int jjFPS
The current frames per second rate, as viewable by pressing F9 twice.
const int jjGameTicks
How long the game has been actively running, at a rate of 70 ticks per second.
const bool jjIsAdmin
Whether the current game executable is logged in as a Remote Admin in the current online server.
const bool jjIsServer
Whether the current game executable is hosting an online server.
const bool jjIsTSF
Whether the current game executable is 1.23+ or 1.24+. Useful for Lori, XMas enemies, etc.
bool jjLayerHasTiles[8]
Simply, whether JJ2 should draw the layer or not. Setting this to true for a layer that does not actually have any tiles may have unpredictable consequences; it is best to use this solely to hide layers that really do have tiles.
const int jjLayerHeight[8]
The height of each layer, in tiles.
bool jjLayerLimitVisibleRegion[8]
Assuming the layer is not vertically tiled, whether the layer should be vertically offset some pixels downward, the exact value depending on the current resolution.
bool jjLayerTileHeight[8]
Whether each layer should be vertically tiled, as seen in the JCS Layer Properties window.
bool jjLayerTileWidth[8]
Whether each layer should be horizontally tiled, as seen in the JCS Layer Properties window.
Setting this to true for a layer that is not saved with Tile Width checked in JCS may lead to unpredictable effects if the layer's width is not a multiple of 4. If you wish to turn it on partway through the level, it is best to check Tile Width in JCS and then disable it in onLevelLoad.
const int jjLayerWidth[8]
The width of each layer, in tiles.
const int jjLayerWidthReal[8]
If a layer has Tile Width checked, the lowest common multiple of its width in tiles and 4. Otherwise, its width in tiles.
const int jjLayerWidthRounded[8]
The lowest multiple of four greater or equal to each layer's width in tiles.
float jjLayerXAutoSpeed[8]
The X auto speed of each layer, as seen in the JCS Layer Properties window.
float jjLayerXSpeed[8]
The X speed of each layer, as seen in the JCS Layer Properties window.
float jjLayerYAutoSpeed[8]
The Y auto speed of each layer, as seen in the JCS Layer Properties window.
float jjLayerYSpeed[8]
The Y speed of each layer, as seen in the JCS Layer Properties window.
const jjPLAYER jjLocalPlayers[4]
The local players.
const int jjLocalPlayerCount
The number of local players.
const int jjMaxHealth
The most health a player can ever have, as set by the /maxhealth command. Defaults to 5 in Single Player/Cooperative/Battle, or 3 in Capture The Flag.
bool jjMusicActive
Mute Music, as seen in the Sound & Music Properties window.
int jjMusicVolume
Music Volume, as seen in the Sound & Music Properties window.
const int jjObjectCount
The number of objects currently in memory. Useful for looping through jjObjects.
jjOBJ jjObjectPresets[256]
The templates from which each object is built. Tends to contain default xSpeed, ySpeed, points, curAnim, and so on. Make changes here in onLevelLoad() for maximum efficiency.
jjOBJ jjObjects[]
All the objects currently in memory.
jjPLAYER jjP
The current player. See the jjPLAYER documentation above for further details.
jjPAL jjPalette
The current palette. See the jjPAL documentation above for further details.
const int jjPlayerCount
The total number of players in the game. Potentially distinct from jjLocalPlayerCount when in online servers. Note that using this as the maximum value for a for loop may be impractical, since player numbers need not be consecutive.
const jjPLAYER jjPlayers[32]
All the players in the game, local or otherwise.
const int jjRenderFrame
How long the game has been running. Unlike jjGameTicks, jjRenderFrame updates when the game is paused. This is the value used for drawing layers with automatic x/y speeds.
bool jjSoundEnabled
Whether JJ2 should produce any form of audio at all.
bool jjSoundFXActive
Mute Sound, as seen in the Sound & Music Properties window.
int jjSoundFXVolume
Sound Volume, as seen in the Sound & Music Properties window.
const int jjStartHealth
How much health a player starts with, as set by the /starthealth command. Defaults to 5 in Single Player/Cooperative/Battle, or 3 in Capture The Flag.
bool jjTriggers[32]
The triggers, as set by the Trigger Zone and Trigger Crate events.
bool jjWarpsTransmuteCoins
If set to false, using a coin warp in Single Player mode will not turn all remaining coins into red and green gems.
float jjWaterChangeSpeed
How fast water moves up or down when the water level is set (by event or function) with the "Instant" parameter set to false. Defaults to 1.
const float jjWaterLevel
How high the water currently is, in pixels.
This is a constant value; use the jjSetWaterLevel helper function instead for changing it.
WATERLIGHT::wl jjWaterLighting
The current way that water and ambient lighting interact in the level. (Ambient lighting varies by local player and as such is a jjPLAYER property.) The following constants are permissible values:
  • WATERLIGHT::NONE: The default. When water is activate, the level will display at lighting 100, regardless of the current settings.
  • WATERLIGHT::GLOBAL: The entire level will be lit according to the current ambient lighting settings, both above and below the water line.
  • WATERLIGHT::LAGUNICUS: The current ambient lighting setting is ignored. Above the water, the level will display at lighting 100. Below the water, the level will display darker and darker depending on how far below the water line the player is.
const float jjWaterTarget
The height the water is moving towards, in pixels. If the water level is set (by event or function) with the "Instant" parameter set to false, there will be a period in which jjWaterLevel and jjWaterTarget are two distinct values.
This is a constant value; use the jjSetWaterLevel helper function instead for changing it.
jjPLAYER p
The current player; an alias of jjP, and the only property not to begin with the jj prefix, provided solely for convenience value. See the jjPLAYER documentation above for further details.

Global Functions

int jjAddObject(OBJECT::Object eventID, float xPixel, float yPixel)
int jjAddObject(OBJECT::Object eventID, float xPixel, float yPixel, uint16 creatorID, CREATOR::Type creatorType)
Adds an object of type eventID at xOrg xPixel and yOrg yPixel. Possible values for creatorType are CREATOR::OBJECT, CREATOR::LEVEL, and CREATOR::PLAYER. Possible values for eventID can be found in the appendix at the bottom of the page.
Returns the object ID of the new object, or 0 if the function fails for whatever reason.
void jjAlert(string text)
Writes text to the chatlogger window, and also displays it ingame for the local player.
void jjChat(string text)
In online play, sends text to the server as a line of chat. If text is a command (e.g. "/spectate on" or "/ready"), it will be interpreted as such to the extent that the local player is allowed to use that command in the server.
In offline play, JJ2+ will try to parse text as a command but will not display it as chat because there is no chat in offline mode. That said, few commands have any effect offline at all.
float jjCos(uint in)
Returns the cosine of in with a range of 0.0-1.0 and a domain of 0-1023. Numbers outside the domain will be seemlessly moduloed.
void jjDebug(string text)
Writes text to the chatlogger window (but not ingame), but only if [General]AngelscriptDebug equals True in plus.ini.
void jjEnableEachASFunction()
Resets all 256 bools in jjEnabledASFunctions to true.
int jjEventGet(uint16 xTile, uint16 yTile)
Gets the Event ID at tile xTile,yTile, as seen in JCS.ini. This number can also be compared to the OBJECT or AREA constants listed in the appendix at the bottom of this file.
void jjEventSet(uint16 xTile, uint16 yTile, uint8 newEventID)
void jjEventSet(uint16 xTile, uint16 yTile, OBJECT::Object newEventID)
void jjEventSet(uint16 xTile, uint16 yTile, AREA::Area newEventID)
Sets the event at tile xTile,yTile to newEventID. Possible OBJECT or AREA constants are listed in the appendix at the bottom of this file.
Caution: this is a permanent change and will subsist even after death in offline play.
bool jjMusicLoad(string filename, bool forceReload = false)
Loads and starts playing a new music file, of any type supported by JJ2+. Returns false if the file cannot be found in either the main game folder or the cache subfolder, or if the specified music file is already playing and forceReload is false.
void jjMusicPause()
Pauses the current music track. May not work with .mp3 files.
void jjMusicPlay()
(Re)starts the current music track.
void jjMusicResume()
Resumes the current music track, once paused. May not work with .mp3 files.
void jjMusicStop()
Stops the current music track.
void jjNxt(string& filename = "", bool warp = false, bool fast = false)
Ends the level and skips to the next one, or to filename if specified. Only works in Single Player and Cooperative.
int jjParameterGet(uint16 xTile, uint16 yTile, uint8 offset, int8 length)
Gets one of the parameters at tile xTile,yTile. Follow JCS.ini's lead in figuring out how to write the offset and length parameters.
length is the simplest: use the exact same formatting JCS.ini does. To get the speed of a belt event, for instance, length should be -8. To get the number of blue gems in a gem crate, length should be 4. And so on.
offset is calculated by adding the absolute values of every parameter on the tile prior to the one you want. The first (bottommost) parameter will always have offset 0. To get the parameter "Blue" in Gem Crate, offset should be 8 (4+4). To get the Y-Speed of a Rotating Rock, offset should be 12 (8+abs(-4)). And so on.
Set length to 2 and offset to -4 to get the difficulty of an event (normal, easy, hard, multiplayer-only).
void jjParameterSet(uint16 xTile, uint16 yTile, uint8 offset, int8 length, int newValue)
Sets one of the parameters at tile xTile,yTile. length and offset work exactly as they do for jjParameterGet; the only change is newValue, which should be a valid number for the length setting. Trying to assign a negative number to an unsigned length parameter doesn't really make sense, for example, nor can you reasonably assign a newValue of 100 to a length of 3.
Note that this is not quite as powerful as it may seem, since many (most?) objects read and process their parameters into memory when they are first created, rather than continually reading them again and again as the game continues. The function will however work fine for zones that affect the player, such as Warp or Sucker Tube or Wind, and it will also successfully set parameters for any new objects created after the function is called.
Caution: this is a permanent change and will subsist even after death in offline play.
void jjPrint(string text)
Writes text to the chatlogger window but does not display it ingame.
uint jjRandom()
Provides a random number.
float jjResetWaterGradient()
Restores 16-bit water to its natural colors.
void jjSample(float xPixel, float yPixel, SOUND::Sample sample, int volume = 63, int frequency = 0)
Plays a sound from anims.j2a at pixel xPixel, yPixel. Possible values for sample are listed in the appendix at the bottom of this file.
volume ranges from 1-63, and 0 will default to 63. Higher values of frequency result in higher frequencies, or leaving it at 0 will use the sample's unique default frequency.
void jjSamplePriority(SOUND::Sample sample)
Plays a sound from anims.j2a, no matter what's going on. This is the function used to play the sugar rush jingle. Possible values for sample are listed in the appendix at the bottom of this file.
void jjSetFadeColors(uint8 red, uint8 green, uint8 blue)
void jjSetFadeColors(uint8 paletteColorID = 207)
Sets the fade colors of the level's textured background, as seen in the Layer properties window for layer 8 in JCS. Has no effect if there is no textured background.
A simpler one (or zero!) parameter version of the function also exists to set the fade colors to the same RGB values as used by one of the entries in jjPalette. This defaults to 207, which is the last color of the most common textured background gradient and thus, not infrequently, the fade color used in 8-bit color.
float jjSetWaterGradient(uint8 red1, uint8 green1, uint8 blue1, uint8 red2, uint8 green2, uint8 blue2)
float jjSetWaterGradient()
Changes the colors used by water in 16-bit color. If no parameters are included, the gradient will be generated from palette entries 176 and 207 instead, the most typical textured background colors (and most of the colors used by 8-bit water).
float jjSetWaterLevel(float yPixel, bool instant)
Sets jjWaterTarget to yPixel. If instant is true, jjWaterLevel will also be set to yPixel; otherwise, it will move slowly up or down from its current height until it reaches its new target.
Caution: this function is not identical to the Water Level event in JCS. The event measures in tiles, but this function measures in pixels. Multiply by thirty-two to get the same effect.
float jjSin(uint in)
Returns the sine of in with a range of 0.0-1.0 and a domain of 0-1023. Numbers outside the domain will be seemlessly moduloed. This is the sine function used by JJ2 for spinning platforms and the like.
bool jjSwitchTrigger(uint8 id)
Toggles jjTriggers[id] from true to false, or vice versa, like the "switch" parameter on the Trigger Zone and Trigger Crate events.
uint16 jjTileGet(uint8 layer, int xTile, int yTile)
Returns the current tile at tile xTile,yTile in layer layer. If the tile is an animated tile, this function will return the tile ID for that animated tile instead of the current frame.
Caution: the numbers produced by this function for flipped and/or animated tiles may not be the same in later JJ2+ releases. You should not compare numbers produced by this function except to other numbers produced by this same function.
uint16 jjTileSet(uint8 layer, int xTile, int yTile, uint16 newTile)
Sets the current tile at tile xTile,yTile in layer layer to be newTile. The same change will be applied to all instances of the same four-tile word that appear elsewhere in the level.
Caution: the numbers used for flipped and/or animated tiles may not be the same in later JJ2+ releases. If you wish to use this function to place a flipped and/or animated tile, obtain the number to use directly from jjTileGet.
void jjTriggerRock(uint8 id)
Activates all Rotating Rock events with the "RockID" parameter set to id, exactly like the Trigger Rock event.
void jjUpdateTexturedBG()
If you've used jjTileSet on layer 8, and layer 8 is a textured background, you'll need to call this function to ensure that the changes you've made are visible.

Appendix of Constants

WEAPON::Weapon

Weapons are named pretty intuitively, using the common names for each one instead of necessarily the JCS names or official manual names. The exceptions are Pepper Spray and Electro-Blaster, which are simply GUN8 and GUN9 (a la JCS) to allow for situations in which those constants refer to the Fireball and Blade Guns instead.

STATE::State

These are the different modes, or states, that a jjOBJ object can be in at any given time. The important ones are START, which is the initial state of an object that's just been created; KILL or sometimes DONE, for when an object gets destroyed; DEACTIVATE, for when an object passes out of memory in single player mode; EXPLODE, for when an enemy or something explodes into tiny particles; and FREEZE, for when an object gets shot with ice. The rest are largely arbitrary.

AREA::Area

Indented constants are alternate aliases for the non-indented constants directly above them. They evaluate to exactly the same results — the only difference between, say, AREA::JAZZLEVELSTART and AREA::JAZZSTART is which you'd rather type.

OBJECT::Object

Indented constants are alternate aliases for the non-indented constants directly above them. They evaluate to exactly the same results — the only difference between, say, OBJECT::SAVEPOST and OBJECT::CHECKPOINT is which you'd rather type.

SOUND::Sample

Preview samples at the JJ2 Soundboard. Naturally, certain samples are only available in TSF.

ANIM::Set

Values used for the first parameter of the jjOBJ method determineCurAnim. These are in the same order as they appear in Jazz Sprite Dynamite (although certain sets obviously do not appear in 1.23 anims.j2a), so it should be totally straightforward to match the names to the numbers.

Thanks

AngelScript is written and maintained by Andreas Jönsson of AngelCode.com. The JJ2+ developers owe him a great deal of thanks.