PDA

View Full Version : JJ2 AngelScript Presets!


FawFul
Feb 1, 2013, 04:12 AM
Hello everyone, I'm starting this official thread to collect some easy preset codes for jj2's AngelScript (http://www.jazz2online.com/jj2plus/plus-angelscript.html) so people won't have to make it over and over. It's also a tool to help new people understand seperately without being overwhelmed by really big scripts. only post basic preset scripts please, without much addition. for example, my script about giving a random power up to random players. I'm not adding all kinds of gimmicks like 3% chance of shield and fastfire, unlimited ammo on certain weapons and so on: keep it basic / editable.

Everyone is free to post Angelscripts here that quoted. I will try to compile them in this newspost. I made up a few categories myself (name more if you like). Also make sure your code works well. Text covered in red will be the variables you change



Weapon and firing related

Full Ammo randomizer #1 - Cooba (works multiple times)

int num;

void onFunction0() {
num = (jjRandom()%9) + 1;
p.powerup[num] = true;
p.currWeapon = num;
if (num > 1) p.ammo[num] = 50;
switch (num) {
case 1: p.showText("§1#@@@@@@||||||||B|||||||L|||||||A|||||||S||||||| T|||||||E|||||||R|||||||!"); break;
case 2: p.showText("§1#@@@@@@||||B||||O||U||||N||C||||E||R||||!"); break;
case 3: p.showText("§1#@@@@@@||||I|||C|||E|||!"); break;
case 4: p.showText("§1#@@@@@@||||S||||||||E||||||EK||||||ER|||||||!"); break;
case 5: p.showText("§1#@@@@@@|||R|||||||F|||||||!"); break;
case 6: p.showText("§1#@@@@@@||||T||||||OA||||||ST||||||ER||||||!"); break;
case 7: p.showText("§1#@@@@@@|||T|N|||||T|!"); break;
case 8: p.showText("§1#@@@@@@|||||P|E|||||P|P|||||E|R|||||! |||||||o||r ||||F|I|||||R|E|||||B|A|||||L|L|||||!"); break;
case 9: p.showText("§1#@@@@@@|||||E|||||||L|||||||E|||||||C|||||||T|| |||||R|||||||O |||||||B|||||||L|||||||A|||||||S|||||||T|||||||E|| |||||R|||||||!"); break;
}
}


Full Ammo randomizer #2 - FawFuL (works one time till death)

void onFunction0() {
if (p.health != 0) {
switch(jjRandom()%9) {
case 0: p.powerup[1] = true;
p.showText("§1#@@@@@@||||||||B|||||||L|||||||A|||||||S||||||| T|||||||E|||||||R|||||||!");
p.currWeapon = WEAPON::BLASTER; break;
case 1: p.ammo[2]=50;
p.powerup[2] = true;
p.showText("§1#@@@@@@||||B||||O||U||||N||C||||E||R||||!");
p.currWeapon = WEAPON::BOUNCER; break;
case 2: p.ammo[3]=50;
p.powerup[3] = true;
p.showText("§1#@@@@@@||||I|||C|||E|||!");
p.currWeapon = WEAPON::ICE; break;
case 3: p.ammo[4]=50;
p.powerup[4] = true;
p.showText("§1#@@@@@@||||S||||||||E||||||EK||||||ER||||||S!");
p.currWeapon = WEAPON::SEEKER; break;
case 4: p.ammo[5]=50;
p.powerup[5] = true;
p.showText("§1#@@@@@@|||R|||||||F|||||||!");
p.currWeapon = WEAPON::RF; break;
case 5: p.ammo[6]=50;
p.powerup[6] = true;
p.showText("§1#@@@@@@||||T||||||OA||||||ST||||||ER||||||!");
p.currWeapon = WEAPON::TOASTER; break;
case 6: p.ammo[7]=50;
p.showText("§1#@@@@@@|||T|N|||||T|!");
p.currWeapon = WEAPON::TNT; break;
case 7: p.ammo[8]=50;
p.powerup[8] = true;
p.showText("§1#@@@@@@|||||P|E|||||P|P|||||E|R|||||! |||||||o||r ||||F|I|||||R|E|||||B|A|||||L|L|||||!");
p.currWeapon = WEAPON::GUN8; break;
case 8: p.ammo[9]=50;
p.powerup[9] = true;
p.showText("§1#@@@@@@|||||E|||||||L|||||||E|||||||C|||||||T|| |||||R|||||||O |||||||B|||||||L|||||||A|||||||S|||||||T|||||||E|| |||||R|||||||!");
p.currWeapon = WEAPON::GUN9; break;
}
}
}
}

void onPlayer() {
if (p.health == 0) jjEnabledASFunctions[TextID Variable] = true; //Unvanishes Textstring 0, Works again upon respawning
}



Object related
-

Animation related
-

Sound related
-

Pallette and Light related

Day and Night cycle - Sir Elementaler

const uint dnCYCLELENGTH=700; // Day Length.
const uint dnEVERYXTICKS=4; //the amount ticks the pallette refreshes it's colours.
const uint dnINITIALTICKS=256; //determines the initial time of the day. 0 means dawn, 256 means noon, 512 means dusk, 768 means midnight and 1024 means dawn again. All values allowed.
const string dnNIGHTTILESET="Carrot1N.j2t"; // the name of the tileset whose palette should be used in midnight.
jjPAL PaletteNight;

void onLevelLoad()
{
PaletteNight.load(dnNIGHTTILESET);
}

void onMain()
{
if(jjGameTicks%dnEVERYXTICKS==0)
{
jjPalette=PaletteNight;
jjPalette.copyFrom(2,252,2,jjBackupPalette,(jjSin( 1024*jjGameTicks/dnCYCLELENGTH+dnINITIALTICKS)+1)/2);
jjPalette.apply();
}
}




Layer (speed) related
-

SP and RPG (story) related
-

Physics and Character changes related
-

Area & Trigger related

Punish campers - Grytolle

/** script settings **/
const uint checkCampInterval=80; //how often to check for camping (gameticks)
/*********************/

/** level settings: define camp areas **/
array>> campArea = {
/* A camparea is a rectangle referred to by its top left and bottom right corner
x,y -----------
| |
| |
----------- a,b */
// camparea(x,y) camparea(a,b) allowed camp time(gameticks)
{{29,12}, {40,12}, {500}}, //camparea #0: on top of seek pu
{{64,05}, {101,19}, {500}} //camparea #1: the rf area
};
//it doesn't seem like you can have mixed arrays in AS
//so we just put the strings in a separatr array
array campAreaName = {
"above seeks", //camparea #0
"in the rf area" //camparea #1
};
/******** end of level settings ********/

