Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Survivor.mut | Violet CLM | Mutator | 9.7 |
void onLevelBegin() { //can't use commands while cycling
if (jjIsServer || jjGameConnection == GAME::LOCAL) {
if (jjGameMode != GAME::CTF) { //non-team-based
if (jjGameCustom != GAME::LRS && jjGameCustom != GAME::XLRS)
jjChat("/lrs");
} else {
if (jjGameCustom != GAME::TLRS)
jjChat("/tlrs");
}
}
}
array<uint> StartWarpIDs();
array<int> ArenaBoundaries = {9999, 9999, 0, 0}; //left, top, right, bottom
void onLevelLoad() { //find start warp ID
for (int yTile = 0; yTile < 26; ++yTile)
for (int xTile = 0; xTile < 30; ++xTile) {
const int eventID = jjEventGet(xTile, yTile);
if (eventID == AREA::WARP && jjParameterGet(xTile, yTile, 8, 8) == 0) { //not a coin warp
jjMASKMAP mask(jjTileGet(4, xTile, yTile));
if (!mask[15, 2] && !mask[2, 30] && !mask[30, 30]) { //not a solid tile; these three pixels serve to weed out all the warps on masked tiles in all thirty survivor levels/tilesets
const uint warpID = jjParameterGet(xTile, yTile, 0, 8);
if (!(warpID == 0 && StartWarpIDs.length > 0)) //avoid issue with survivor08
StartWarpIDs.insertLast(warpID); //several levels use multiple warp IDs instead of (only) multiple warp targets per ID
}
} else if (eventID == AREA::WATERLEVEL) //survivor03, survivor23, maybe others I'm forgetting
jjSetWaterLevel(jjParameterGet(xTile, yTile, 0, 8) * 32, true);
}
if (jjEventGet(6, 7) == AREA::TRIGGERZONE) //survivor13
jjTriggers[jjParameterGet(6, 7, 0, 5)] = (jjParameterGet(6, 7, 5, 1) == 1);
jjCharacters[CHAR::JAZZ].airJump = jjCharacters[CHAR::SPAZ].airJump;
jjCharacters[CHAR::JAZZ].doubleJumpCountMax = jjCharacters[CHAR::SPAZ].doubleJumpCountMax;
jjCharacters[CHAR::JAZZ].doubleJumpXSpeed = jjCharacters[CHAR::SPAZ].doubleJumpXSpeed;
jjCharacters[CHAR::JAZZ].doubleJumpYSpeed = jjCharacters[CHAR::SPAZ].doubleJumpYSpeed;
if (jjIsTSF) {
jjCharacters[CHAR::LORI].airJump = jjCharacters[CHAR::SPAZ].airJump;
jjCharacters[CHAR::LORI].doubleJumpCountMax = jjCharacters[CHAR::SPAZ].doubleJumpCountMax;
jjCharacters[CHAR::LORI].doubleJumpXSpeed = jjCharacters[CHAR::SPAZ].doubleJumpXSpeed;
jjCharacters[CHAR::LORI].doubleJumpYSpeed = jjCharacters[CHAR::SPAZ].doubleJumpYSpeed;
}
for (int xTile = jjLayerWidth[4] - 1; xTile >= 0; --xTile)
for (int yTile = jjLayerHeight[4] - 1; yTile >= 0; --yTile) {
const int eventID = jjEventGet(xTile, yTile);
if (eventID == OBJECT::DESTRUCTSCENERY) {
if (xTile < ArenaBoundaries[0])
ArenaBoundaries[0] = xTile;
if (xTile > ArenaBoundaries[2])
ArenaBoundaries[2] = xTile;
if (yTile < ArenaBoundaries[1] && (ArenaBoundaries[1] == 9999 || ArenaBoundaries[1] - yTile < 40)) //avoid issue with survivor24
ArenaBoundaries[1] = yTile;
if (yTile > ArenaBoundaries[3])
ArenaBoundaries[3] = yTile;
}
}
for (int i = 0; i < 4; ++i) { //extend sides slightly
if (i > 1)
ArenaBoundaries[i] += 2;
else
ArenaBoundaries[i] -= 1;
ArenaBoundaries[i] *= 32;
}
SpinningString.align = STRING::CENTER;
}
bool GameWasActive = true;
bool LocalPlayerWasBlinking = false;
jjPLAYER@ LocalPlayer = jjLocalPlayers[0];
void onMain() { //Go through and adjust certain objects to be destroyable (or not) depending on whether the game is in progress or paused/pregaming
bool gameActive = jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME;
if (gameActive && !GameWasActive) {
for (int i = 0; i < 32; ++i)
if (jjPlayers[i].isActive && jjPlayers[i].isConnecting) {
gameActive = false; //don't start the game if someone's connecting
break;
}
}
if (GameWasActive != gameActive) {
GameWasActive = gameActive;
if (gameActive) {
for (int i = jjObjectCount - 1; i >= 1; --i) {
jjOBJ@ obj = jjObjects[i];
if (obj.behavior == BEHAVIOR::DESTRUCTSCENERY)
obj.bulletHandling = HANDLING::DETECTBULLET;
else if (obj.behavior == BEHAVIOR::CRATE)
obj.playerHandling = HANDLING::SPECIAL;
}
} else {
for (int i = jjObjectCount - 1; i >= 1; --i) {
jjOBJ@ obj = jjObjects[i];
if (obj.behavior == BEHAVIOR::DESTRUCTSCENERY)
obj.bulletHandling = HANDLING::IGNOREBULLET;
else if (obj.behavior == BEHAVIOR::CRATE)
obj.playerHandling = HANDLING::SPECIALDONE;
}
}
}
const bool localPlayerBlinking = LocalPlayer.blink != 0;
if (LocalPlayerWasBlinking != localPlayerBlinking) {
for (int i = jjObjectCount - 1; i >= 1; --i) {
jjOBJ@ obj = jjObjects[i];
if (obj.behavior == BEHAVIOR::SPRING || obj.behavior == BEHAVIOR::BUMP || obj.behavior == BEHAVIOR::PADDLE) //stuff that you shouldn't be able to use while blinking
obj.playerHandling = (localPlayerBlinking) ? HANDLING::SPECIALDONE : HANDLING::SPECIAL;
}
LocalPlayerWasBlinking = localPlayerBlinking;
}
}
array<int> playerState(4, 0); //0: starting. 1: warping. 2: in game.
void onPlayer(jjPLAYER@ play) {
if (play.health > 0) {
if (play.yPos < 20*32) { //in start area
if (playerState[play.localPlayerID] == 0) {
play.keyLeft = play.keyRight = play.keyJump = play.keyFire = play.keyRun = false;
play.doubleJumpCount = 0; //so you'll be able to double jump again if you revive
const int arenaLeft = ArenaBoundaries[0];
const int arenaTop = ArenaBoundaries[1];
const int arenaRight = ArenaBoundaries[2] - jjSubscreenWidth;
const int arenaBottom = ArenaBoundaries[3] - jjSubscreenHeight;
const int arenaHalfWidth = (arenaRight - arenaLeft) / 2;
const int arenaHalfHeight = (arenaBottom - arenaTop) / 2;
const float intensityX = jjSin((arenaHalfWidth > arenaHalfHeight) ? jjRenderFrame/2 : jjRenderFrame*3);
const float intensityY = jjSin((arenaHalfWidth > arenaHalfHeight) ? jjRenderFrame*3 : jjRenderFrame/2);
play.cameraFreeze(
arenaLeft + arenaHalfWidth + intensityX * arenaHalfWidth,
arenaTop + arenaHalfHeight + intensityY * arenaHalfHeight,
false, true
);
if (play.warpID == 0 && play.blink == 0 && GameWasActive) { //ready to begin; has to be ==0, not <2, to work with survivor21
play.warpToID(StartWarpIDs[jjRandom() % StartWarpIDs.length]);
playerState[play.localPlayerID] = 1;
jjTriggers[1] = true; //in a happy bit of consistency, all Survivor levels use trigger 1 to start the level
}
} else if (GameWasActive && playerState[play.localPlayerID] == 2) { //out
playerState[play.localPlayerID] = 0;
play.hurt(10, true); //works better than jjPLAYER::kill
}
} else { //in arena
if (playerState[play.localPlayerID] == 1) { //finished warping
playerState[play.localPlayerID] = 2; //in game
play.cameraUnfreeze(false);
}
if (play.health != jjMaxHealth && !(jjGameCustom == GAME::XLRS || jjGameState == GAME::OVERTIME)) //invincible, but in a way that allows players to be hit
play.health = jjMaxHealth;
}
}
}
jjTEXTAPPEARANCE SpinningString(STRING::SPIN);
bool onDrawHealth(jjPLAYER@ play, jjCANVAS@ screen) {
if (GameWasActive) { //reviving after death, preferably
int intensity = abs(play.blink);
if (intensity > 255) intensity = 255;
if (playerState[play.localPlayerID] == 0)
screen.drawString(jjSubscreenWidth/2, jjSubscreenHeight/2 - 30, "Get Ready", STRING::LARGE, SpinningString, 0, SPRITE::BLEND_NORMAL, intensity);
}
return !(jjGameCustom == GAME::XLRS || jjGameState == GAME::OVERTIME);
}
Jazz2Online © 1999-INFINITY (Site Credits). We have a Privacy Policy. Jazz Jackrabbit, Jazz Jackrabbit 2, Jazz Jackrabbit Advance and all related trademarks and media are ™ and © Epic Games. Lori Jackrabbit is © Dean Dodrill. J2O development powered by Loops of Fury and Chemical Beats.
Eat your lima beans, Johnny.