Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Retroic | FireSworD | Battle | N/A |
const bool MLLESetupSuccessful = MLLE::Setup(); ///@MLLE-Generated
#include "MLLE-Include-1.6.asc" ///@MLLE-Generated
#pragma require "Retroic-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "Retroic.j2l" ///@MLLE-Generated
#pragma require "Meteor.j2a"
#pragma require "expmine.wav"
#pragma require "FTURROCK.wav"
#pragma require "EXPSTD3.wav"
#pragma require "redeemer_flight.wav"
#pragma require "jjnetAmmo_retroic.asc"
#include "jjnetAmmo_retroic.asc"
#pragma require "SpringMushroom.j2a"
#pragma require "S3K_87.wav"
bool controllingRedeemer, warning = false;
int xPos = 0, yPos = 0, cameraX = 0, cameraY = 0, redeemerAngle = 0, CTFArrowTimer = 0;
uint delay = 0;
bool cameraFrozen = false;
float freezeCameraX = 0;
float freezeCameraY = 0;
bool freezeCameraCentered = false;
void pretendFreezeCamera(float x, float y, bool centered) {
cameraFrozen = true;
freezeCameraX = x;
freezeCameraY = y;
freezeCameraCentered = centered;
}
void pretendUnfreezeCamera() {
cameraFrozen = false;
}
void processFrozenCamera(jjPLAYER@ player) {
if (cameraFrozen)
player.cameraFreeze(freezeCameraX, freezeCameraY, freezeCameraCentered, true);
else
player.cameraUnfreeze();
}
int redeemerColor(jjPLAYER@ creator) {
//switch(creator.team) {
//case TEAM::BLUE: return 0;
//case TEAM::RED: return 1;
//case TEAM::GREEN: return 2;
//case TEAM::YELLOW: return 3;
//}
return 0;
}
bool gameIsActive() {
return jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME;
}
bool CTFMode() {
return (jjGameMode == GAME::CTF && jjGameCustom == GAME::NOCUSTOM) || jjGameCustom == GAME::DCTF;
}
bool otherMode() {
return jjGameMode != GAME::CTF || jjGameCustom == GAME::TB || jjGameCustom == GAME::TLRS || jjGameCustom == GAME::DOM;
}
bool isDestructibleItem(jjOBJ@ target) {
return target.eventID == OBJECT::TNT || target.behavior == BEHAVIOR::MONITOR;
}
class vector2i {
int x, y;
}
array<vector2i> oneWays;
void onLevelLoad() {
jjAnimSets[ANIM::CUSTOM[0]].load(0, "SpringMushroom.j2a");
for (int i = 0; i < 9; i++) {
jjAnimations[jjAnimSets[ANIM::SPRING] + i] = jjAnimations[jjAnimSets[ANIM::CUSTOM[0]] + i];
}
jjAnimSets[ANIM::CUSTOM[22]].load(0, "Meteor.j2a");
jjAnimations[jjAnimSets[ANIM::AMMO] + 24] = jjAnimations[jjAnimSets[ANIM::CUSTOM[22]] + 1];
jjAnimations[jjAnimSets[ANIM::AMMO] + 25] = jjAnimations[jjAnimSets[ANIM::CUSTOM[22]] + 2];
jjObjectPresets[OBJECT::BOUNCERBULLET].behavior = jjObjectPresets[OBJECT::BOUNCERBULLETPU].behavior = Meteor();
jjObjectPresets[OBJECT::BOUNCERBULLET].special = jjObjectPresets[OBJECT::BOUNCERBULLET].determineCurAnim(ANIM::CUSTOM[22], 1);
jjObjectPresets[OBJECT::BOUNCERBULLETPU].special = jjObjectPresets[OBJECT::BOUNCERBULLETPU].determineCurAnim(ANIM::CUSTOM[22], 0);
jjObjectPresets[OBJECT::BOUNCERBULLET].ySpeed = jjObjectPresets[OBJECT::BOUNCERBULLETPU].ySpeed = jjObjectPresets[OBJECT::BLASTERBULLET].ySpeed;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].killAnim = jjObjectPresets[OBJECT::SEEKERBULLET].killAnim;
jjObjectPresets[OBJECT::BOUNCERBULLET].lightType = LIGHT::POINT;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].lightType = LIGHT::BRIGHT;
jjObjectPresets[OBJECT::BOUNCERBULLET].light = jjObjectPresets[OBJECT::BOUNCERBULLETPU].light = 10;
jjObjectPresets[OBJECT::BOUNCERAMMO15].determineCurAnim(ANIM::CUSTOM[22], 3);
jjObjectPresets[OBJECT::BOUNCERAMMO15].determineCurFrame();
jjObjectPresets[OBJECT::BOUNCERPOWERUP].determineCurAnim(ANIM::CUSTOM[22], 4);
jjObjectPresets[OBJECT::BOUNCERPOWERUP].determineCurFrame();
jjWeapons[WEAPON::BOUNCER].defaultSample = false;
jjWeapons[WEAPON::BOUNCER].style = WEAPON::MISSILE;
jjSampleLoad(SOUND::ORANGE_BOEMR, "expmine.wav");
jjObjectPresets[OBJECT::TNT].determineCurFrame();
jjObjectPresets[OBJECT::TNT].behavior = Redeemer();
jjObjectPresets[OBJECT::TNT].xSpeed = jjObjectPresets[OBJECT::BLASTERBULLET].xSpeed * 1.33;
jjObjectPresets[OBJECT::TNT].counterEnd = 255;
jjObjectPresets[OBJECT::TNT].killAnim = jjObjectPresets[OBJECT::SEEKERBULLET].killAnim;
jjObjectPresets[OBJECT::REDSPRING].behavior =
jjObjectPresets[OBJECT::GREENSPRING].behavior =
jjObjectPresets[OBJECT::BLUESPRING].behavior =
jjObjectPresets[OBJECT::FROZENSPRING].behavior =
jjObjectPresets[OBJECT::HORREDSPRING].behavior = SpringMushroom();
jjObjectPresets[OBJECT::HORREDSPRING].causesRicochet = false;
jjWeapons[WEAPON::TNT].maximum = 1;
jjAnimSets[ANIM::SONCSHIP].load();
jjAnimSets[ANIM::VINE].load();
jjAnimations[jjAnimSets[ANIM::AMMO] + 59] = jjAnimations[jjAnimSets[ANIM::SONCSHIP] + 0];
jjObjectPresets[OBJECT::THING].determineCurAnim(ANIM::SONCSHIP, 0);
jjObjectPresets[OBJECT::THING].determineCurFrame();
jjObjectPresets[OBJECT::THING].behavior = RedeemerPickup();
jjObjectPresets[OBJECT::THING].scriptedCollisions = true;
generateRedeemerPickupSprite(jjAnimSets[ANIM::CUSTOM[1]], array<uint> = {0});
jjSampleLoad(SOUND::P2_POEP, "FTURROCK.wav");
jjSampleLoad(SOUND::P2_PTOEI, "EXPSTD3.wav");
jjSampleLoad(SOUND::P2_SPLOUT, "redeemer_flight.wav");
jjSampleLoad(SOUND::COMMON_SPRING1, "S3K_87.wav");
jjSampleLoad(SOUND::SPRING_SPRING1, "S3K_87.wav");
jjObjectPresets[OBJECT::BOLLPLATFORM].direction = SPRITE::FLIPH;
jjObjectPresets[OBJECT::FRUITPLATFORM].direction = SPRITE::FLIPH;
jjObjectPresets[OBJECT::PINKPLATFORM].direction = SPRITE::FLIPHV;
jjObjectPresets[OBJECT::PINKPLATFORM].bulletHandling = HANDLING::DESTROYBULLET;
jjANIMFRAME@ frame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::PINKPLAT].firstAnim + 0].firstFrame];
frame.hotSpotY = -12;
setAmmoPresets(OBJECT::BOUNCERAMMO15);
setAmmoPresets(OBJECT::TOASTERAMMO15);
setAmmoPresets(OBJECT::RFAMMO15);
jjObjectPresets[OBJECT::PRETZEL].behavior = WarpOrb();
jjObjectPresets[OBJECT::PRETZEL].lightType = LIGHT::LASER;
jjObjectPresets[OBJECT::PRETZEL].light = 10;
jjObjectPresets[OBJECT::PRETZEL].scriptedCollisions = true;
jjANIMFRAME@ spikebollFrame = jjAnimFrames[jjAnimations[jjAnimSets[ANIM::SPIKEBOLL].firstAnim].firstFrame];
jjPIXELMAP(0, 0, 32, 32, 4).save(spikebollFrame);
spikebollFrame.hotSpotX = -spikebollFrame.width/2;
spikebollFrame.hotSpotY = -spikebollFrame.height + 14;
for (int x = 0; x < jjLayerWidth[1]; x++) {
for (int y = 0; y < jjLayerHeight[1]; y++) {
uint16 myTile = jjTileGet(1, x, y);
if (myTile < 1350) {
jjTileSet(1, x, y, myTile + 1350);
}
}
}
jjANIMFRAME@ CircularGlow = jjAnimFrames[jjObjectPresets[OBJECT::ORANGE].curFrame];
jjPIXELMAP circle(32, 32);
for (uint x = 0; x < circle.width; ++x)
for (uint y = 0; y < circle.height; ++y)
circle[x,y] = (sqrt(pow(16-int(x), 2) + pow(16-int(y), 2)) < 16) ? 234 : 0;
circle.save(CircularGlow);
CircularGlow.hotSpotX = -CircularGlow.width/2;
CircularGlow.hotSpotY = -CircularGlow.height/2;
jjWeapons[WEAPON::TNT].allowed = true;
}
jjANIMSET@ customSpringSprite;
array<int> fastCustomSpringSpeeds(jjLocalPlayerCount);
bool generateCustomSpringSprites(jjANIMSET@ anim, const array<uint> &in colors) {
int length = colors.length();
bool success = (@customSpringSprite = anim).allocate(array<uint>(length * 3, 5)) !is null;
if (success) {
uint srcSet = jjAnimSets[ANIM::SPRING];
for (int i = 0; i < length; i++) {
uint color = colors[i];
uint destAnimOffset = anim + i * 3;
for (int j = 0; j < 3; j++) {
uint srcAnim = jjAnimations[srcSet + j];
uint destAnim = jjAnimations[destAnimOffset + j];
for (int k = 0; k < 5; k++) {
jjPIXELMAP image(jjAnimFrames[destAnim + k] = jjAnimFrames[srcAnim + k]);
int width = image.width;
int height = image.height;
for (int l = 0; l < height; l++) {
for (int m = 0; m < width; m++) {
int pixel = image[m, l];
if (pixel >= 32 && pixel < 40)
image[m, l] = color + (pixel & 7);
}
}
if (!image.save(jjAnimFrames[destAnim + k]))
return false;
}
}
}
}
return success;
}
void initializeCustomSpring(jjOBJ@ obj) {
int anim = obj.curAnim;
obj.behave(obj.behavior = BEHAVIOR::SPRING, false);
if (obj.curAnim != anim) {
obj.curAnim = anim + 2;
obj.determineCurFrame();
}
obj.draw();
}
void turnIntoCustomSpring(jjOBJ@ obj, uint color, float power, bool horizontal) {
if (horizontal) {
obj.xSpeed = power;
obj.ySpeed = 0.f;
} else {
obj.xSpeed = 0.f;
obj.ySpeed = -power;
if (obj.state == STATE::START && obj.creatorType == CREATOR::LEVEL) {
int x = int(obj.xPos) >> 5;
int y = int(obj.yPos) >> 5;
if (jjParameterGet(x, y, 0, 1) != 0) {
jjParameterSet(x, y, 0, 1, 0);
obj.yPos -= 4.f;
obj.ySpeed = power;
}
}
}
obj.behavior = initializeCustomSpring;
obj.curAnim = customSpringSprite + color * 3 + (horizontal ? 1 : 0);
obj.energy = obj.frameID = obj.freeze = obj.justHit = obj.light = obj.points = 0;
obj.isBlastable = obj.isTarget = obj.scriptedCollisions = obj.triggersTNT = false;
obj.deactivates = obj.isFreezable = true;
obj.bulletHandling = HANDLING::IGNOREBULLET;
obj.playerHandling = HANDLING::SPECIAL;
obj.lightType = LIGHT::NORMAL;
obj.determineCurFrame();
}
class Meteor : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE? true:false);
jjPLAYER@ creator = jjPlayers[obj.creatorID];
if (obj.state != STATE::EXPLODE) {
if (obj.counter == 1 && creator.isLocal) {
jjSample(creator.xPos, creator.yPos, SOUND::ORANGE_BOEMR, 42, obj.eventID == OBJECT::BOUNCERBULLET? 22000 : 20000);
obj.var[2] = 0;
}
obj.age += obj.direction == 0? 10 : 10 * obj.direction;
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[22], obj.eventID == OBJECT::BOUNCERBULLET? 1:0, 0, -obj.age, 1, 1, obj.eventID == OBJECT::BOUNCERBULLET || obj.var[4] == 1? SPRITE::SINGLEHUE : SPRITE::NORMAL, 72);
jjPARTICLE@ smoke = jjAddParticle(PARTICLE::SMOKE);
if (smoke !is null) {
smoke.xPos = smoke.xPos;
smoke.yPos = smoke.yPos;
}
if (obj.eventID == OBJECT::BOUNCERBULLETPU && obj.var[4] == 0) {
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[22], 0, 0, -obj.age, 1, 1, SPRITE::TRANSLUCENTSINGLEHUE, 40);
jjPARTICLE@ cinders = jjAddParticle(PARTICLE::FIRE);
if (cinders !is null) {
cinders.xPos = int(obj.xPos - 8) + jjRandom()%17;
cinders.yPos = int(obj.yPos - 8) + jjRandom()%17;
}
}
if (obj.yPos > jjWaterLevel) {
obj.var[4] = 1;
obj.xSpeed = obj.xSpeed * 0.875;
obj.ySpeed = obj.ySpeed * 0.875;
}
switch (obj.direction) {
case 1: obj.xSpeed -= obj.eventID == OBJECT::BOUNCERBULLET? 0.1:0.15; obj.ySpeed += obj.eventID == OBJECT::BOUNCERBULLET? 0.15:0.2; break;
case -1: obj.xSpeed += obj.eventID == OBJECT::BOUNCERBULLET? 0.1:0.15; obj.ySpeed += obj.eventID == OBJECT::BOUNCERBULLET? 0.15:0.2; break;
}
if (obj.xSpeed == 0) obj.ySpeed += 0.4;
if (obj.ySpeed > 8) obj.ySpeed = 8;
} else {
obj.age = 0;
if (obj.var[2] == 0) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BENZIN1, 0, 0);
obj.var[2] = 1;
for (int i = -1; i <= 1; i+= 2) {
Rock temp;
jjOBJ@ rock = jjObjects[jjAddObject(OBJECT::SHARD, int(obj.xPos + (i * 12)), int(obj.yPos - 8), obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
rock.determineCurAnim(obj.eventID == OBJECT::BOUNCERBULLETPU? ANIM::CUSTOM[22] : ANIM::FONT, obj.eventID == OBJECT::BOUNCERBULLETPU? 0:14);
rock.playerHandling = HANDLING::PLAYERBULLET;
rock.var[3] = 2;
rock.var[4] = obj.var[4];
rock.var[5] = obj.eventID == OBJECT::BOUNCERBULLETPU? 0:1;
rock.var[6] = obj.eventID == OBJECT::BOUNCERBULLETPU? 8:0;
rock.special = obj.eventID == OBJECT::BOUNCERBULLETPU? 40:72;
rock.animSpeed = 2;
rock.direction = i;
rock.xSpeed = 6 * i;
rock.ySpeed = -3;
rock.state = STATE::FLY;
rock.lightType = LIGHT::POINT;
rock.light = 10;
rock.counterEnd = jjObjectPresets[OBJECT::BOUNCERBULLET].counterEnd;
rock.killAnim = jjObjectPresets[OBJECT::BOUNCERBULLET].killAnim;
}
}
}
}
}
class Rock : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE? true:false);
if (obj.state == STATE::FLY) {
obj.age += obj.direction == 0? 10 : 10 * obj.direction;
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::CUSTOM[22], obj.var[5] == 0? 0:1, 0, -obj.age, 0.5, 0.5, SPRITE::SINGLEHUE, obj.special);
switch (obj.direction) {
case 1: obj.xSpeed -= 0.05; obj.ySpeed += 0.1; break;
case -1: obj.xSpeed += 0.05; obj.ySpeed += 0.1; break;
}
if (obj.yPos > jjWaterLevel) {
obj.var[4] = 1;
obj.xSpeed = obj.xSpeed * 0.875;
obj.ySpeed = obj.ySpeed * 0.875;
}
jjPARTICLE@ smoke = jjAddParticle(PARTICLE::SMOKE);
if (smoke !is null && obj.var[5] == 2) {
smoke.xPos = obj.xPos;
smoke.yPos = obj.yPos;
}
}
}
}
class Redeemer : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
//var[0] - angle
//var[1] - angular speed
//var[2] - has the redeemer exploded
//special - value of jjGameTicks at the time the last packet was sent/received
int angle;
float speed = jjObjectPresets[OBJECT::TNT].xSpeed;
if (obj.creatorType != CREATOR::PLAYER)
obj.delete();
jjPLAYER@ creator = jjPlayers[obj.creatorID];
switch (obj.state) {
case STATE::START:
obj.curAnim = jjObjectPresets[obj.eventID].curAnim;
jjSamplePriority(SOUND::P2_POEP);
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
obj.ySpeed = speed * -jjSin(obj.var[0]);
obj.xSpeed = speed * jjCos(obj.var[0]);
obj.direction = obj.xSpeed < 0.f ? -1 : 1;
obj.var[2] = 0;
if (creator.isLocal) controllingRedeemer = true;
obj.state = STATE::FLY;
break;
case STATE::FLY:
jjDrawRotatedSprite(obj.xPos, obj.yPos, (creator.isLocal || jjGameMode != GAME::CTF)? ANIM::SONCSHIP : ANIM::CUSTOM[0], (creator.isLocal || jjGameMode != GAME::CTF)? 0 : redeemerColor(creator), obj.curFrame, obj.var[0], 2, 2, SPRITE::NORMAL);
if (creator.isLocal) {
redeemerCamera(creator, obj);
redeemerAngle = obj.var[0];
if (!jjLowDetail && (obj.counter % 131 == 36 || obj.counter == 1) && controllingRedeemer) jjSamplePriority(SOUND::P2_SPLOUT);
float dx = creator.xPos - obj.xPos, dy = creator.yPos - obj.yPos;
if (dx * dx + dy * dy < 420 * 420) warning = true;
else warning = false;
if (creator.health == 0) {
pretendUnfreezeCamera();
controllingRedeemer = false;
} else {
if (controllingRedeemer) {
creator.xSpeed = 0;
if (creator.keyRight && !jjMaskedPixel(int(creator.xPos-16), int(creator.yPos))) creator.xPos -= 0.368f;
if (creator.keyLeft && !jjMaskedPixel(int(creator.xPos+16), int(creator.yPos))) creator.xPos += 0.368f;
}
if (obj.counter >= 21) {
if (controllingRedeemer) {
if (creator.keyRight || (obj.direction < 0 ? creator.keyUp : creator.keyDown)) {
if (obj.var[1] > -16) obj.var[1] = obj.var[1] - 1;
if (obj.var[1] > 0) obj.var[1] = 0;
} else if (creator.keyLeft || (obj.direction < 0 ? creator.keyDown : creator.keyUp)) {
if (obj.var[1] < 16) obj.var[1] = obj.var[1] + 1;
if (obj.var[1] < 0) obj.var[1] = 0;
} else {
obj.var[1] = 0;
}
}
else obj.var[1] = 0;
}
if (obj.counter >= 127)
obj.counter = 35;
else if (obj.counter >= 35 && creator.keyFire && controllingRedeemer)
obj.state = STATE::EXPLODE;
}
xPos = int(obj.xPos);
yPos = int(obj.yPos);
}
if (obj.yPos >= jjLayerHeight[4]*32 || obj.yPos <= 0 || obj.xPos <= 0 || obj.xPos >= jjLayerWidth[4]*32) obj.state = STATE::EXPLODE;
obj.var[0] = obj.var[0] + obj.var[1];
obj.ySpeed = speed * -jjSin(obj.var[0]);
obj.xSpeed = speed * jjCos(obj.var[0]);
if (obj.counter % 3 == 0 && !jjLowDetail) spawnFireTrail(obj);
break;
case STATE::EXPLODE:
if (obj.var[2] == 0) {
RedeemerExplosion temp;
jjOBJ@ explosion = jjObjects[jjAddObject(OBJECT::BULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
jjSamplePriority(SOUND::P2_PTOEI);
obj.var[2] = 1;
explosion.var[2] = 1;
} else {
jjDrawResizedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 5, obj.curFrame + 5, 8, 8, SPRITE::NORMAL, 0, 3, 3);
}
if (creator.isLocal) {
pretendUnfreezeCamera();
controllingRedeemer = false;
}
break;
}
int previousState = obj.state;
obj.behave(BEHAVIOR::BULLET, false);
if (!creator.isLocal) {
if (obj.special + 128 > jjGameTicks)
obj.state = previousState;
} else if (obj.special + 4 <= jjGameTicks) {
jjSTREAM packet;
packet.push(int8(obj.creatorID));
packet.push(obj.state == STATE::EXPLODE);
packet.push(obj.xPos);
packet.push(obj.yPos);
if (obj.state != STATE::EXPLODE) {
packet.push(int16(obj.var[0]));
packet.push(int16(obj.var[1]));
}
jjSendPacket(packet);
obj.special = jjGameTicks;
}
}
}
void spawnFireTrail(jjOBJ@ obj) {
jjOBJ@ trail = jjObjects[jjAddObject(OBJECT::EXPLOSION, int(obj.xPos - jjCos(obj.var[0])), int(obj.yPos - jjSin(obj.var[0])))];
trail.determineCurAnim(ANIM::AMMO, 3);
trail.lightType = LIGHT::POINT;
trail.playerHandling = HANDLING::PARTICLE;
trail.bulletHandling = HANDLING::IGNOREBULLET;
trail.isBlastable = false;
}
void redeemerCamera(jjPLAYER@ creator, jjOBJ@ obj) {
float dx = jjLayerWidth[4] - obj.xPos, dy = jjLayerHeight[4] - obj.yPos;
if (jjLayerWidth[4] - dx <= 400) cameraX = 400;
else cameraX = int(obj.xPos);
if (jjLayerHeight[4] - dy <= 400) cameraY = 400;
else cameraY = int(obj.yPos);
if (controllingRedeemer) {
pretendFreezeCamera(int(obj.xPos) >= 8528? 8528 : cameraX, int(obj.yPos) >= 4080? 4080 : cameraY, true);
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
float reticleScale = jjSin(jjGameTicks*5);
float reticleColor = jjSin(jjGameTicks*10)*2;
float pdx = play.xPos - obj.xPos, pdy = play.yPos - obj.yPos;
if ((pdx * pdx + pdy * pdy < 320 * 320) && (jjGameMode != GAME::CTF || jjFriendlyFire || play.team != creator.team) && !play.isLocal)
jjDrawResizedSprite(play.xPos, play.yPos, ANIM::SONCSHIP, 7, 0, reticleScale + 2, reticleScale + 2, SPRITE::SINGLECOLOR, int(reticleColor + 18), 1);
}
}
}
class RedeemerPickup : jjBEHAVIORINTERFACE {
float getY(const ::jjOBJ@ obj) const {
int arg = (((obj.objectID << 3) + ::jjGameTicks) << (obj.yPos > ::jjWaterLevel ? 1 : 4)) + (int(obj.xPos) << 4);
return obj.yPos + ::jjSin(arg) * 4.f;
}
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP, false);
jjDrawResizedSprite(int(obj.xPos) - (6 * obj.direction), getY(obj), ANIM::CUSTOM[1], 0, obj.curFrame, 2 * obj.direction, 2, ((obj.xPos < 4464 && jjLocalPlayers[0].team == TEAM::BLUE) || (obj.xPos > 4464 && jjLocalPlayers[0].team == TEAM::RED))? SPRITE::NORMAL : SPRITE::NORMAL);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
if (play.ammo[WEAPON::TNT] < jjWeapons[WEAPON::TNT].maximum) {
if (play.isLocal) {
play.ammo[WEAPON::TNT] = play.ammo[WEAPON::TNT] + 1;
if (jjAutoWeaponChange) play.currWeapon = WEAPON::TNT;
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_LOADSPAZ, 0, 0);
if (play.charCurr == CHAR::JAZZ) {
jjSample(play.xPos, play.yPos, SOUND::JAZZSOUNDS_JUMMY, 0, 0);
}
if (play.charCurr == CHAR::SPAZ) {
jjSample(play.xPos, play.yPos, SOUND::SPAZSOUNDS_HAPPY, 0, 0);
}
if (play.charCurr == CHAR::LORI) {
jjSample(play.xPos, play.yPos, SOUND::LORISOUNDS_WEHOO, 0, 0);
}
}
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
}
return true;
}
}
class RedeemerExplosion : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
//var[0] - obj.counter
//var[2] - has the redeemer exploded
//var[4] - blast radius
//var[5] - damage
//var[8] - has the player been hit by the explosion
obj.playerHandling = HANDLING::PARTICLE;
obj.bulletHandling = HANDLING::IGNOREBULLET;
obj.lightType = obj.var[2] == 1? LIGHT::RING2 : LIGHT::NONE;
jjPLAYER@ creator = jjPlayers[obj.creatorID];
jjPLAYER@ play = jjLocalPlayers[0];
if (obj.var[2] == 1) {
obj.var[0] = obj.var[0] + 1;
obj.light += 2;
obj.var[4] = obj.light * 5;
if (obj.var[4] >= 460) obj.var[5] = 1;
else if (obj.var[4] >= 360 && obj.var[4] < 460) obj.var[5] = 2;
else if (obj.var[4] < 360) obj.var[5] = 7;
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ target = jjObjects[i];
float dx = target.xPos - obj.xPos, dy = target.yPos - obj.yPos;
if (isDestructibleItem(target) && target.var[4] == 0) {
if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
if (target.eventID != OBJECT::TNT) {
if (creator.isLocal) creator.objectHit(target, -1, HANDLING::SPECIAL);
} else target.state = STATE::EXPLODE;
target.var[4] = 1;
}
else target.var[4] = 0;
}
else if (target.behavior == BEHAVIOR::PICKUP && target.state == STATE::FLOAT) {
if (dx * dx + dy * dy < obj.var[4] * obj.var[4])
target.state = STATE::FLOATFALL;
}
}
float pdx = play.xPos - obj.xPos, pdy = play.yPos - obj.yPos;
if (!controllingRedeemer && pdx * pdx + pdy * pdy < 1600 * 1600) {
uint random = jjRandom();
int magnitude = (2 << (random & 3)) - 1;
int halfMagnitude = magnitude >> 1;
if ((jjGameTicks & 1 == 0 && !jjTriggers[19]) || (jjGameTicks & 1 == 0 && jjTriggers[19] && jjMaskedHLine(int(play.xPos) - 12, 24, int(play.yPos) + 21)))
pretendFreezeCamera(play.cameraX + (random & magnitude) - halfMagnitude, play.cameraY + (random >> 8 & magnitude) - halfMagnitude, false);
else
pretendUnfreezeCamera();
}
}
if (jjIsServer && gameIsActive()) {
for (int i = 0; i < 32; i++) {
jjPLAYER@ player = jjPlayers[i];
if (
player.isActive && player.isInGame && player.health > 0 && gameIsActive()
&& ((jjGameMode != GAME::CTF && jjGameCustom != GAME::PEST && jjGameCustom != GAME::RT) || jjFriendlyFire || player.team != creator.team || player is creator)
) {
float dx = player.xPos - obj.xPos, dy = player.yPos - obj.yPos;
if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
if (obj.var[8] & 1 << i == 0) {
player.hurt(obj.var[5], true, creator);
obj.var[8] = obj.var[8] | 1 << i;
}
}
}
}
}
if (obj.var[0] == 1) {
jjSample(obj.xPos, obj.yPos, SOUND::BILSBOSS_FIRE, 0, 0);
for (int i = -8; i <= 8; i+=8) {
for (int j = -8; j <= 8; j+=8) {
if (i != 0 || j != 0) {
Fireworks temp;
int id = jjAddObject(OBJECT::ELECTROBULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave));
if (id != 0) {
jjOBJ@ flares = jjObjects[id];
flares.xSpeed = j*2;
flares.ySpeed = i*2;
}
}
}
}
}
else if (obj.var[0] == 70) {
obj.var[0] = 0;
obj.var[2] = 0;
obj.var[4] = 0;
if (!controllingRedeemer) pretendUnfreezeCamera();
obj.delete();
}
}
}
class Fireworks : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::ELECTROBULLET, false);
obj.counterEnd = 210;
if (obj.ySpeed < 10 && obj.xSpeed != 0) obj.ySpeed += 0.5;
obj.playerHandling = HANDLING::PARTICLE;
obj.bulletHandling = HANDLING::IGNOREBULLET;
if (obj.state == STATE::FLY) obj.particlePixelExplosion(1);
}
}
class WarpOrb : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
if (obj.state == STATE::START) {
obj.xPos = obj.xOrg += 16;
obj.yPos = obj.yOrg += 8;
}
obj.behave(BEHAVIOR::PICKUP, false);
if (obj.state == STATE::FLOATFALL) obj.state = STATE::FLOAT;
}
void onDraw(jjOBJ@ obj) {
int frame = obj.objectID * 8 + jjGameTicks;
frame = (frame + int(obj.xPos) + int(obj.yPos) * 256)*16;
jjDrawTile(obj.xPos- 16, (obj.yPos + jjSin(frame)*4) - 18, 8 + TILE::ANIMATED);
jjDrawSprite(obj.xPos, obj.yPos + jjSin(frame)*4, ANIM::SPIKEBOLL, 0, 0, 0, SPRITE::TRANSLUCENT, 255);
jjDrawSprite(obj.xPos, obj.yPos + jjSin(frame)*4, ANIM::SPIKEBOLL, 0, 0, 0, SPRITE::BLEND_COLOR, 255);
jjDrawSprite(obj.xPos, obj.yPos + jjSin(frame)*4, ANIM::SPIKEBOLL, 0, 0, 0, SPRITE::TRANSLUCENT, 255);
//jjDrawString(obj.xPos + 48, obj.yPos, "" + VeryCoolMathWizFunction(jjGameTicks));
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
player.warpToID(0);
jjSample(player.xPos, player.yPos, SOUND::COMMON_PICKUP1, 63, 17500);
obj.frameID = 0;
obj.behavior = BEHAVIOR::EXPLOSION2;
return true;
}
}
void onReceive(jjSTREAM &in packet, int clientID) {
int8 playerID;
bool explosion;
float xPos, yPos;
int16 angle, angleSpeed;
jjSTREAM packetBackup;
if (jjIsServer)
packetBackup = packet;
if (packet.pop(playerID) && playerID >= 0 && playerID < 32 &&
packet.pop(explosion) && packet.pop(xPos) && packet.pop(yPos) &&
(explosion || packet.pop(angle) && packet.pop(angleSpeed))
) {
const jjPLAYER@ player = jjPlayers[playerID];
if (!jjIsServer || player.isActive && player.isInGame && player.clientID == clientID ) {
jjOBJ@ redeemer;
for (int i = 0; i < jjObjectCount; i++) {
jjOBJ@ obj = jjObjects[i];
if (obj.isActive && obj.eventID == OBJECT::TNT && obj.creatorType == CREATOR::PLAYER && obj.creatorID == uint(playerID)) {
@redeemer = obj;
break;
}
}
if (redeemer is null && jjGameTicks < 140) {
int id = jjAddObject(OBJECT::TNT, xPos, yPos, playerID, CREATOR::PLAYER);
if (id > 0)
@redeemer = jjObjects[id];
}
if (redeemer !is null) {
if (jjIsServer)
jjSendPacket(packetBackup, -clientID);
if (explosion)
redeemer.state = STATE::EXPLODE;
redeemer.xPos = xPos;
redeemer.yPos = yPos;
redeemer.var[0] = angle;
redeemer.var[1] = angleSpeed;
redeemer.special = jjGameTicks;
}
}
}
}
bool onDrawAmmo(jjPLAYER@ play, jjCANVAS@ canvas) {
if (controllingRedeemer) {
canvas.drawString(
jjSubscreenWidth - 480,
jjSubscreenHeight - 450,
"Redeemer!",
STRING::MEDIUM,
STRING::NORMAL
);
//canvas.drawString(
//jjSubscreenWidth - 496,
//jjSubscreenHeight - 422,
//"Redeemer pos " + int(xPos / 32) + "," + int(yPos / 32),
//STRING::SMALL,
//STRING::NORMAL
//);
canvas.drawString(
jjSubscreenWidth - 624,
jjSubscreenHeight - 406,
"|Use the |||movement keys |||||to rotate the missile",
STRING::SMALL,
STRING::NORMAL
);
canvas.drawString(
jjSubscreenWidth - 625,
jjSubscreenHeight - 390,
"|Press |||FIRE |||||to detonate the missile in mid-air",
STRING::SMALL,
STRING::NORMAL
);
canvas.drawRectangle(
jjSubscreenWidth - 750,
jjSubscreenHeight - 240,
140,
140,
87,
SPRITE::TRANSLUCENT
);
canvas.drawString(
jjSubscreenWidth - 708,
jjSubscreenHeight - 108,
"Radar",
STRING::SMALL,
STRING::PALSHIFT,
16
);
canvas.drawRotatedSprite(
jjSubscreenWidth - 680,
jjSubscreenHeight - 170,
ANIM::CUSTOM[1],
0,
jjGameTicks >> 2,
redeemerAngle,
1,
1,
SPRITE::SINGLEHUE,
80
);
for (int i = 0; i < 32; i++) {
jjPLAYER@ player = jjPlayers[i];
uint8 teamColor;
switch (player.team) {
case TEAM::BLUE: teamColor = 34; break;
case TEAM::RED: teamColor = 24; break;
case TEAM::GREEN: teamColor = 18; break;
case TEAM::YELLOW: teamColor = 40; break;
default: teamColor = 24; break;
}
int radarOffsetX = int(xPos - player.xPos) / 35;
int radarOffsetY = int(yPos - player.yPos) / 35;
if (radarOffsetX < 70 && radarOffsetX > -63 && radarOffsetY < 70 && radarOffsetY > -63 && player.xPos > 0 && player.yPos > 0 && !play.isSpectating && !play.isOut && !play.isConnecting) {
if (player.flag != 0 && !player.isLocal) {
canvas.drawResizedSprite(
((jjSubscreenWidth - 678) - radarOffsetX),
((jjSubscreenHeight - 168) - radarOffsetY),
ANIM::FLAG,
3,
jjGameTicks >> 2,
radarOffsetX > 0? 0.4:-0.4,
0.4,
SPRITE::SINGLECOLOR,
player.team == TEAM::BLUE? 24 : 34
);
canvas.drawRectangle(
((jjSubscreenWidth - 680) - radarOffsetX),
((jjSubscreenHeight - 170) - radarOffsetY),
6,
6,
teamColor,
SPRITE::NORMAL
);
}
else if (player.flag == 0) {
canvas.drawRectangle(
((jjSubscreenWidth - 680) - radarOffsetX),
((jjSubscreenHeight - 170) - radarOffsetY),
player.isLocal? 8:6,
player.isLocal? 8:6,
player.isLocal? 64 : jjGameMode == GAME::CTF? teamColor : 24,
SPRITE::NORMAL
);
}
}
for (int j = 1; j < jjObjectCount; j++) {
if (jjObjects[j].eventID == OBJECT::TNT) {
uint8 redeemerColor;
switch (jjPlayers[jjObjects[j].creatorID].team) {
case TEAM::BLUE: redeemerColor = 34; break;
case TEAM::RED: redeemerColor = 24; break;
case TEAM::GREEN: redeemerColor = 18; break;
case TEAM::YELLOW: redeemerColor = 40; break;
default: redeemerColor = 88; break;
}
int radarMissileOffsetX = int(xPos - jjObjects[j].xPos) / 35;
int radarMissileOffsetY = int(yPos - jjObjects[j].yPos) / 35;
if (!jjPlayers[jjObjects[j].creatorID].isLocal && radarMissileOffsetX < 70 && radarMissileOffsetX > -63 && radarMissileOffsetY < 70 && radarMissileOffsetY > -63) {
canvas.drawRotatedSprite(
((jjSubscreenWidth - 680) - radarMissileOffsetX),
((jjSubscreenHeight - 170) - radarMissileOffsetY),
ANIM::CUSTOM[1],
0,
jjGameTicks >> 2,
jjObjects[j].var[0],
0.5,
0.5,
SPRITE::SINGLECOLOR,
jjGameMode == GAME::CTF? redeemerColor : 90
);
}
}
}
}
if (warning) {
canvas.drawString(
jjSubscreenWidth - 550,
jjSubscreenHeight - 374,
"||WARNING: YOU ARE IN RANGE!",
STRING::SMALL,
STRING::NORMAL
);
}
if (!jjLowDetail && jjGameTicks % 140 >= 7) {
canvas.drawString(
jjSubscreenWidth - 132,
jjSubscreenHeight - 46,
"REC",
STRING::MEDIUM,
STRING::NORMAL
);
canvas.drawSprite(
jjSubscreenWidth - 146,
jjSubscreenHeight - 45,
ANIM::VINE,
0,
0,
0,
SPRITE::NORMAL
);
}
}
else if (!controllingRedeemer && play.currWeapon == WEAPON::TNT) {
canvas.drawString(
jjSubscreenWidth - 80,
jjSubscreenHeight - 14,
"x" + play.ammo[WEAPON::TNT],
STRING::MEDIUM,
STRING::NORMAL
);
canvas.drawResizedSprite(
jjSubscreenWidth - 110,
jjSubscreenHeight - 14,
ANIM::CUSTOM[1],
0,
jjGameTicks >> 2,
2,
2,
SPRITE::NORMAL
);
}
return controllingRedeemer || play.currWeapon == WEAPON::TNT;
}
jjANIMSET@ redeemerPickupSprite;
bool generateRedeemerPickupSprite(jjANIMSET@ anim, const array<uint> &in colors) {
int length = colors.length();
bool success = (@redeemerPickupSprite = anim).allocate(array<uint>(length, 8)) !is null;
if (success) {
uint srcSet = jjAnimSets[ANIM::SONCSHIP];
for (int i = 0; i < length; i++) {
uint color = colors[i];
uint destAnimOffset = anim + i;
uint srcAnim = jjAnimations[srcSet + 0];
uint destAnim = jjAnimations[destAnimOffset + 0];
for (int k = 0; k < 8; k++) {
jjPIXELMAP image(jjAnimFrames[destAnim + k] = jjAnimFrames[srcAnim + k]);
int width = image.width;
int height = image.height;
for (int l = 0; l < height; l++) {
for (int m = 0; m < width; m++) {
int pixel = image[m, l];
if (pixel >= 40 && pixel < 48)
image[m, l] = color;
}
}
if (!image.save(jjAnimFrames[destAnim + k]))
return false;
}
}
}
return success;
}
void onMain() {
array<jjLAYER@> layers = jjLayerOrderGet();
layers[8].xOffset -=1;
layers[9].xOffset -=0.2f;
if (layers[8].xOffset % (layers[8].widthReal*32) == 0) layers[8].xOffset = 0;
if (layers[9].xOffset % (layers[9].widthReal*32) == 0) layers[9].xOffset = 0;
layers[8].yOffset += jjSin(jjGameTicks*10)/5;
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ obj = jjObjects[i];
if (obj.isActive && obj.eventID == OBJECT::COPTER && obj.state == STATE::FLY) {
obj.counter = 0;
if (obj.var[4] == 0)
obj.state = STATE::DONE;
}
}
}
void onPlayer(jjPLAYER@ play) {
processFrozenCamera(play);
if (controllingRedeemer) play.currWeapon = WEAPON::BLASTER;
for (uint i = 0; i < oneWays.length(); i++) {
jjEventSet(oneWays[i].x, oneWays[i].y, AREA::ONEWAY);
}
oneWays.resize(0);
int px = int(play.xPos), py = int(play.yPos);
bool masked;
for (int i = -11 + int(play.ySpeed); i <= 14; i++) {
if (masked = jjMaskedHLine(px - 14, 28, py + i))
break;
}
if (!masked) {
for (int i = 8; i <= 16; i += 8) {
for (int j = 12; j <= 20; j += 8) {
int x = (px + play.direction * j) >>> 5, y = (py + i) >>> 5;
if (x >= 0 && y >= 0 && x < jjLayerWidth[4] && y < jjLayerHeight[4] && jjEventGet(x, y) == AREA::ONEWAY) {
vector2i point;
jjEventSet(point.x = x, point.y = y, 0);
oneWays.insertLast(point);
}
}
}
}
}
void onLevelReload() {
MLLE::Palette.apply();
}
void onLevelBegin() {
for (int i = 1; i < 255; i++) {
jjOBJ@ preset = jjObjectPresets[i];
if (preset.playerHandling == HANDLING::PICKUP) {
preset.behavior = CannotBeShotDown(preset.behavior);
}
}
}
class CannotBeShotDown : jjBEHAVIORINTERFACE {
CannotBeShotDown(const jjBEHAVIOR &in behavior) {
originalBehavior = behavior;
}
void onBehave(jjOBJ@ obj) {
obj.behave(originalBehavior);
if (obj.state == STATE::FLOATFALL)
obj.state = STATE::FLOAT;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
if (bullet is null) {
obj.behavior = originalBehavior;
if (player.objectHit(obj, force, obj.playerHandling))
return true;
obj.behavior = this;
}
return false;
}
private jjBEHAVIOR originalBehavior;
}
class SpringMushroom : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::SPRING, false);
jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos - 16, obj.curFrame, obj.eventID != OBJECT::HORREDSPRING? 0: obj.direction == 0? 0:512, 2, 2, SPRITE::NORMAL);
if (obj.state == STATE::SPRING && !jjLowDetail) {
jjPARTICLE@ spores = jjAddParticle(PARTICLE::FIRE);
if (spores !is null) {
spores.xPos = int(obj.xPos - 28) + (jjRandom()%28)*2;
spores.yPos = int(obj.yPos - 14) + jjRandom()%14;
if (jjRandom()%2 > 0)
spores.ySpeed = -1;
else spores.ySpeed = -0.6;
spores.fire.color = 64;
spores.fire.colorStop = 72;
}
}
}
}
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.