/** script globals **/
const uint campAreas = campArea.length(); //save the number of campAreas for easy reference
array campTime(campAreas,0); //initialize campTime for all areas as 0 gameticks
/********************/


/** This function checks if a player is in a certain camparea **/
/** and returns two bools: 1) whether the player is in the camp area **/
/** and 2) whether they have been there for too long **/
array isInCampArea(int player, int camparea) { //use an array to return multiple bools
array returnThis = {false, false}; //we assume that the player is not camping
// (and not for too long)
int maxCamp = campArea[camparea][2][0]; //store a bunch of information in temporary
int xCamp = campArea[camparea][0][0]; //variables for easier reading
int aCamp = campArea[camparea][1][0];
int yCamp = campArea[camparea][0][1];
int bCamp = campArea[camparea][1][1];
int xPos = jjPlayers[player].xPos / 32;
int yPos = jjPlayers[player].yPos / 32;

if ((xPos >= xCamp)&&(xPos <= aCamp)&&(yPos >= yCamp)&&(yPos <= bCamp)) { //is player in camparea?
campTime[camparea] += checkCampInterval;
returnThis[0] = true; //set bool is camping
jjPlayers[player].showText("You are camping " + campAreaName[camparea]); //display text (looks stupid if
if (maxCamp < campTime[camparea]) { // camping is checked too often)
returnThis[1] = true; //set bool camped for too long
}
}
else campTime[camparea] = 0; //player not camping -> reset timer

return returnThis; //return the (possibly altered) bool
}

/** You guys know what this one does already! **/
void onPlayer() {
if (jjGameTicks % checkCampInterval == 0) { //(thanks Artem/Foly)
for (uint i=0; i < campAreas;i++) { //loop through all camp areas
//^uint to avoid warning "Signed/Unsigned mismatch"
array isCamping = isInCampArea(p.localPlayerID, i); //check player and area, store result
if (isCamping[0]) { //is current player in camparea #1?
if (isCamping[1]) { //has current player been there for too long?
jjChat("I camped for too long " + campAreaName[i] + ". Now I die :c");
p.health = 0; //kill the player
campTime[i] = 0; //reset timer
}
}
}
}
}

cooba
Feb 1, 2013, 04:33 AM
Great idea for a thread.

Allow me to submit my own ammo randomizer, though! Not that anything is technically wrong with Faw's (very good and ambitious first script), of course.

int num;

void onFunction0() {
num = (jjRandom()%9) + 1;
p.powerup[num] = true;
p.currWeapon = num;
if (num > 1) p.ammo[num] = 50;
switch (num) {
case 1: p.showText("§1#@@@@@@||||||||B|||||||L|||||||A|||||||S||||||| T|||||||E|||||||R|||||||!"); break;
case 2: p.showText("§1#@@@@@@||||B||||O||U||||N||C||||E||R||||!"); break;
case 3: p.showText("§1#@@@@@@||||I|||C|||E|||!"); break;
case 4: p.showText("§1#@@@@@@||||S||||||||E||||||EK||||||ER|||||||!"); break;
case 5: p.showText("§1#@@@@@@|||R|||||||F|||||||!"); break;
case 6: p.showText("§1#@@@@@@||||T||||||OA||||||ST||||||ER||||||!"); break;
case 7: p.showText("§1#@@@@@@|||T|N|||||T|!"); break;
case 8: p.showText("§1#@@@@@@|||||P|E|||||P|P|||||E|R|||||! |||||||o||r ||||F|I|||||R|E|||||B|A|||||L|L|||||!"); break;
case 9: p.showText("§1#@@@@@@|||||E|||||||L|||||||E|||||||C|||||||T|| |||||R|||||||O |||||||B|||||||L|||||||A|||||||S|||||||T|||||||E|| |||||R|||||||!"); break;
}
}

FawFul
Feb 1, 2013, 06:33 AM
I would really love to see a Respawn trigger crate script for any ID explained, short and with variables!

Grytolle
Feb 1, 2013, 06:55 AM
Maybe this should be done on ERE? Or is the wiki too broken?

Stijn
Feb 1, 2013, 07:16 AM
Working on a code snippet section for J2O as we speak. Of course, as usual with whatever I'm working on, no ETA.

Meanwhile, if you have any feature requests for such a thing already, post them here.

FawFul
Feb 1, 2013, 07:31 AM
I want something else than JCF for this too, something easier to look over and with search functions. Meanwhile, best is to use this till there is another solution.

Violet CLM
Feb 1, 2013, 09:11 AM
I would really love to see a Respawn trigger crate script for any ID explained, short and with variables!
Two notes:

1) Trigger crates only query their Trigger ID when they're destroyed, so it's a question of the xOrg/yOrg bitfeld, not setting some other property to the desired ID.
2) Unless you're doing a single player level, you should probably use a generator object instead, so that the trigger crate is shared throughout the server. Otherwise you run the risk of the crate only existing locally and thus only changing a trigger locally.

If you still want such a script, though, I'd be tempted to do something like this pseudocode:

class myTriggerCrateGenerator:
uint16 xOrg;
uint16 yOrg;
uint respawnCounter = 0;
uint respawnDelay;
int object = 0;
void myTriggerCrateGenerator(uint16 x, uint16 y, uint d) {
xOrg = x*32; yOrg = y*32; respawnDelay = d;
}
void do() {
switch (respawnCounter) {
case 0:
jjOBJ@ o = jjObjects[object];
if (!(o.isActive && o.eventID == OBJECT::TRIGGERCRATE && o.xOrg == xOrg && o.yOrg == yOrg))
respawnCounter = 1;
break;
case respawnDelay: //this doesn't work, but in pseudo-code it does!
respawnCounter = 0;
object = jjAddObject(OBJECT::TRIGGERCRATE, xOrg, yOrg);
break;
default:
++respawnCounter;
}
}
And then have an array of myTriggerCrateGenerator objects and call do() on each of them every tick. But this is really just reinventing the wheel.

FawFul
Feb 1, 2013, 12:39 PM
Two notes:

1) Trigger crates only query their Trigger ID when they're destroyed, so it's a question of the xOrg/yOrg bitfeld, not setting some other property to the desired ID.
2) Unless you're doing a single player level, you should probably use a generator object instead, so that the trigger crate is shared throughout the server. Otherwise you run the risk of the crate only existing locally and thus only changing a trigger locally.

If you still want such a script, though, I'd be tempted to do something like this pseudocode:

And then have an array of myTriggerCrateGenerator objects and call do() on each of them every tick. But this is really just reinventing the wheel.

I've seen respawning trigger crates in JCSisFUN.

The thing i just want is to regenerate any trigger crate ID that is not just ID 31 that also works in MP (as in works as well as a normal trigger crate). I've never scripted before this update, i also have no idea what psuedo-code is. I just keep wondering if this is possible for MP, and i still haven't got clear answers yet.

Stijn
Feb 1, 2013, 12:53 PM
http://en.wikipedia.org/wiki/Pseudocode

Seren
Feb 1, 2013, 02:58 PM
A function that converts an integer variable to a string:

string IntToStr(int Input) {
int Number = Input;
string tempstr;
tempstr = "";
while (Number > 0) {
switch (Number % 10) {
case 0: tempstr = "0" + tempstr; break;
case 1: tempstr = "1" + tempstr; break;
case 2: tempstr = "2" + tempstr; break;
case 3: tempstr = "3" + tempstr; break;
case 4: tempstr = "4" + tempstr; break;
case 5: tempstr = "5" + tempstr; break;
case 6: tempstr = "6" + tempstr; break;
case 7: tempstr = "7" + tempstr; break;
case 8: tempstr = "8" + tempstr; break;
case 9: tempstr = "9" + tempstr; break;
}
Number = Number/10;
}
if (tempstr == "")
tempstr = "0";
return tempstr;
}
I... don't want to play smart ass or anything, but I know a slightly shorter piece of code (http://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes_strings.html) for that:
formatInt(value,"l");

Violet CLM
Feb 1, 2013, 03:29 PM
I've seen respawning trigger crates in JCSisFUN.

The thing i just want is to regenerate any trigger crate ID that is not just ID 31 that also works in MP (as in works as well as a normal trigger crate). I've never scripted before this update, i also have no idea what psuedo-code is. I just keep wondering if this is possible for MP, and i still haven't got clear answers yet.
<a href="http://www.jazz2online.com/jcsref/node.php?node=84&mode=id&menu=topics"><img src="http://www.jazz2online.com/upload/adminmedia/EventTheory9.png" /></a>
Set "Initial Delay" to 1 on the upper-right MCE Event for best results. This is what I would have done in that level, but cooba thought doing it through AngelScript would be clearer than using a MCE as pictured. If you want something multiplayer-friendly, use an MCE.

That said, I have an idea for how AngelScript might be able to make it easier, so watch this space.

Foly
Feb 1, 2013, 11:06 PM
I... don't want to play smart ass or anything, but I know a slightly shorter piece of code (http://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes_strings.html) for that:
formatInt(value,"l");

Yes, i tried that one too but it didn't work for me :(
Either i did it wrong or it isn't build in with jj2+.

Seren
Feb 2, 2013, 01:37 AM
I hadn't been sure either so I had checked it before I posted that, it works just fine. Try something like this (in multiplayer) to test:
void onPlayer()
{
jjChat(formatInt(jjGameTicks,"l"));
}

Foly
Feb 2, 2013, 01:43 AM
I hadn't been sure either so I had checked it before I posted that, it works just fine. Try something like this (in multiplayer) to test:
void onPlayer()
{
jjChat(formatInt(jjGameTicks,"l"));
}

Oh, i made a mistake then, sorry. Thanks for noticing, it's always better to have shorter codes :)

Grytolle
Feb 2, 2013, 02:49 AM
I found this for syntax highlighting of AngelScript in Notepad++.

I just dropped it in the program folder\plugins\APIs, and then I am able to select it for a specific file by clicking Language -> AngelScript. It would be nicer if it could be made so that it automatically identifies .j2as files as AngelScript, but I couldn't get it to work and I'm not really intending to try coding anything myself at the moment, so I'll leave that up to you.

AngelScript syntax highlighting (http://www.jazz2online.com/jj2plus/AngelScript.xml)

FawFul
Feb 2, 2013, 05:46 AM
<a href="http://www.jazz2online.com/jcsref/node.php?node=84&mode=id&menu=topics"><img src="http://www.jazz2online.com/upload/adminmedia/EventTheory9.png" /></a>
Set "Initial Delay" to 1 on the upper-right MCE Event for best results. This is what I would have done in that level, but cooba thought doing it through AngelScript would be clearer than using a MCE as pictured. If you want something multiplayer-friendly, use an MCE.

That said, I have an idea for how AngelScript might be able to make it easier, so watch this space.

Thanks a lot! Now i only need a way to turn it off to 0 with this.

Violet CLM
Feb 2, 2013, 09:31 AM
Add 32 to the leftmost MCE Event's "Event" parameter to make it act as an Off crate, or 64 to make it act as a Switch crate.

Seren
Feb 2, 2013, 10:03 AM
Day / night cycle
This script will smoothly change tileset palette between day and night. If used in multiplayer, it works for every client locally, meaning that each client will see a different time of the day.
const uint dnCYCLELENGTH=700;
const uint dnEVERYXTICKS=4;
const uint dnINITIALTICKS=256;
const string dnNIGHTTILESET="Carrot1N.j2t";
jjPAL PaletteNight;

void onLevelLoad()
{
PaletteNight.load(dnNIGHTTILESET);
}

void onMain()
{
if(jjGameTicks%dnEVERYXTICKS==0)
{
jjPalette=PaletteNight;
jjPalette.copyFrom(2,252,2,jjBackupPalette,(jjSin( 1024*jjGameTicks/dnCYCLELENGTH+dnINITIALTICKS)+1)/2);
jjPalette.apply();
}
}

dnCYCLELENGTH determines length of a single cycle in game ticks. 70 means one second.
dnEVERYXTICKS determines how often the palette should be updated. 1 will give the smoothest effect but can slow down the game. Higher values will save memory but not look as nice.
dnINITIALTICKS determines the initial time of the day. 0 means dawn, 256 means noon, 512 means dusk, 768 means midnight and 1024 means dawn again (there will be no difference between setting this constant to 0 and 1024). Of course, values in between are also allowed.
dnNIGHTTILESET is name of the tileset whose palette should be used in midnight. Note that the noon palette will be set to the default tileset of the level.

Healing freezer
In team games, this script will let players heal their teammates by shooting ice bullets at them. A single bullet can heal multiple people. Each bullet will heal 1 heart of damage. If freezer is powered-up, it shoots two bullets, so if both hit a player, it heals 2 hearts of damage in total. It won't heal the person who shot the bullet nor members of the opposite team.
void onPlayer()
{
for (int i=1;i&lt;jjObjectCount;i++)
{
if(jjObjects[i].isActive&&(jjObjects[i].eventID==OBJECT::ICEBULLET||jjObjects[i].eventID==OBJECT::ICEBULLETPU))
{
if(jjObjects[i].xPos&gt;p.xPos-12
&&jjObjects[i].xPos&lt;p.xPos+12
&&jjObjects[i].yPos&gt;p.yPos-12
&&jjObjects[i].yPos&lt;p.yPos+12
&&jjObjects[i].state!=STATE::KILL
&&jjPlayers[jjObjects[i].creator].playerID!=p.playerID
&&jjPlayers[jjObjects[i].creator].teamRed==p.teamRed)
{
if(p.health&lt;jjMaxHealth)
{
p.health=p.health+1;
}
jjObjects[i].state=STATE::KILL;
}
}
}
}
This script has no properties to edit.

Toni_
Feb 3, 2013, 12:32 AM
I would appreciate if someone writes a script that:

1) Makes text on text events not bouncing, or bouncing even more.
2) Changing direction of text on text events appearing. (Default is from right to left)
3) Makes it appear on different horizontal line.

Grytolle
Feb 3, 2013, 05:16 AM
Just A Random User: I am pretty sure that such functions first need to be implemented in plus.dll, not really anything that a script can solve.

Punish campers xd!
This was the first thing I could think of when I wanted to try out AngelScript, but it could probably be altered quite easily for trigger-like purposes or something. It also illustrates the use of (multi-layered) arrays and return in conjunction with an array.

semi.j2as:
Pastebin'd for easier reading (http://pastebin.com/X9AgdftM)

old code removed to save space

Edit: Please read the code on pastebin, because things like "<bool>" gets treated as html code here.
Edit2: It would make more sense to execute jjPlayers[player].showText("You are camping " + campAreaName[camparea]); outside of the function. If there are more improvements that will have to be made, I will work that into the next version. :P

Jerrythabest
Feb 3, 2013, 05:55 AM
Oh NICE Grytolle! That one's REALLY awesome :D

Toni_
Feb 3, 2013, 08:58 AM
Punishment should be -1h. Killing a player sounds too severe. If I use this script, will this work for -1h punishment?

if (isCamping[1])
{
jjChat("I camped for too long " + campAreaName[i] + ". Now I get punishment");
p.health = p.health - 1;
campTime[i] = 0;
}

Grytolle
Feb 3, 2013, 09:44 AM
Punishment should be -1h. Killing a player sounds too severe. If I use this script, will this work for -1h punishment?

if (isCamping[1])
{
jjChat("I camped for too long " + campAreaName[i] + ". Now I get punishment");
p.health = p.health - 1;
campTime[i] = 0;
}
Yes, that would work, but you might be able to write it shorter like this:
p.health -= 1;

I've made a new version of the script, however. In this version, you'd need to use this:
jjPlayers[pID].pHealth -= 1;
//or
jjPlayers[pID].pHealth = jjPlayers[pID].pHealth - 1;

----------

Please use pastebin to see everything properly: http://pastebin.com/fwQ1Q3b9
saving space

Seren
Feb 3, 2013, 09:46 AM
Just A Random User: I am pretty sure that such functions first need to be implemented in plus.dll, not really anything that a script can solve.
You need to be more open-minded. It can be done with a script. I could do it myself but it's very highly complicated and requires a lot of time, while I have many other scripts to write. Also, I'm afraid it would be limited to about 100 characters on screen.

Violet CLM
Feb 3, 2013, 10:24 AM
]jjPlayers[pID].pHealth -= 1;
Doesn't work, unfortunately. Health is one of a number of properties that are actually pairs of get_health/set_health methods being passed off as simple properties, and -=/+=/--/++ don't work on those.

SE, are you proposing drawing text manually by creating objects with individual characters as their sprites? If so, that's very resourceful, but eww.

Seren
Feb 3, 2013, 10:47 AM
SE, are you proposing drawing text manually by creating objects with individual characters as their sprites?
MAYBE

http://img845.imageshack.us/img845/5228/seas1.png

But hey, for short enough strings it works!

Jerrythabest
Feb 3, 2013, 12:38 PM
I figure we could provide API access to the drawText series of functions, so people can write their own UI elements. By doing it that way such elements would benefit from the fact that someday I'll implement 3D support for the UI itself, which will mostly happen in the drawText stuff.

Grytolle
Feb 3, 2013, 02:05 PM
I figure we could provide API access to the drawText series of functions, so people can write their own UI elements. By doing it that way such elements would benefit from the fact that someday I'll implement 3D support for the UI itself, which will mostly happen in the drawText stuff.That would be great!

Made a new version where you can define several rectangles to form one camp area (see id #3, the seekbox on semi).

Illustrating what tiles are marked:
http://jazzjackrabbit.net/gry/camparea.png
It was a bit tricky to select the right ones, because when you jump into a tile above you your head (atleast as spaz) sticks into it a bit (the right outer side of the seekbox). I also made a small alteration to the comparison code, changing (xPos <= aCamp) to (xPos < aCamp). Not sure why it's better, but trial and error tells me that it is so.

Punish campers! xd v2.0
http://pastebin.com/XBQhpkAK (as always, please read it on pastebin)
/*
Punish campers xd! v2.0

changes v2.0:
-made non-rectangular camp areas possible

changes v1.1:
-had to recreate the onPlayer function, because it wouldn't work for clients :S
-moved a message out of isInCampArea()
-killed player with .kill() instead of .health=0 (thx cooba)

improvements needed:
-make it not needed to state maxcamp for every sub-area
-show time remaining in campspot (could be achieved with the timer functions, I assume)
-don't kill players if the game is stopped (the AngelScript implementation needs a new bool)
-the chat is sent as teamchat if the player last used teamchat
-you regain health if you die on purpose with flag xd
*/

/** script settings **/
const uint checkCampInterval=70; //how often to check for camping (gameticks) 70 = one second
/*********************/

/** level settings: define camp areas **/
array<array<array<int>>> campArea = {
/* A camparea is a rectangle referred to by its top left and bottom right corner
x,y -----------
| |
| |
----------- a,b */
// camparea(x,y) camparea(a,b) allowed camp id
// time(gameticks) (needed for new shapes)
{{29,12}, {40,12}, {250}, {0}}, //camparea #0: on top of seek pu
{{64,05}, {101,19}, {500}, {1}}, //camparea #1: the rf area
{{30,49}, {64,56}, {250}, {2}}, //camparea #2: at carrot

{{31,14}, {41,14}, {250}, {3}}, //camparea #3: rectangle1
{{30,15}, {41,15}, {250}, {3}}, //camparea #3: rectangle2
{{30,16}, {41,16}, {250}, {3}}, //camparea #3: rectangle3
{{31,17}, {41,17}, {250}, {3}}, //camparea #3: rectangle4
{{32,18}, {39,18}, {250}, {3}}, //camparea #3: rectangle5
{{35,19}, {38,19}, {250}, {3}} //camparea #3: rectangle6
};
//it doesn't seem like you can have mixed arrays in AS
//so we just put the strings in a separate array
array<string> campAreaName = {
"above seeks", //camparea #0
"in the rf area", //camparea #1
"at the carrot", //camparea #2
"in the seek box" //camparea #3
};
/******** end of level settings ********/

/** script globals **/
uint campAreas = 0;
uint campAreasRealLength;
array<int> campTime;


void onLevelLoad() {
campAreasRealLength = campArea.length();
for (uint i=0; i < campAreasRealLength;i++) {
campAreas = campArea[i][3][0];
}
campAreas++;
campTime.resize(campAreas);
}

/********************/


/** This function checks if a player is in a certain camparea **/
/** and returns two bools: 1) whether the player is in the camp area **/
/** and 2) whether they have been there for too long **/
array<bool> isInCampArea(int pID, int camparea) { //use an array<bool> to return multiple bools
//if (camparea == 3) jjDebug("checking area #" + formatInt(camparea,"l"));
array<bool> returnThis = {false, false}; //we assume that the player is not camping
// (and not for too long)

int maxCamp;
int xPos = jjPlayers[pID].xPos / 32;
int yPos = jjPlayers[pID].yPos / 32;
campTime[camparea] += checkCampInterval; //update camptime

for (uint j=0; j < campAreasRealLength;j++) {
if (campArea[j][3][0] == camparea) { //all parts of the camp area
//jjDebug("camp #" + formatInt(j,"l"));
maxCamp = campArea[j][2][0]; //store a bunch of information in temporary
int xCamp = campArea[j][0][0]; //variables for easier reading
int aCamp = campArea[j][1][0];
int yCamp = campArea[j][0][1];
int bCamp = campArea[j][1][1];

if ((xPos >= xCamp)&&(xPos < aCamp)&&(yPos >= yCamp)&&(yPos <= bCamp)) { //is player in camparea?
returnThis[0] = true; //set bool is camping
}

}
}


if (!returnThis[0]) {
campTime[camparea] = 0; //player not camping -> reset timer
//if (camparea == 3) jjDebug("not camping #" + formatInt(camparea,"l"));
}
/*else {
if (camparea == 3)jjDebug("is camping" + formatInt(camparea,"l"));
}*/
if (maxCamp < campTime[camparea]) {
returnThis[1] = true; //set bool camped for too long
}





return returnThis; //return the (possibly altered) bool
}

/** onPlayer wouldn't work for me ;S **/
void realOnPlayer(int pID) {
if (jjGameTicks % checkCampInterval == 0) { //(thanks Artem/Foly)
for (uint i=0; i < campAreas;i++) { //loop through all camp areas
//^uint to avoid warning "Signed/Unsigned mismatch"
array<bool> isCamping = isInCampArea(pID, i); //check player and area, store result
if (isCamping[0]) { //is current player in camparea #1?
jjPlayers[pID].showText("You are camping " + campAreaName[i]); //display text (looks stupid if
// camping is checked too often)
if (isCamping[1]) { //has current player been there for too long?

/** WHAT SHOULD HAPPEN IF THE PLAYER CAMPS FOR TOO LONG??? **/
jjChat("I camped for too long " + campAreaName[i] + ". Now I die :c");
jjPlayers[pID].kill(); //kill the player
campTime[i] = 0; //reset timer
/** ^-^ **/

}
}
}
}
}
void onMain() {
/** emulating onPlayer **/
for (uint i=0; i < 32;i++) {
if ((jjPlayers[i].isActive)&&(jjPlayers[i].isLocal)) realOnPlayer(i);
}
/************************/
}

Stijn
Feb 3, 2013, 02:20 PM
http://www.jazz2online.com/snippets/

Quick and dirty, but seems to work. Will make it look more fancy later. Feature requests and bug reports are possible, can't say much about when they'd be addressed though.

Grytolle
Feb 3, 2013, 02:29 PM
Seems to work well, except that the version number didn't increase :)

Stijn
Feb 3, 2013, 02:34 PM
Yeah, as usual all kinds of bugs appear when someone uses it for something else than testing ;)

djazz
Feb 3, 2013, 02:42 PM
Here's my blade gun!
http://www.youtube.com/watch?v=Qr8pahz-QTs

Pastebin: http://pastebin.com/5WYsBEQT
It's also on the snippets page, here: http://www.jazz2online.com/snippets/37/blade-gun-electroblaster-pu/

Stijn
Feb 3, 2013, 03:47 PM
Seems to work well, except that the version number didn't increase :)
Fixed this, and also added a "raw code" button to pages to go to a plaintext version of the source code. The highlighted code is also a bit more readable, though there's only so much you can do with Gry's coding style ;)

Seren
Feb 3, 2013, 09:30 PM
added a "raw code" button to pages to go to a plaintext version of the source code.
Oh nice, that and ctrl+A solves the issue as was lack of a "select the whole code" button that I didn't even have time to mention yet.

Violet CLM
Feb 3, 2013, 11:07 PM
DJazz, mind if I put that blade gun video on the Mod DB page? It's pretty cool-looking.

djazz
Feb 3, 2013, 11:51 PM
DJazz, mind if I put that blade gun video on the Mod DB page? It's pretty cool-looking.
Sure thing! :D

DennisKainz
Feb 4, 2013, 08:42 AM
I'm making a little SP level, and I have made a little part of the script...

void onLevelLoad() { jjObjectPresets[OBJECT::NORMTURTLE].energy = 8; jjObjectPresets[OBJECT::BEE].energy = 8; jjObjectPresets[OBJECT::TURTLESHELL].energy = 32; }
void onMain() { p.food = 99; if (p.health > 1) p.health = 1; }

I managed to make some enemies health x8, emulate the Instagib command, and make Jazz get the sugar rush with one only food item (would help a lot in the Jazz Unleashed Hell level), but I have spent a whole unsuccesful hour trying to make an expression for me to have as the level completing goal to kill every single enemy and collect every single item.

I tried "if (OBJECT::NORMTURTLE = 0)", "if (OBJECT::NORMTURTLE.state = STATE::KILL)", "if (OBJECT::NORMTURTLE.jjObjectCount = 0)" but they all crashed the j2as file instead. Can anyone help me here?

Violet CLM
Feb 4, 2013, 11:06 AM
Hmmm. That's a tricky one, because SP doesn't store jjOBJ copies of objects that aren't near to the player. It's only in MP that you get jjOBJs for everything all the time. But there might still be a solution...

bool areAllNormTurtlesDestroyed() {
jjOBJ@ o;
for (int i = 1; i < jjObjectCount; ++i) {
@o = jjObjects[i];
if (o.isActive && o.eventID == OBJECT::NORMTURTLE) return false;
}
for (uint16 x = 0; x < jjLayerWidth[4]; ++x) {
(for uint16 y = 0; y < jjLayerHeight[4]; ++y) {
if (jjEventGet(x,y) == OBJECT::NORMTURTLE && jjParameterGet(x,y,-1,1) == 0) return false;
}
}
return true;
}
The key step is <code>jjParameterGet(x,y,-1,1)</code>, which is a bit that is set to 1 in the event field when an object is created. The bit is set back to 0 if the object passes off screen and gets deactivated, but it is left at 1 if you destroy the object. Basically, if it's at 0 JJ2 takes that as a cue to create the object when that tile is close enough to the player -- if it's at 1, JJ2 ignores it. So that code might work, unless there's something else I'm not thinking of.

Grytolle
Feb 4, 2013, 01:50 PM
Notice: Undefined variable: oPackage in /home/jazzonli/public_html/J2Ov2/snippets/form.php on line 29

Fatal error: Call to a member function info() on a non-object in /home/jazzonli/public_html/J2Ov2/snippets/form.php on line 29

: (

Stijn
Feb 4, 2013, 02:43 PM
Should be fixed

Grytolle
Feb 4, 2013, 03:24 PM
Works!

DennisKainz
Feb 5, 2013, 06:53 AM
The only thing I don't like is that when you commit a mistake in the code, you aren't notified of which line and which position your mistake is, nor you are notified of what the expression should be.

eg. "Error at line 3 at position 19: Missing brackets" or "Error at line 4 at position 14: Unknown variable "healtj""

djazz
Feb 5, 2013, 06:58 AM
The only thing I don't like is that when you commit a mistake in the code, you aren't notified of which line and which position your mistake is, nor you are notified of what the expression should be.

Like this?

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.)

The errors prints out in the chatlogger window.

DennisKainz
Feb 5, 2013, 07:01 AM
Oh ... Sorry ... mistake of mine. I never read the ChatLog, you know.

Foly
Feb 6, 2013, 06:36 AM
I guess this thread can still be used for some advertising of code snippets:

http://www.jazz2online.com/snippets/50/boomerang-gun/

This is a script that changes the powered up blaster into a boomerang gun. Nothing much more to say about it, you'll see how it works if you try it :)

DennisKainz
Feb 6, 2013, 01:43 PM
Basic code for subdividing a level into mini-rooms, as in Oddworld games:

if (p.xPos > 0)
if (p.xPos < 640)
if (p.yPos > 0)
if (p.yPos < 480)
p.cameraFreeze(0, 0, false, true);
if (p.xPos > 640)
if (p.xPos < 1280)
if (p.yPos > 0)
if (p.yPos < 480)
p.cameraFreeze(640, 0, false, true);
if (p.xPos > 0)
if (p.xPos < 640)
if (p.yPos > 480)
if (p.yPos < 960)
p.cameraFreeze(0, 480, false, true);
if (p.xPos > 640)
if (p.xPos < 1280)
if (p.yPos > 480)
if (p.yPos < 960)
p.cameraFreeze(640, 480, false, true);

And so on ...

Seren
Feb 6, 2013, 10:09 PM
Basic code for subdividing a level into mini-rooms, as in Oddworld games:

if (p.xPos > 0)
if (p.xPos < 640)
if (p.yPos > 0)
if (p.yPos < 480)
p.cameraFreeze(0, 0, false, true);
if (p.xPos > 640)
if (p.xPos < 1280)
if (p.yPos > 0)
if (p.yPos < 480)
p.cameraFreeze(640, 0, false, true);
if (p.xPos > 0)
if (p.xPos < 640)
if (p.yPos > 480)
if (p.yPos < 960)
p.cameraFreeze(0, 480, false, true);
if (p.xPos > 640)
if (p.xPos < 1280)
if (p.yPos > 480)
if (p.yPos < 960)
p.cameraFreeze(640, 480, false, true);

And so on ...
Or, instead of hundreds of lines for barely medium-sized SP levels, you can use this one-liner:
void onPlayer()
{
p.cameraFreeze(p.xPos-p.xPos%640,p.yPos-p.yPos%480,false,true);
}

DennisKainz
Feb 7, 2013, 01:16 AM
Thank you for your help. I didn't know the % could be used for symmetric number skips.

Hey! I won't need that "rest" custom option anymore, since I can use "if (jjGameTicks = jjGameTicks%700)" for things happening every 10 seconds!

I have sooo much to learn yet...

Jerrythabest
Feb 7, 2013, 01:29 AM
You can also use "if (jjGameTics % 700 == 0)", saves you half the typing. Also, you'll need to use '==' for comparing ;)

DennisKainz
Feb 7, 2013, 01:47 AM
Thank you for your advice. Besides, the other expression did not work!

Jerrythabest
Feb 7, 2013, 03:32 AM
Ah, on second thought your expression wouldn't work indeed. The 'jjGameTicks%700' part would only produce numbers 0-699. It would evaluate to true every gametick for the first 10 seconds, and to false ever after that.

Seren
Feb 9, 2013, 08:03 AM
http://img593.imageshack.us/img593/1457/purplej.png (http://www.jazz2online.com/snippets/51/colorful-super-gems/)

Violet CLM
Feb 9, 2013, 10:08 AM
Yeah, that one's definitely planned for inclusion, though I hadn't gotten around to it yet, mostly because gem rings are so much more difficult to do that for.

(If you leave var[0] at 0, do they act as coins? I forget how flexible that code is.)

Seren
Feb 9, 2013, 10:20 AM
(If you leave var[0] at 0, do they act as coins? I forget how flexible that code is.)
A bit. Their colors go disco and on being collected they show how many coins you have, but won't add to the amount.

Jerrythabest
Feb 10, 2013, 03:46 AM
Haha, nice one. We don't need to enhance any more events in Plus, people will do it through scripts! :D

Violet CLM
Feb 10, 2013, 10:56 AM
I'll admit I'm hoping someone will figure out <em>for</em> us what Auto Fire and Max Weapon should do as useful events.

minmay
Feb 10, 2013, 04:59 PM
I always pictured Max Weapon as a power-up box that powered up all your weapons and gave them maximum ammo, just like jjgod without the invincibility. That's just my guess as to what it was originally supposed to be like, though, not a suggestion for what would be a good new event (it wouldn't be a good new event IMO).

Personally I'd just leave them nonexistent and save the JCS.ini space for completely new cool events later.

P.S. Jerrythabest: did you add a mod pattern jump function yet? =P

edit: oops offtopic thought this was the actual JJ2+ thread somehow

Grytolle
Feb 10, 2013, 09:53 PM
Never heard about that event, but intuitively I'd agree with minmay, except that I'd say without powerups (because of the difference between jjgod and jjammo). I'd probably also limit the ammo received to the kinds of ammo that are already present in the level.

Jerrythabest
Feb 10, 2013, 11:44 PM
Sounds much like a /ready box to me! :D Put one at each CTF base for pure evilness.


@minmay: I haven't looked into the sound stuff at all, so I'm still clueless about how I would do this. I'm focussing more on graphics at the moment ;)

DennisKainz
Feb 11, 2013, 03:43 AM
The fault if I got a bad rating for "River Secrets" is partly mine, ofcourse, but it is also because of a lot of missing commands in Angel Script.

Now, I don't know if they will ever be included, nor I know if it's POSSIBLE to include them, and I don't EXPECT them to be created, but if they can be, there they are:
- A command for deactivating special moves (one for JUMP JUMP and one for DUCK JUMP)
- A command for deactivating running mode ("ERR: Reference is read-only)
- One for deactivating buttstomp
- Checking and alterating what Jazz and siblings do ("ERR: "state" is not a member of "jjPlayer")
- Making the ammo pickups give you more or less ammunition (I tried var[0-100] unsuccessfully)
- Making some enemies hurt you more than 1 HP
- Making the max health higher or lower than 5 even in SP mode
- Maybe also making the maximum ammunitions higher than 99 (I had no problem making them LOWER than 99)
- Making the blink time higher or lower (in my case 0) even in SP mode
- A command for deactivating direction changes in midair (if the player isn't standing on the ground or a platform, the direction keys do nothing)

Foly
Feb 11, 2013, 08:23 AM
- A command for deactivating running mode ("ERR: Reference is read-only)


You can limit the speed in onMain or onPlayer:

Pseudocode/code:
if (p.xSpeed > value) p.xSpeed = value;
if (p.xSpeed < -value) p.xSpeed = -value;
p.jumpStrength = othervalue;

Or you can use speed = sqrt(p.xSpeed^2 + p.ySpeed^2) and limit that one, it all depends on how you want it to be limited.


- Making the ammo pickups give you more or less ammunition (I tried var[0-100] unsuccessfully)
- Making some enemies hurt you more than 1 HP
- Maybe also making the maximum ammunitions higher than 99 (I had no problem making them LOWER than 99)


It is possible to code this, if you want i can give you a pseudocode/code for it.


- Making the max health higher or lower than 5 even in SP mode


In multiplayer use jjChat("maxhealth x"), i don't know if this works in sp too.


- A command for deactivating direction changes in midair (if the player isn't standing on the ground or a platform, the direction keys do nothing)

If by this you mean when the player jumps it should keep it's xSpeed, then it should be possible to do this with AS.

As for the other stuff, i don't think it's possible yet to do this in AngelScript, correct me if i'm wrong :)

Seren
Feb 11, 2013, 09:13 AM
- Making the blink time higher or lower (in my case 0) even in SP mode
if(p.invincibility<0)
{
p.invincibility=0;
}

DennisKainz
Feb 12, 2013, 07:18 AM
Indeed, I tried the Invincibility cheat, but it resulted to change the invincibility given from the carrots (the one with the translucent circumferences around Jazz), not the blink time.

I just need to know all the expressions it's possible to find in AngelScript, and their exact meaning. I'm too lazy to test them one by one until I find what I need (IF it exists), and I hope someone will add some more expressions and make a simplified version of the AngelScript someday.

Oh, by the way, the AngelScript manual says "jumpSpeed" instead of "jumpStrength". I hope it was fixed already.

Seren
Feb 12, 2013, 08:24 AM
Uh, so I assume that invincibility going below 0 when you get hurt is a random artifact. The game changes the value but doesn't read it. Surprisingly, "/noblink on" doesn't work in SP either. Feels like somebody worked really hard to make changes on that front difficult.

Violet CLM
Feb 12, 2013, 12:22 PM
I just need to know all the expressions it's possible to find in AngelScript, and their exact meaning.
http://www.jazz2online.com/jj2plus/plus-angelscript.html
I'm too lazy to test them one by one until I find what I need (IF it exists)
Well, that's your problem, then.
and I hope someone will add some more expressions and make a simplified version of the AngelScript someday.
These are two contradictory goals.
Oh, by the way, the AngelScript manual says "jumpSpeed" instead of "jumpStrength". I hope it was fixed already.
http://www.jazz2online.com/jj2plus/plus-readme.html#lc020413

Jerrythabest
Feb 12, 2013, 12:34 PM
Surprisingly, "/noblink on" doesn't work in SP either. Feels like somebody worked really hard to make changes on that front difficult.Before the Jan 28th release, commands were only available in online games. They have been written for and tested with online games exclusively. Their availability in offline games is a side effect of the new menus and of the AngelScript API. We haven't come to fixing that yet, which means many commands don't work properly offline (neither through AngelScript nor through the menus). This is a thing on the to-do list.

Seren
Feb 12, 2013, 12:59 PM
Oh, don't mind that, "somebody" was actually meant to point to an abstract entity, I didn't mean to criticize your work. I just figured out that most MP commands would work in SP as a side-effect of the independent implementations of them and the menus you mention, so I was surprised noblink doesn't. But I acknowledge the situation Plus is in and understand that some features don't yet work as expected or planned.

Jerrythabest
Feb 12, 2013, 02:03 PM
Oh, no worries, I didn't interpret your post as being offensive or anything. Just decided I'd explain how this happened :)

In fact, we even had the menu items available to admins for a few hours. But that turned out to be so extremely buggy that we've decided to disable them for now.

Violet CLM
Feb 16, 2013, 09:42 PM
I figure we could provide API access to the drawText series of functions, so people can write their own UI elements.
Turns out yes, we can.
<img src="http://img687.imageshack.us/img687/9746/pluslizards.png" width="279" height="239" alt="LIZARD" />
Number of objects in screenshot: three.

Jerrythabest
Feb 17, 2013, 12:57 AM
Oh wow. OH WOW.

Stijn
Feb 17, 2013, 01:07 AM
Now all that's needed is a putPixel() function and we can have custom GUIs!

Seren
Feb 21, 2013, 12:57 PM
Uhm, last time I explained a way of converting integers into strings I didn't mention an even simpler way that also works. I actually did it on purpose, because personally I consider it a rather ugly way, but I just realized that some of you might want to choose it as it takes much less space and doesn't require memorizing a function name. There goes:
""+value
So, the code I used for testing here:void onPlayer()
{
jjChat(formatInt(jjGameTicks,"l"));
}
can also be changed into the following:void onPlayer()
{
jjChat(""+jjGameTicks);
}
with the same effect. You won't even get warnings about mixing variable types. "" can also be replaced with an actual string, if you want one there.

Side note: Assignment in this manner is also allowed, that is, for example, if you use the following code:
string name=555;name will become a declared string that says "555". But that's one really ugly piece of code and I beg you to never do something like that.

Oh, right, and I should mention it works fine with floats too.

Jerrythabest
Feb 21, 2013, 01:55 PM
Hey, those things remind of PHP. Really, the AngelScript guy (what was his name again?) is less strict than I'd expected at first.

Violet CLM
Feb 21, 2013, 02:26 PM
Of course, a benefit of formatInt is that it lets you use hexadecimal notation, or padding zeroes, or other such, depending on your specific needs.

Jerrythabest
Feb 22, 2013, 07:01 AM
You know what would be useful? A reverse-lookup for enums. LikejjEnum(2, WEAPON::Weapon); returns "ICE".

cooba
Feb 27, 2013, 10:59 AM
Sharing is caring: http://www.jazz2online.com/snippets/65/fire-shield-burns-enemies-on-touch/

Very much room for improvement (never hurting the player when burning would be a good start)...

Violet CLM
Feb 27, 2013, 11:13 AM
You know what would be useful? A reverse-lookup for enums. LikejjEnum(2, WEAPON::Weapon); returns "ICE".
Doesn't seem to be a thing AngelScript supports, and presumably for good reason. Not all integers have exactly one enum value that represents them -- some have zero, some have two or more.

Sharing is caring
Would <code>o.objType | 16 == 16</code> work there in place of the long list of eventIDs? Also IIRC you should specify the creator ID in jjAddObject as p.playerID, to ensure the right player gets points for destroying the enemy.

cooba
Feb 27, 2013, 11:21 AM
Would <code>o.objType | 16 == 16</code> work there in place of the long list of eventIDs?That doesn't work, but I suppose I can just check <code>enemy.objType >= 16</code>.Also IIRC you should specify the creator ID in jjAddObject as p.playerID, to ensure the right player gets points for destroying the enemy.<s>There are no points received as all, for some weird reason.</s> Yup, adding that did the trick. Updated.

Seren
Feb 27, 2013, 11:53 AM
<code>o.objType | 16 == 16</code>
<code>o.objType & 16 == 16</code> ?

Violet CLM
Feb 27, 2013, 11:56 AM
...yes, that's what I meant. Maybe <code>(o.objType & 16) == 16</code> just to be safe, since I don't remember AngelScript's order of operator priority.

Jerrythabest
Feb 28, 2013, 09:09 AM
<strike>From my experience bitwise operators always come last, so you should always use parentheses around those in these situations. (Haven't tested.)</strike>

EDIT: Read below.

Seren
Feb 28, 2013, 10:43 AM
Here's the manual (http://www.angelcode.com/angelscript/sdk/docs/manual/doc_operator_precedence.html). The parentheses aren't necessary.

Jerrythabest
Feb 28, 2013, 01:06 PM
Hey, interesting. Apparently I was wrong. I'll edit my post to reduce confusion.

Seren
May 6, 2013, 08:05 AM
I think the code snippets section should be divided into two categories based on whether they are meant for level designers or coders. The former usually need ready, specific scripts that might only have a set of values to be modified, while the latter require "libraries", i.e. sets of enums, classes and functions that help them avoid reinventing the wheel. The difference can be compared to that between a level editor and a library. Currently most, if not all of the snippets belong to the designer-friendly category (with Grytolle's triggar zones somewhat standing out due to necessity to write a short piece of own code), but it's partly because I don't want to create a mess there. If any level makers come there for presets I imagine they would be easily confused by scripts that promise everything but do nothing.

Jerrythabest
May 6, 2013, 12:10 PM
Yes, I agree. Sounds very reasonable.

Stijn
May 7, 2013, 02:57 PM
Well, there's tags, for now. I might make explicit categories if people would actually upload more scripts :P

cooba
Sep 12, 2013, 06:36 AM
Have you always wanted a trigger crate to do more cool stuff than just changing a trigger, but you've felt the code was pretty ugly, and then wished for something like onCrate()?

Here's pretty much it:

http://www.jazz2online.com/snippets/82/calling-code-on-crashing-a-crate

cooba
Oct 20, 2013, 06:01 AM
<a href="http://www.jazz2online.com/snippets/86/vertically-flip-any-tile-by-placing-an-event">But Violet, how do I flip tiles vertically?</a>

Jerrythabest
Oct 20, 2013, 07:31 AM
Now we finally have a truly valid reason for replacing JCS with MLLE in the next release :p

Treylina
Oct 20, 2013, 01:01 PM
In that case, MLLE should be made 1.24 compatible. Or is it already? I can't be bothered to look through the entire thread (nor can I find it anymore).

In the case of MLLE vs webJCS, I don't like using webJCS much, it's too intensive on my computer. It's only good for live collaberations.

Violet CLM
Oct 20, 2013, 01:06 PM
One of MLLE's big strengths is that it's <em>everything</em>-compatible, including Battery Check, AGA, 1.10o, and 1.00g/h. :P It's big weaknesses are that it's got some big bugs and isn't currently available for download.

Jerrythabest
Oct 20, 2013, 01:11 PM
... And that it's lead developer is suffering from another project that is taking up all his time :)

Love & Thunder
Oct 21, 2013, 04:19 PM
I quite agree with Treylina about MLLE and WebJCS, and -- in case anyone's curious and has forgotten -- the MLLE thread is called "Playing catchup with DJazz".
(Also, if anyone wants it and Violet's okay with it, I could upload the version I have installed on this computer to my public Dropbox.)