| Name | Author | Game Mode | Rating | |||||
|---|---|---|---|---|---|---|---|---|
| One Battle1 After Another | cooba | Multiple | N/A | |||||
| Asteroid Armada | PurpleJazz | Battle | N/A | |||||
#pragma name "Spaceship (v1.11)"
#pragma description "Turns JJ2 into a spaceship shoot-em-up."
#pragma require "Spaceship.j2a"
#pragma require "Spaceship v1-11.asc"
#pragma require "Silence.wav"
#include "Resize v11.asc"
#include "MLLE-Weapons.asc"
const float PI = 3.1415927f;
namespace Spaceship {
bool animsLoaded = false;
uint customAnimID = 0;
class SPACESHIP {
float xSpeed, ySpeed, xAcc, yAcc, xMomentum, yMomentum, fireAngle, momentum = 0;
float maxSpeed = 8;
float maxTurningSpeed = 7;
float maxSpeedRev = 6;
float maxTurningSpeedRev = 4.5;
float maxDiagonalSpeed = 7.5;
float rotationAcc = 0;
int health, anim, angle, sample, sample2, fireDelay, hitDelay, armor, damageAccumulated, accumulationTime, rotationSpeed, kamikazeCooldown;
int powerTime = 30*70;
int boostTime = 2.5*70;
int damageCalc(SPACESHIP@ ship, int animSpeed) {
if (ship.armor >= animSpeed) {
return (animSpeed / 3);
} else {
return (animSpeed - (ship.armor / 3 * 2));
}
}
bool thrust, reverse, boost, rotating, fire, justHit, wasHit, stopWeaponChange, powerUp, SDPunishment, tntPowerup, kamikaze, killShip = false;
bool hasShip = true;
SPACESHIP(){}
};
array<SPACESHIP> Ships(32);
const float PI = 3.1415926535f;
int xPos = 0, yPos = 0, cameraX = 0, cameraY = 0, radarX = 100, radarY = jjSubscreenHeight - 220;
array<int> closestPlayers(32, -1); //needed even for non-local players
uint8 currentWeapon, bufferedWeapon = 1;
bool crosshairFlash = false;
int crosshairTime = 0;
bool gameIsActive() {
return jjGameState == GAME::STARTED || jjGameState == GAME::OVERTIME;
}
bool canBeHit(jjPLAYER@ play, jjPLAYER@ creator, jjOBJ@ obj) {
SPACESHIP@ ship = Ships[creator.playerID];
return play !is null && (play !is creator || obj.eventID == OBJECT::BULLET) && play.blink == 0 && play.health > 0 && (creator.blink == 0 || ship.kamikaze) && obj.state != STATE::EXPLODE && (creator.isEnemy(play) || (play is creator && obj.eventID == OBJECT::BULLET)) && gameIsActive();
}
float recoilX(SPACESHIP@ ship, jjOBJ@ obj, float recoil) {
return ((obj.xSpeed / (ship.thrust? 16:128)) * recoil);
}
float recoilY(SPACESHIP@ ship, jjOBJ@ obj, float recoil) {
return ((obj.ySpeed / (ship.thrust? 16:128)) * recoil);
}
int teamColor(jjPLAYER@ play) {
if (play.team == TEAM::BLUE) return 32;
if (play.team == TEAM::RED) return 24;
if (play.team == TEAM::YELLOW) return 40;
if (play.team == TEAM::GREEN) return 16;
return 32;
}
bool isAlly(jjPLAYER@ creator, jjPLAYER@ play) {
return !creator.isLocal && jjGameMode == GAME::CTF && creator.team == play.team;
}
bool active = true;
int maxHealth;
bool showInstructions = false;
array<bool> pressOnce(3, false);
int currPage = 1;
void handleOnLevelLoad() {
if (!animsLoaded) {
animsLoaded = true;
while (jjAnimSets[ANIM::CUSTOM[customAnimID]] != 0)
++customAnimID;
customAnimID = ANIM::CUSTOM[customAnimID];
jjAnimSets[customAnimID].load(0, "Spaceship.j2a");
}
jjAnimSets[ANIM::DEVAN].load();
jjAnimSets[ANIM::MENU].load();
jjWeapons[WEAPON::BLASTER].infinite = false;
jjWeapons[WEAPON::BLASTER].maximum = 25;
jjWeapons[WEAPON::BLASTER].defaultSample = false;
jjObjectPresets[OBJECT::BLASTERBULLET].xSpeed = jjObjectPresets[OBJECT::BLASTERBULLET].xSpeed * -2.5;
jjObjectPresets[OBJECT::BLASTERBULLET].ySpeed = 0;
jjObjectPresets[OBJECT::BLASTERBULLET].xAcc = 0;
jjObjectPresets[OBJECT::BLASTERBULLET].yAcc = 0;
jjObjectPresets[OBJECT::BLASTERBULLET].counterEnd = 65;
jjObjectPresets[OBJECT::BLASTERBULLET].behavior = Blaster();
jjObjectPresets[OBJECT::BLASTERBULLET].special = jjObjectPresets[OBJECT::BLASTERBULLET].determineCurAnim(ANIM::DEVAN, 0);
jjObjectPresets[OBJECT::BLASTERBULLET].determineCurFrame();
jjObjectPresets[OBJECT::BLASTERBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::BLASTERBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::BLASTERBULLET].animSpeed = 12;
jjObjectPresets[OBJECT::BLASTERBULLET].triggersTNT = true;
jjObjectPresets[OBJECT::BLASTERBULLETPU].xSpeed = jjObjectPresets[OBJECT::BLASTERBULLETPU].xSpeed * -2.5;
jjObjectPresets[OBJECT::BLASTERBULLETPU].ySpeed = 0;
jjObjectPresets[OBJECT::BLASTERBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::BLASTERBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::BLASTERBULLETPU].counterEnd = 65;
jjObjectPresets[OBJECT::BLASTERBULLETPU].behavior = Blaster();
jjObjectPresets[OBJECT::BLASTERBULLETPU].special = jjObjectPresets[OBJECT::BLASTERBULLETPU].determineCurAnim(ANIM::DEVAN, 0);
jjObjectPresets[OBJECT::BLASTERBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::BLASTERBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::BLASTERBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::BLASTERBULLETPU].animSpeed = 24;
jjObjectPresets[OBJECT::BLASTERBULLETPU].triggersTNT = true;
jjWeapons[WEAPON::BOUNCER].maximum = 100;
jjWeapons[WEAPON::BOUNCER].defaultSample = false;
jjObjectPresets[OBJECT::BOUNCERBULLET].xSpeed = jjObjectPresets[OBJECT::BOUNCERBULLET].xSpeed * -3;
jjObjectPresets[OBJECT::BOUNCERBULLET].ySpeed = 0;
jjObjectPresets[OBJECT::BOUNCERBULLET].xAcc = 0;
jjObjectPresets[OBJECT::BOUNCERBULLET].yAcc = 0;
jjObjectPresets[OBJECT::BOUNCERBULLET].counterEnd = 70;
jjObjectPresets[OBJECT::BOUNCERBULLET].behavior = RapidBlaster();
jjObjectPresets[OBJECT::BOUNCERBULLET].special = jjObjectPresets[OBJECT::BOUNCERBULLET].determineCurAnim(ANIM::AMMO, 27);
jjObjectPresets[OBJECT::BOUNCERBULLET].determineCurFrame();
jjObjectPresets[OBJECT::BOUNCERBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::BOUNCERBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::BOUNCERBULLET].animSpeed = 4;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].xSpeed = jjObjectPresets[OBJECT::BOUNCERBULLETPU].xSpeed * -3;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].ySpeed = 0;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].counterEnd = 70;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].behavior = RapidBlaster();
jjObjectPresets[OBJECT::BOUNCERBULLETPU].special = jjObjectPresets[OBJECT::BOUNCERBULLETPU].determineCurAnim(ANIM::AMMO, 60);
jjObjectPresets[OBJECT::BOUNCERBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::BOUNCERBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::BOUNCERBULLETPU].animSpeed = 8;
jjWeapons[WEAPON::ICE].maximum = 25;
jjWeapons[WEAPON::ICE].defaultSample = false;
jjWeapons[WEAPON::ICE].spread = SPREAD::RFPU;
jjObjectPresets[OBJECT::ICEBULLET].xSpeed = jjObjectPresets[OBJECT::ICEBULLET].xSpeed * -3;
jjObjectPresets[OBJECT::ICEBULLET].ySpeed = 0;
jjObjectPresets[OBJECT::ICEBULLET].xAcc = 0;
jjObjectPresets[OBJECT::ICEBULLET].yAcc = 0;
jjObjectPresets[OBJECT::ICEBULLET].counterEnd = 15;
jjObjectPresets[OBJECT::ICEBULLET].freeze = 0;
jjObjectPresets[OBJECT::ICEBULLET].var[7] = 0;
jjObjectPresets[OBJECT::ICEBULLET].behavior = IceBurster();
jjObjectPresets[OBJECT::ICEBULLET].special = jjObjectPresets[OBJECT::ICEBULLET].determineCurAnim(ANIM::PICKUPS, 45);
jjObjectPresets[OBJECT::ICEBULLET].determineCurFrame();
jjObjectPresets[OBJECT::ICEBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::ICEBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::ICEBULLET].animSpeed = 25;
jjObjectPresets[OBJECT::ICEBULLETPU].xSpeed = jjObjectPresets[OBJECT::ICEBULLETPU].xSpeed * -3;
jjObjectPresets[OBJECT::ICEBULLETPU].ySpeed = 0;
jjObjectPresets[OBJECT::ICEBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::ICEBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::ICEBULLETPU].counterEnd = 15;
jjObjectPresets[OBJECT::ICEBULLETPU].freeze = 0;
jjObjectPresets[OBJECT::ICEBULLETPU].var[7] = 0;
jjObjectPresets[OBJECT::ICEBULLETPU].behavior = IceBurster();
jjObjectPresets[OBJECT::ICEBULLETPU].special = jjObjectPresets[OBJECT::ICEBULLETPU].determineCurAnim(ANIM::PICKUPS, 45);
jjObjectPresets[OBJECT::ICEBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::ICEBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::ICEBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::ICEBULLETPU].animSpeed = 50;
jjObjectPresets[OBJECT::ICEBULLETPU].killAnim = jjObjectPresets[OBJECT::RFBULLET].killAnim;
jjWeapons[WEAPON::SEEKER].maximum = 15;
jjObjectPresets[OBJECT::SEEKERBULLET].xSpeed = jjObjectPresets[OBJECT::SEEKERBULLET].xSpeed * -5.5;
jjObjectPresets[OBJECT::SEEKERBULLET].ySpeed = jjObjectPresets[OBJECT::SEEKERBULLET].ySpeed * 5.5;
jjObjectPresets[OBJECT::SEEKERBULLET].xAcc = 0;
jjObjectPresets[OBJECT::SEEKERBULLET].yAcc = 0;
jjObjectPresets[OBJECT::SEEKERBULLET].counterEnd = 160;
jjObjectPresets[OBJECT::SEEKERBULLET].lightType = jjObjectPresets[OBJECT::BLASTERBULLET].lightType;
jjObjectPresets[OBJECT::SEEKERBULLET].behavior = HomingMissile();
jjObjectPresets[OBJECT::SEEKERBULLET].special = jjObjectPresets[OBJECT::SEEKERBULLET].determineCurAnim(ANIM::AMMO, 37);
jjObjectPresets[OBJECT::SEEKERBULLET].determineCurFrame();
jjObjectPresets[OBJECT::SEEKERBULLET].killAnim = jjObjectPresets[OBJECT::SEEKERBULLET].killAnim;
jjObjectPresets[OBJECT::SEEKERBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::SEEKERBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::SEEKERBULLET].animSpeed = 30;
jjObjectPresets[OBJECT::SEEKERBULLETPU].xSpeed = jjObjectPresets[OBJECT::SEEKERBULLETPU].xSpeed * -5.5;
jjObjectPresets[OBJECT::SEEKERBULLETPU].ySpeed = jjObjectPresets[OBJECT::SEEKERBULLETPU].ySpeed * 5.5;
jjObjectPresets[OBJECT::SEEKERBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::SEEKERBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::SEEKERBULLETPU].counterEnd = 180;
jjObjectPresets[OBJECT::SEEKERBULLETPU].lightType = jjObjectPresets[OBJECT::BLASTERBULLET].lightType;
jjObjectPresets[OBJECT::SEEKERBULLETPU].behavior = HomingMissile();
jjObjectPresets[OBJECT::SEEKERBULLETPU].special = jjObjectPresets[OBJECT::SEEKERBULLETPU].determineCurAnim(ANIM::AMMO, 42);
jjObjectPresets[OBJECT::SEEKERBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::SEEKERBULLETPU].killAnim = jjObjectPresets[OBJECT::SEEKERBULLETPU].killAnim;
jjObjectPresets[OBJECT::SEEKERBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::SEEKERBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::SEEKERBULLETPU].animSpeed = 60;
jjWeapons[WEAPON::RF].maximum = 10;
jjWeapons[WEAPON::RF].spread = SPREAD::NORMAL;
jjWeapons[WEAPON::RF].defaultSample = false;
jjObjectPresets[OBJECT::RFBULLET].xSpeed = jjObjectPresets[OBJECT::RFBULLET].xSpeed * -10;
jjObjectPresets[OBJECT::RFBULLET].ySpeed = jjObjectPresets[OBJECT::RFBULLET].ySpeed * -10;
jjObjectPresets[OBJECT::RFBULLET].xAcc = 0;
jjObjectPresets[OBJECT::RFBULLET].yAcc = 0;
jjObjectPresets[OBJECT::RFBULLET].counterEnd = 180;
jjObjectPresets[OBJECT::RFBULLET].lightType = LIGHT::NONE;
jjObjectPresets[OBJECT::RFBULLET].behavior = SuperMissile();
jjObjectPresets[OBJECT::RFBULLET].special = jjObjectPresets[OBJECT::RFBULLET].determineCurAnim(ANIM::SONCSHIP, 0);
jjObjectPresets[OBJECT::RFBULLET].determineCurFrame();
jjObjectPresets[OBJECT::RFBULLET].killAnim = jjObjectPresets[OBJECT::SEEKERBULLET].killAnim;
jjObjectPresets[OBJECT::RFBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::RFBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::RFBULLET].animSpeed = 90;
jjObjectPresets[OBJECT::RFBULLETPU].xSpeed = jjObjectPresets[OBJECT::RFBULLETPU].xSpeed * -10;
jjObjectPresets[OBJECT::RFBULLETPU].ySpeed = jjObjectPresets[OBJECT::RFBULLETPU].ySpeed * -10;
jjObjectPresets[OBJECT::RFBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::RFBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::RFBULLETPU].counterEnd = 180;
jjObjectPresets[OBJECT::RFBULLETPU].lightType = LIGHT::NONE;
jjObjectPresets[OBJECT::RFBULLETPU].behavior = SuperMissile();
jjObjectPresets[OBJECT::RFBULLETPU].special = jjObjectPresets[OBJECT::RFBULLETPU].determineCurAnim(ANIM::SONCSHIP, 0);
jjObjectPresets[OBJECT::RFBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::RFBULLETPU].killAnim = jjObjectPresets[OBJECT::SEEKERBULLET].killAnim;
jjObjectPresets[OBJECT::RFBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::RFBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::RFBULLETPU].animSpeed = 180;
jjWeapons[WEAPON::TOASTER].maximum = 50;
jjWeapons[WEAPON::TOASTER].multiplier = 8;
jjObjectPresets[OBJECT::TOASTERBULLET].xAcc = 0;
jjObjectPresets[OBJECT::TOASTERBULLET].yAcc = 0;
jjObjectPresets[OBJECT::TOASTERBULLET].behavior = Flamethrower();
jjObjectPresets[OBJECT::TOASTERBULLET].determineCurFrame();
jjObjectPresets[OBJECT::TOASTERBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::TOASTERBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::TOASTERBULLET].animSpeed = 6;
jjObjectPresets[OBJECT::TOASTERBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::TOASTERBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::TOASTERBULLETPU].behavior = Flamethrower();
jjObjectPresets[OBJECT::TOASTERBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::TOASTERBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::TOASTERBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::TOASTERBULLETPU].animSpeed = 12;
jjWeapons[WEAPON::TNT].maximum = 10;
jjAnimSets[ANIM::ROBOT].load();
jjAnimations[jjAnimSets[ANIM::AMMO] + 59] = jjAnimations[jjAnimSets[ANIM::ROBOT] + 0];
jjObjectPresets[OBJECT::TNT].killAnim = jjObjectPresets[OBJECT::RFBULLET].killAnim;
jjObjectPresets[OBJECT::TNT].special = jjObjectPresets[OBJECT::TNT].determineCurAnim(ANIM::ROBOT, 0);
jjObjectPresets[OBJECT::TNT].determineCurFrame();
jjObjectPresets[OBJECT::TNT].lightType = LIGHT::NONE;
jjObjectPresets[OBJECT::TNT].behavior = SpikeMine();
jjObjectPresets[OBJECT::TNT].scriptedCollisions = true;
jjObjectPresets[OBJECT::TNT].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::TNT].animSpeed = 75;
jjObjectPresets[OBJECT::TNT].counterEnd = 245;
jjObjectPresets[OBJECT::TNT].isBlastable = false;
jjWeapons[WEAPON::GUN8].maximum = 35;
jjWeapons[WEAPON::GUN8].spread = SPREAD::NORMAL;
jjWeapons[WEAPON::GUN8].gradualAim = false;
jjWeapons[WEAPON::GUN8].defaultSample = false;
jjObjectPresets[OBJECT::FIREBALLBULLET].xSpeed = -15;
jjObjectPresets[OBJECT::FIREBALLBULLET].ySpeed = 0;
jjObjectPresets[OBJECT::FIREBALLBULLET].xAcc = 0;
jjObjectPresets[OBJECT::FIREBALLBULLET].yAcc = 0;
jjObjectPresets[OBJECT::FIREBALLBULLET].eventID = OBJECT::BLASTERBULLET;
jjObjectPresets[OBJECT::FIREBALLBULLET].behavior = Laser();
jjObjectPresets[OBJECT::FIREBALLBULLET].special = jjObjectPresets[OBJECT::FIREBALLBULLET].determineCurAnim(ANIM::AMMO, 30);
jjObjectPresets[OBJECT::FIREBALLBULLET].determineCurFrame();
jjObjectPresets[OBJECT::FIREBALLBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::FIREBALLBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::FIREBALLBULLET].animSpeed = 40;
jjObjectPresets[OBJECT::FIREBALLBULLET].counterEnd = 140;
jjObjectPresets[OBJECT::FIREBALLBULLET].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].xSpeed = -15;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].ySpeed = 0;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].xAcc = 0;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].yAcc = 0;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].eventID = OBJECT::BLASTERBULLETPU;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].behavior = Laser();
jjObjectPresets[OBJECT::FIREBALLBULLETPU].special = jjObjectPresets[OBJECT::FIREBALLBULLETPU].determineCurAnim(ANIM::AMMO, 30);
jjObjectPresets[OBJECT::FIREBALLBULLETPU].determineCurFrame();
jjObjectPresets[OBJECT::FIREBALLBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].animSpeed = 80;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].counterEnd = 140;
jjObjectPresets[OBJECT::FIREBALLBULLETPU].killAnim = jjObjectPresets[OBJECT::ICEBULLET].killAnim;
jjWeapons[WEAPON::GUN9].maximum = 75;
jjObjectPresets[OBJECT::ELECTROBULLET].xSpeed = jjObjectPresets[OBJECT::ELECTROBULLET].xSpeed * -4;
jjObjectPresets[OBJECT::ELECTROBULLET].ySpeed = 0;
jjObjectPresets[OBJECT::ELECTROBULLET].counterEnd = 200;
jjObjectPresets[OBJECT::ELECTROBULLET].behavior = ElectroBlaster();
jjObjectPresets[OBJECT::ELECTROBULLET].scriptedCollisions = true;
jjObjectPresets[OBJECT::ELECTROBULLET].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::ELECTROBULLET].animSpeed = 18;
jjObjectPresets[OBJECT::ELECTROBULLETPU].xSpeed = jjObjectPresets[OBJECT::ELECTROBULLETPU].xSpeed * -4;
jjObjectPresets[OBJECT::ELECTROBULLETPU].ySpeed = 0;
jjObjectPresets[OBJECT::ELECTROBULLETPU].counterEnd = 210;
jjObjectPresets[OBJECT::ELECTROBULLETPU].behavior = ElectroBlaster();
jjObjectPresets[OBJECT::ELECTROBULLETPU].scriptedCollisions = true;
jjObjectPresets[OBJECT::ELECTROBULLETPU].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::ELECTROBULLETPU].animSpeed = 36;
jjObjectPresets[OBJECT::BOUNCERAMMO3].behavior =
jjObjectPresets[OBJECT::ICEAMMO3].behavior =
jjObjectPresets[OBJECT::SEEKERAMMO3].behavior =
jjObjectPresets[OBJECT::RFAMMO3].behavior =
jjObjectPresets[OBJECT::TOASTERAMMO3].behavior =
jjObjectPresets[OBJECT::TNTAMMO3].behavior =
jjObjectPresets[OBJECT::GUN8AMMO3].behavior =
jjObjectPresets[OBJECT::GUN9AMMO3].behavior = AmmoPickup();
jjObjectPresets[OBJECT::BOUNCERAMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::ICEAMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::SEEKERAMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::RFAMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::TOASTERAMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::TNTAMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::GUN8AMMO3].scriptedCollisions =
jjObjectPresets[OBJECT::GUN9AMMO3].scriptedCollisions = true;
jjObjectPresets[OBJECT::BOUNCERAMMO3].var[4] = 2;
jjObjectPresets[OBJECT::ICEAMMO3].var[4] = 3;
jjObjectPresets[OBJECT::SEEKERAMMO3].var[4] = 4;
jjObjectPresets[OBJECT::RFAMMO3].var[4] = 5;
jjObjectPresets[OBJECT::TOASTERAMMO3].var[4] = 6;
jjObjectPresets[OBJECT::TNTAMMO3].var[4] = 7;
jjObjectPresets[OBJECT::GUN8AMMO3].var[4] = 8;
jjObjectPresets[OBJECT::GUN9AMMO3].var[4] = 9;
jjObjectPresets[OBJECT::BOUNCERAMMO3].var[5] = 5;
jjObjectPresets[OBJECT::ICEAMMO3].var[5] = 2;
jjObjectPresets[OBJECT::SEEKERAMMO3].var[5] = 2;
jjObjectPresets[OBJECT::RFAMMO3].var[5] = 1;
jjObjectPresets[OBJECT::TOASTERAMMO3].var[5] = 3;
jjObjectPresets[OBJECT::TNTAMMO3].var[5] = 1;
jjObjectPresets[OBJECT::GUN8AMMO3].var[5] = 3;
jjObjectPresets[OBJECT::GUN9AMMO3].var[5] = 4;
jjObjectPresets[OBJECT::CARROT].behavior = HealthPickup();
jjObjectPresets[OBJECT::CARROT].scriptedCollisions = true;
jjObjectPresets[OBJECT::CARROT].determineCurAnim(customAnimID, 6);
jjObjectPresets[OBJECT::CARROT].determineCurFrame();
jjObjectPresets[OBJECT::CARROT].light = 8;
jjObjectPresets[OBJECT::FULLENERGY].behavior = MegaHealthPickup();
jjObjectPresets[OBJECT::FULLENERGY].scriptedCollisions = true;
jjObjectPresets[OBJECT::FULLENERGY].determineCurAnim(customAnimID, 7);
jjObjectPresets[OBJECT::FULLENERGY].determineCurFrame();
jjObjectPresets[OBJECT::FIRESHIELD].behavior = PowerOrb();
jjObjectPresets[OBJECT::FIRESHIELD].scriptedCollisions = true;
jjObjectPresets[OBJECT::FIRESHIELD].playerHandling = HANDLING::PICKUP;
jjObjectPresets[OBJECT::FIRESHIELD].light = 8;
jjObjectPresets[OBJECT::FIRESHIELD].triggersTNT = false;
jjObjectPresets[OBJECT::FIRESHIELD].determineCurAnim(customAnimID, 5);
jjObjectPresets[OBJECT::FIRESHIELD].determineCurFrame();
jjObjectPresets[OBJECT::PURPLEGEM].determineCurAnim(customAnimID, 1);
jjObjectPresets[OBJECT::PURPLEGEM].determineCurFrame();
jjObjectPresets[OBJECT::PURPLEGEM].behavior = ShipExplosion();
jjObjectPresets[OBJECT::PURPLEGEM].playerHandling = HANDLING::PARTICLE;
jjObjectPresets[OBJECT::PURPLEGEM].bulletHandling = HANDLING::IGNOREBULLET;
jjObjectPresets[OBJECT::PURPLEGEM].frameID = 0;
jjObjectPresets[OBJECT::FULLENERGY].light = 8;
jjObjectPresets[OBJECT::PLASMASHIELD].behavior = ShieldPickup();
jjObjectPresets[OBJECT::PLASMASHIELD].scriptedCollisions = true;
jjObjectPresets[OBJECT::PLASMASHIELD].playerHandling = HANDLING::PICKUP;
jjObjectPresets[OBJECT::PLASMASHIELD].light = 8;
jjObjectPresets[OBJECT::PLASMASHIELD].triggersTNT = false;
jjObjectPresets[OBJECT::PLASMASHIELD].determineCurAnim(customAnimID, 3);
jjObjectPresets[OBJECT::PLASMASHIELD].determineCurFrame();
array<OBJECT::Object> Powerups = {OBJECT::BLASTERPOWERUP, OBJECT::BOUNCERPOWERUP, OBJECT::ICEPOWERUP, OBJECT::SEEKERPOWERUP, OBJECT::RFPOWERUP, OBJECT::TOASTERPOWERUP, OBJECT::TNTPOWERUP, OBJECT::GUN8POWERUP, OBJECT::GUN9POWERUP};
for (uint p = 0; p < Powerups.length(); p++) {
jjObjectPresets[Powerups[p]].behavior = ShieldPickup();
jjObjectPresets[Powerups[p]].scriptedCollisions = true;
jjObjectPresets[Powerups[p]].playerHandling = HANDLING::PICKUP;
jjObjectPresets[Powerups[p]].light = 8;
jjObjectPresets[Powerups[p]].triggersTNT = false;
jjObjectPresets[Powerups[p]].determineCurAnim(customAnimID, 3);
jjObjectPresets[Powerups[p]].determineCurFrame();
}
jjObjectPresets[OBJECT::WATERSHIELD].behavior = MegaShieldPickup();
jjObjectPresets[OBJECT::WATERSHIELD].scriptedCollisions = true;
jjObjectPresets[OBJECT::WATERSHIELD].playerHandling = HANDLING::PICKUP;
jjObjectPresets[OBJECT::WATERSHIELD].light = 8;
jjObjectPresets[OBJECT::WATERSHIELD].triggersTNT = false;
jjObjectPresets[OBJECT::WATERSHIELD].determineCurAnim(customAnimID, 4);
jjObjectPresets[OBJECT::WATERSHIELD].determineCurFrame();
}
jjOBJ@ assignHealthPickup(uint8 eventID) {
jjOBJ@ preset = jjObjectPresets[eventID];
preset.behavior = HealthPickup();
preset.scriptedCollisions = true;
preset.playerHandling = HANDLING::PICKUP;
preset.triggersTNT = false;
preset.determineCurAnim(customAnimID, 6);
preset.determineCurFrame();
preset.light = 8;
return preset;
}
jjOBJ@ assignMegaHealthPickup(uint8 eventID) {
jjOBJ@ preset = jjObjectPresets[eventID];
preset.behavior = MegaHealthPickup();
preset.scriptedCollisions = true;
preset.playerHandling = HANDLING::PICKUP;
preset.triggersTNT = false;
preset.determineCurAnim(customAnimID, 7);
preset.determineCurFrame();
preset.light = 8;
return preset;
}
jjOBJ@ assignShieldPickup(uint8 eventID) {
jjOBJ@ preset = jjObjectPresets[eventID];
preset.behavior = ShieldPickup();
preset.scriptedCollisions = true;
preset.playerHandling = HANDLING::PICKUP;
preset.triggersTNT = false;
preset.determineCurAnim(customAnimID, 3);
preset.determineCurFrame();
preset.light = 8;
return preset;
}
jjOBJ@ assignMegaShieldPickup(uint8 eventID) {
jjOBJ@ preset = jjObjectPresets[eventID];
preset.behavior = MegaShieldPickup();
preset.scriptedCollisions = true;
preset.playerHandling = HANDLING::PICKUP;
preset.triggersTNT = false;
preset.determineCurAnim(customAnimID, 4);
preset.determineCurFrame();
preset.light = 8;
return preset;
}
jjOBJ@ assignPowerOrb(uint8 eventID) {
jjOBJ@ preset = jjObjectPresets[eventID];
preset.behavior = PowerOrb();
preset.scriptedCollisions = true;
preset.playerHandling = HANDLING::PICKUP;
preset.triggersTNT = false;
preset.determineCurAnim(customAnimID, 5);
preset.determineCurFrame();
preset.light = 8;
return preset;
}
void assignPickupDefaults() {
jjObjectPresets[OBJECT::CARROT].behavior = HealthPickup();
jjObjectPresets[OBJECT::CARROT].scriptedCollisions = true;
jjObjectPresets[OBJECT::CARROT].determineCurAnim(customAnimID, 6);
jjObjectPresets[OBJECT::CARROT].determineCurFrame();
jjObjectPresets[OBJECT::CARROT].light = 8;
jjObjectPresets[OBJECT::FULLENERGY].behavior = MegaHealthPickup();
jjObjectPresets[OBJECT::FULLENERGY].scriptedCollisions = true;
jjObjectPresets[OBJECT::FULLENERGY].determineCurAnim(customAnimID, 7);
jjObjectPresets[OBJECT::FULLENERGY].determineCurFrame();
jjObjectPresets[OBJECT::SEEKERPOWERUP].behavior = MegaShieldPickup();
jjObjectPresets[OBJECT::SEEKERPOWERUP].scriptedCollisions = true;
jjObjectPresets[OBJECT::SEEKERPOWERUP].playerHandling = HANDLING::PICKUP;
jjObjectPresets[OBJECT::SEEKERPOWERUP].light = 8;
jjObjectPresets[OBJECT::SEEKERPOWERUP].triggersTNT = false;
jjObjectPresets[OBJECT::SEEKERPOWERUP].determineCurAnim(customAnimID, 4);
jjObjectPresets[OBJECT::SEEKERPOWERUP].determineCurFrame();
array<OBJECT::Object> Shields = {OBJECT::FIRESHIELD, OBJECT::WATERSHIELD, OBJECT::LIGHTNINGSHIELD, OBJECT::LASERSHIELD};
for (uint s = 0; s < Shields.length(); s++) {
jjObjectPresets[Shields[s]].behavior = PowerOrb();
jjObjectPresets[Shields[s]].scriptedCollisions = true;
jjObjectPresets[Shields[s]].playerHandling = HANDLING::PICKUP;
jjObjectPresets[Shields[s]].light = 8;
jjObjectPresets[Shields[s]].triggersTNT = false;
jjObjectPresets[Shields[s]].determineCurAnim(customAnimID, 5);
jjObjectPresets[Shields[s]].determineCurFrame();
}
array<OBJECT::Object> Powerups = {OBJECT::BLASTERPOWERUP, OBJECT::BOUNCERPOWERUP, OBJECT::ICEPOWERUP, OBJECT::RFPOWERUP, OBJECT::TOASTERPOWERUP, OBJECT::TNTPOWERUP, OBJECT::GUN8POWERUP, OBJECT::GUN9POWERUP};
for (uint p = 0; p < Powerups.length(); p++) {
jjObjectPresets[Powerups[p]].behavior = ShieldPickup();
jjObjectPresets[Powerups[p]].scriptedCollisions = true;
jjObjectPresets[Powerups[p]].playerHandling = HANDLING::PICKUP;
jjObjectPresets[Powerups[p]].light = 8;
jjObjectPresets[Powerups[p]].triggersTNT = false;
jjObjectPresets[Powerups[p]].determineCurAnim(customAnimID, 3);
jjObjectPresets[Powerups[p]].determineCurFrame();
}
jjObjectPresets[OBJECT::PURPLEGEM].determineCurAnim(customAnimID, 1);
jjObjectPresets[OBJECT::PURPLEGEM].determineCurFrame();
jjObjectPresets[OBJECT::PURPLEGEM].behavior = ShipExplosion();
jjObjectPresets[OBJECT::PURPLEGEM].playerHandling = HANDLING::PARTICLE;
jjObjectPresets[OBJECT::PURPLEGEM].bulletHandling = HANDLING::IGNOREBULLET;
jjObjectPresets[OBJECT::PURPLEGEM].frameID = 0;
}
void handleAnimationWork() {
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::JAZZ] + 53],
3,
Resize::Method::Scale2x
);
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::SPAZ] + 53],
3,
Resize::Method::Scale2x
);
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::LORI] + 53],
3,
Resize::Method::Scale2x
);
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::PICKUPS] + 41],
2,
Resize::Method::Scale2x
);
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::AMMO] + 30],
2,
Resize::Method::Scale2x
);
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::SONCSHIP] + 0],
1.5,
Resize::Method::Scale2x
);
Resize::Resize(
jjAnimations[jjAnimSets[ANIM::MENU] + 1],
3.5,
Resize::Method::Scale2x
);
jjANIMATION@ animBlaster = jjAnimations[jjAnimSets[ANIM::DEVAN] + 0];
for (uint i = 0; i < animBlaster.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animBlaster + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 32 && sprite[x,y] <= 39) sprite[x,y] -= 17;
}
}
sprite.save(frame);
}
jjANIMATION@ animBurst = jjAnimations[jjAnimSets[ANIM::PICKUPS] + 45];
for (uint i = 0; i < animBurst.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animBurst + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 32 && sprite[x,y] <= 39) sprite[x,y] += 56;
}
}
sprite.save(frame);
}
jjANIMATION@ animBurstAmmo = jjAnimations[jjAnimSets[ANIM::AMMO] + 29];
for (uint i = 0; i < animBurstAmmo.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animBurstAmmo + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 32 && sprite[x,y] <= 39) sprite[x,y] += 56;
}
}
sprite.save(frame);
}
jjANIMATION@ animBurstAmmoPU = jjAnimations[jjAnimSets[ANIM::AMMO] + 28];
for (uint i = 0; i < animBurstAmmoPU.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animBurstAmmoPU + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 88 && sprite[x,y] <= 95) sprite[x,y] -= 33;
}
}
sprite.save(frame);
}
jjANIMATION@ animMissile = jjAnimations[jjAnimSets[ANIM::SONCSHIP] + 0];
for (uint i = 0; i < animMissile.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animMissile + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 88 && sprite[x,y] <= 95) sprite[x,y] -= 72;
}
}
sprite.save(frame);
}
jjANIMATION@ animLaser = jjAnimations[jjAnimSets[ANIM::AMMO] + 30];
for (uint i = 0; i < animLaser.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animLaser + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 32 && sprite[x,y] <= 39) sprite[x,y] += 48;
}
}
sprite.save(frame);
}
jjANIMATION@ animLaserAmmo = jjAnimations[jjAnimSets[ANIM::AMMO] + 62];
for (uint i = 0; i < animLaserAmmo.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animLaserAmmo + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 88 && sprite[x,y] <= 95) sprite[x,y] -= 8;
}
}
sprite.save(frame);
}
jjANIMATION@ animLaserAmmoPU = jjAnimations[jjAnimSets[ANIM::AMMO] + 61];
for (uint i = 0; i < animLaserAmmoPU.frameCount; i++) {
jjANIMFRAME@ frame = jjAnimFrames[animLaserAmmoPU + i];
jjPIXELMAP sprite(frame);
for (uint x = 0; x < sprite.width; ++x) {
for (uint y = 0; y < sprite.height; ++y) {
if (sprite[x,y] >= 24 && sprite[x,y] <= 31) sprite[x,y] += 24;
}
}
sprite.save(frame);
}
}
void handleOnLevelBegin() {
jjAlert("|||Press |||||Esc -> Help||| for instructions!");
jjSampleLoad(SOUND::COMMON_LANDPOP, "silence.wav");
}
void handleShipCollisions(jjOBJ@ obj, jjPLAYER@ creator) {
if (!jjLocalPlayers[0].isIdle) {
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
SPACESHIP@ ship = Ships[i];
if (obj.doesCollide(play, true) && canBeHit(play,creator,obj) && (obj.var[8] & 1 << play.playerID == 0 || obj.eventID != OBJECT::FIREBALLBULLET)) {
if (obj.special != 100) {
ship.damageAccumulated += obj.animSpeed;
ship.accumulationTime = 0;
obj.special = 100;
}
if (obj.eventID == OBJECT::ICEBULLET || obj.eventID == OBJECT::ICEBULLETPU) damageNumber(creator, play, ship.damageCalc(ship, ship.damageAccumulated));
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
randomHurtSample(play, 48);
if (!play.isLocal && obj.eventID != OBJECT::ICEBULLET && obj.eventID != OBJECT::ICEBULLETPU) damageNumber(creator, play, ship.damageCalc(ship, ship.damageAccumulated));
if ((obj.eventID == OBJECT::SEEKERBULLET || obj.eventID == OBJECT::SEEKERBULLETPU) && creator.isLocal) obj.state = STATE::EXPLODE;
jjSample(
play.xPos, play.yPos,
(obj.eventID == OBJECT::TOASTERBULLET || obj.eventID == OBJECT::TOASTERBULLETPU)? SOUND::BILSBOSS_FIRE :
(obj.eventID == OBJECT::SEEKERBULLET || obj.eventID == OBJECT::SEEKERBULLETPU || obj.eventID == OBJECT::RFBULLET || obj.eventID == OBJECT::RFBULLETPU || obj.eventID == OBJECT::TNT)? SOUND::COMMON_EXPL_TNT :
(obj.eventID == OBJECT::ELECTROBULLET || obj.eventID == OBJECT::ELECTROBULLETPU)? SOUND::COMMON_ELECTRICHIT :
SOUND::ROBOT_BIG2, 63, 12500 + jjRandom()%2500
);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
}
}
}
}
}
class Blaster : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::FLY && inView(obj)? false:true);
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
if (obj.state == STATE::START) {
obj.state = STATE::FLY;
}
if (obj.state == STATE::FLY) {
if (obj.counter == 1 && jjPlayers[obj.creatorID].isLocal) jjSample(obj.xPos, obj.yPos, SOUND::DEVILDEVAN_PHASER2, 50, obj.eventID == OBJECT::BLASTERBULLETPU? 11500 : 0);
if (obj.counter > 1 && inView(obj)) jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.var[0], 1, 1, obj.eventID == OBJECT::BLASTERBULLETPU? SPRITE::SINGLEHUE : SPRITE::NORMAL, 49);
obj.xPos += (obj.xSpeed / 2.5);
obj.yPos += (obj.ySpeed / 2.5);
}
if (obj.findNearestPlayer(1000) > -1 && obj.findNearestPlayer(1000) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj)) {
ship.xSpeed += recoilX(ship,obj,12);
ship.ySpeed += recoilY(ship,obj,12);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::BLASTERBULLETPU? jjObjectPresets[OBJECT::BLASTERBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::BLASTERBULLET].animSpeed * 1.3);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
jjSample(play.xPos, play.yPos, SOUND::ROBOT_BIG2, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
}
return true;
}
}
class RapidBlaster : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::FLY && inView(obj)? false:true);
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
if (obj.state == STATE::START) {
obj.state = STATE::FLY;
}
if (obj.state == STATE::FLY) {
if (obj.counter == 1 && jjPlayers[obj.creatorID].isLocal) jjSample(obj.xPos, obj.yPos, SOUND::COMMON_PISTOL1, 50, obj.eventID == OBJECT::BOUNCERBULLETPU? 20000 : 0);
if (obj.counter > 1) jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.var[0], 1, 1, obj.eventID == OBJECT::BOUNCERBULLETPU? SPRITE::SINGLEHUE : SPRITE::NORMAL, 88);
obj.xPos += obj.xSpeed * 2;
obj.yPos += obj.ySpeed * 2;
}
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj)) {
ship.xSpeed += recoilX(ship,obj,7.5);
ship.ySpeed += recoilY(ship,obj,7.5);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::BOUNCERBULLETPU? jjObjectPresets[OBJECT::BOUNCERBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::BOUNCERBULLET].animSpeed * 1.3);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
jjSample(play.xPos, play.yPos, SOUND::ROBOT_BIG2, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
}
return true;
}
}
class IceBurster : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::FLY && inView(obj)? false:true);
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
jjPLAYER@ creator = jjPlayers[obj.creatorID];
if (obj.state == STATE::START) {
obj.state = STATE::FLY;
}
if (obj.state == STATE::FLY) {
if (obj.counter == 2 && jjPlayers[obj.creatorID].isLocal) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_ICECRUSH, 30, obj.eventID == OBJECT::ICEBULLETPU? 10500:0);
if (creator.ySpeed == 0) {
if (obj.ySpeed < - 12) obj.ySpeed = -12;
if (obj.ySpeed > 12) obj.ySpeed = 12;
}
}
obj.xPos += (obj.xSpeed / 1.5);
obj.yPos += (obj.ySpeed / 1.5);
if (obj.counter > 1 && inView(obj)) jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.var[0], 1, 1, obj.eventID == OBJECT::ICEBULLETPU? SPRITE::SINGLEHUE : SPRITE::NORMAL, 40);
if (obj.eventID == OBJECT::ICEBULLETPU && jjGameTicks % 3 == 0) {
jjPARTICLE@ cinders = jjAddParticle(PARTICLE::FIRE);
cinders.xPos = obj.xPos;
cinders.yPos = obj.yPos;
}
}
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj)) {
ship.xSpeed += recoilX(ship,obj,17.5);
ship.ySpeed += recoilY(ship,obj,17.5);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::ICEBULLETPU? jjObjectPresets[OBJECT::ICEBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::ICEBULLET].animSpeed * 1.3);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (obj.special != 100) {
ship.damageAccumulated += obj.animSpeed;
ship.accumulationTime = 0;
obj.special = 100;
}
if (obj.eventID == OBJECT::ICEBULLET || obj.eventID == OBJECT::ICEBULLETPU) damageNumber(creator, play, ship.damageCalc(ship, ship.damageAccumulated));
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
jjSample(play.xPos, play.yPos, SOUND::ROBOT_BIG2, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
}
return true;
}
}
class HomingMissile : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::FLY && inView(obj)? false:true);
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
++obj.age;
if (obj.state == STATE::FLY && obj.counter > 1 && inView(obj)) jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.var[0], 1, 1, SPRITE::NORMAL);
if (obj.state == STATE::START) {
obj.points = int(atan2(obj.xSpeed, obj.ySpeed) * 162.974636 /*+ (jjCos(jjRandom() % 512) * 10)*/); //angle
obj.state = STATE::FLY;
obj.xSpeed += obj.var[7] / 65536.f;
} else if (obj.age > 14) { //redirect
array<float>@ target = null;
if (obj.creatorType == CREATOR::PLAYER && jjGameMode > GAME::COOP) {
const int targetPlayerID = closestPlayers[obj.creatorID]; //closest to player who fired this
if (targetPlayerID >= 0)
@target = array<float> = { jjPlayers[targetPlayerID].xPos, jjPlayers[targetPlayerID].yPos };
}
if (target is null)
@target = MLLEWeapons::HelpfulBulletFunctions::GetNearestEnemyPosition(obj, 350); //closest to bullet itself... this part is new to the .asc reimplementation
if (target !is null) {
int difference = ((int(atan2(obj.xPos - target[0], obj.yPos - target[1]) * 162.974636) + 512 - obj.points) & 1023);
if (difference >= 512) difference -= 1024;
obj.points += difference / 8;
obj.xSpeed = 6.5 * jjSin(obj.points);
obj.ySpeed = 6.5 * jjCos(obj.points);
}
}
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.state != STATE::EXPLODE) {
ship.xSpeed += recoilX(ship,obj,55);
ship.ySpeed += recoilY(ship,obj,55);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::SEEKERBULLETPU? jjObjectPresets[OBJECT::SEEKERBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::SEEKERBULLET].animSpeed * 1.5);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
jjSample(play.xPos, play.yPos, SOUND::COMMON_EXPL_TNT, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
}
return true;
}
}
class SuperMissile : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::BULLET, false);
jjPLAYER@ creator = jjPlayers[obj.creatorID];
jjPLAYER@ play;
SPACESHIP@ ship = Ships[creator.playerID];
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
switch (obj.state) {
case STATE::START:
obj.state = STATE::FLY;
obj.lightType = LIGHT::POINT;
obj.var[2] = 0;
break;
case STATE::FLY:
if (obj.counter == 1 && creator.isLocal && !ship.kamikaze) {
jjSample(creator.xPos, creator.yPos, SOUND::INTRO_SHOT1, 0, obj.eventID == OBJECT::RFBULLETPU? 35500 : 0);
}
if (obj.counter > 1 && inView(obj)) jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.var[0], 1, 1, obj.eventID == OBJECT::RFBULLETPU? SPRITE::PALSHIFT : SPRITE::NORMAL, 8);
if (obj.counter % 5 == 0 && !jjLowDetail) {
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::NONE;
trail.playerHandling = HANDLING::PARTICLE;
trail.bulletHandling = HANDLING::IGNOREBULLET;
trail.isBlastable = false;
}
if (ship.kamikaze) obj.state = STATE::EXPLODE;
break;
case STATE::EXPLODE:
obj.animSpeed = obj.animSpeed;
jjDrawResizedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 5, obj.curFrame + 1, obj.eventID == OBJECT::RFBULLETPU? 2.5:2, obj.eventID == OBJECT::RFBULLETPU? 2.5:2, SPRITE::NORMAL);
if (obj.var[2] == 0) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BENZIN1);
Shockwave temp;
jjOBJ@ blast = jjObjects[jjAddObject(OBJECT::BULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
obj.var[2] = 1;
blast.var[2] = 1;
blast.var[8] = obj.var[8];
blast.special = (ship.kamikaze? 1:0);
blast.animSpeed = obj.animSpeed;
blast.eventID = OBJECT::BULLET;
}
break;
}
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.var[8] & 1 << play.playerID == 0 && !ship.kamikaze) {
ship.xSpeed += recoilX(ship,obj,30);
ship.ySpeed += recoilY(ship,obj,30);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::RFBULLETPU? jjObjectPresets[OBJECT::RFBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::RFBULLET].animSpeed * 1.5);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed * 2);
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
obj.var[8] = obj.var[8] | 1 << play.playerID;
jjSample(play.xPos, play.yPos, SOUND::COMMON_EXPL_TNT, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
}
return true;
}
}
class Shockwave : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.playerHandling = HANDLING::PARTICLE;
obj.bulletHandling = HANDLING::IGNOREBULLET;
if (obj.var[2] == 1) {
obj.lightType = obj.var[2] == 1? LIGHT::RING2 : LIGHT::NONE;
obj.var[1] = obj.var[1] + 1;
obj.light += 2;
obj.var[4] = obj.light * (obj.special == 1? 5:4);
obj.var[5] = obj.animSpeed - ((obj.var[4] * obj.animSpeed)/216);
if (obj.var[4] >= 200) obj.var[6] = 20;
else if (obj.var[4] >= 100 && obj.var[6] < 200) obj.var[6] = 30;
else if (obj.var[4] < 100) obj.var[6] = 40;
for (int i = 1; i < jjObjectCount; i++) {
jjOBJ@ target = jjObjects[i];
float dx = target.xPos - obj.xPos, dy = target.yPos - obj.yPos;
if ((target.eventID == OBJECT::TNT || target.behavior == BEHAVIOR::MONITOR || target.behavior == BEHAVIOR::AMMO15 || target.eventID == OBJECT::GUNCRATE || target.eventID == OBJECT::GEMCRATE || target.eventID == OBJECT::CARROTCRATE || target.playerHandling == HANDLING::ENEMY || target.eventID == OBJECT::DESTRUCTSCENERY) && target.var[4] == 0) {
if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
if (target.eventID != OBJECT::TNT) {
obj.objectHit(target, target.playerHandling == HANDLING::ENEMY? HANDLING::ENEMY : HANDLING::SPECIAL);
if (target.playerHandling != HANDLING::ENEMY) target.state = STATE::KILL;
} else {
target.state = STATE::EXPLODE;
target.counter = 18;
}
if (target.playerHandling != HANDLING::ENEMY) target.var[4] = 1;
}
else target.var[4] = 0;
}
}
if (gameIsActive()) {
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.var[4] > 0) {
float dx = play.xPos - obj.xPos, dy = play.yPos - obj.yPos;
if (dx * dx + dy * dy < obj.var[4] * obj.var[4]) {
if (obj.var[8] & 1 << i == 0 && play.blink == 0 && obj.var[5] > 0) {
obj.var[8] = obj.var[8] | 1 << i;
jjSample(play.xPos, play.yPos, SOUND::ROBOT_HYDROPUF, 63, 12500 + jjRandom()%2500);
if ((ship.health - ship.damageCalc(ship, obj.var[5])) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, play.score > 0? 0: obj.var[5]);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, play.score > 0? 0: obj.var[5]) * 2;
}
randomHurtSample(play, 0);
ship.damageAccumulated += obj.var[5];
ship.accumulationTime = 0;
if (!play.isLocal) damageNumber(creator, play, ship.damageCalc(ship, obj.var[5]));
int angle = int(atan2(play.yPos - obj.yPos, play.xPos - obj.xPos) * (512 / PI));
obj.ySpeed = jjSin(angle) * 32;
obj.xSpeed = jjCos(angle) * 32;
ship.xSpeed += recoilX(ship,obj,obj.var[6]);
ship.ySpeed += recoilY(ship,obj,obj.var[6]);
} else {
if (play.isLocal) {
if (play.score == 0) play.hurt(7, true, creator);
}
if (creator.isLocal) {
if (play.score == 0) ship.SDPunishment = true;
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
}
}
}
}
}
}
if (obj.var[1] == 27) {
obj.var[1] = 0;
obj.var[2] = 0;
obj.var[4] = 0;
obj.delete();
}
}
}
class Flamethrower : jjBEHAVIORINTERFACE {
float xSpeed, ySpeed, xPos, yPos;
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::TOASTERBULLET, false);
jjPLAYER@ creator = jjPlayers[obj.creatorID];
if (obj.state == STATE::FLY) {
obj.var[0] = int(creator.xSpeed);
if (obj.counter <= 3) {
xSpeed = obj.xSpeed;
ySpeed = obj.ySpeed;
}
if (obj.counter <= 7) {
obj.xSpeed = xSpeed * 2;
obj.ySpeed = ySpeed * 2;
}
obj.counter++;
if (obj.counter > 1 && inView(obj)) {
jjDrawSprite(obj.xPos, obj.yPos, ANIM::AMMO, 13, jjGameTicks >> 2, obj.direction, obj.eventID == OBJECT::TOASTERBULLETPU? SPRITE::SINGLEHUE : SPRITE::NORMAL, 32);
}
if (obj.counter >= 200) obj.delete();
}
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.state != STATE::EXPLODE) {
ship.xSpeed += recoilX(ship,obj,8);
ship.ySpeed += recoilY(ship,obj,8);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::TOASTERBULLETPU? jjObjectPresets[OBJECT::TOASTERBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::TOASTERBULLET].animSpeed * 1.5);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
jjSample(play.xPos, play.yPos, SOUND::BILSBOSS_FIRE, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
}
return true;
}
}
class SpikeMine : jjBEHAVIORINTERFACE {
bool isPowerup = false;
void onBehave(jjOBJ@ obj) {
obj.behave(obj.state == STATE::EXPLODE && obj.counter >= 18 && inView(obj)? BEHAVIOR::BULLET : BEHAVIOR::TNT, false);
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[creator.playerID];
obj.animSpeed = creator is jjTokenOwner? (isPowerup? 210:105) : (isPowerup? 140:70);
if (obj.state != STATE::EXPLODE) {
obj.xPos = obj.xPos + obj.xSpeed;
obj.yPos = obj.yPos + obj.ySpeed;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, isPowerup? SPRITE::SINGLEHUE : SPRITE::NORMAL, 40);
if (obj.counter == 1) {
if (ship.tntPowerup) isPowerup = true;
else isPowerup = false;
if (creator.isLocal) jjSample(obj.xPos, obj.yPos, SOUND::ROBOT_SHOOT, 0, isPowerup? 17500 : 0);
obj.xSpeed = creator.xSpeed / -4;
obj.ySpeed = (creator.ySpeed < 0.2 && creator.ySpeed > -0.2)? 0 : creator.ySpeed / -4;
}
if (obj.counter >= 175) {
if (obj.counter % 20 > 9) jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::TRANSLUCENTSINGLEHUE, 24);
obj.var[0] = jjSampleLooped(obj.xPos, obj.yPos, SOUND::COMMON_CLOCK, obj.var[0], 0, 0);
}
if (jjMaskedPixel(int(obj.xPos), int(obj.yPos))) {
obj.counter = 18;
obj.state = STATE::EXPLODE;
}
} else {
if (obj.counter == 18) {
jjDrawResizedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 5, obj.curFrame, 2, 2, SPRITE::NORMAL);
obj.behavior = BEHAVIOR::BULLET;
if (obj.var[2] == 0) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_BENZIN1);
Shockwave temp;
jjOBJ@ blast = jjObjects[jjAddObject(OBJECT::BULLET, obj.xPos, obj.yPos, obj.creatorID, CREATOR::PLAYER, jjVOIDFUNCOBJ(temp.onBehave))];
obj.var[2] = 1;
blast.var[2] = 1;
blast.var[8] = obj.var[8];
blast.animSpeed = obj.animSpeed;
blast.eventID = OBJECT::BULLET;
}
} else {
jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, (1 + (obj.counter/4)), (1 + (obj.counter/4)), isPowerup? SPRITE::SINGLEHUE : SPRITE::NORMAL, 40);
}
}
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.var[8] & 1 << play.playerID == 0) {
ship.xSpeed += recoilX(ship,obj,20);
ship.ySpeed += recoilY(ship,obj,20);
randomHurtSample(play, 0);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
obj.var[8] = obj.var[8] | 1 << play.playerID;
obj.counter = 18;
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
jjSample(play.xPos, play.yPos, SOUND::COMMON_EXPL_TNT, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
}
return true;
}
}
class Laser : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.behave(BEHAVIOR::BULLET, obj.state == STATE::EXPLODE && inView(obj)? true:false);
obj.var[0] = int(atan2(-obj.ySpeed, obj.xSpeed) * (512.f * 0.318309886142228f));
if (obj.state == STATE::FLY) {
if (obj.counter == 1 && jjPlayers[obj.creatorID].isLocal) jjSample(obj.xPos, obj.yPos, SOUND::AMMO_LASER, 0, obj.eventID == OBJECT::BLASTERBULLETPU? 12500:0);
if (obj.ySpeed < -15) obj.ySpeed = -15;
if (obj.ySpeed > 15) obj.ySpeed = 15;
obj.xPos += (obj.xSpeed / 2);
obj.yPos += (obj.ySpeed / 2);
}
if (obj.counter > 1 && inView(obj)) jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.var[0], 1, 1, obj.eventID == OBJECT::BLASTERBULLETPU? SPRITE::SINGLEHUE : SPRITE::NORMAL, 48);
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.var[8] & 1 << play.playerID == 0) {
ship.xSpeed += recoilX(ship,obj,40);
ship.ySpeed += recoilY(ship,obj,40);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::FIREBALLBULLETPU? jjObjectPresets[OBJECT::FIREBALLBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::FIREBALLBULLET].animSpeed * 1.5);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
obj.var[8] = obj.var[8] | 1 << play.playerID;
jjSample(play.xPos, play.yPos, SOUND::ROBOT_BIG2, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
}
return true;
}
}
class ElectroBlaster : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
obj.behave(BEHAVIOR::ELECTROBULLET, obj.counter > 1 && inView(obj)? true:false);
obj.xPos += jjCos(obj.counter*36)*(obj.ySpeed/3);
obj.yPos += jjSin(obj.counter*36)*(obj.xSpeed/3);
if (obj.findNearestPlayer(500) > -1 && obj.findNearestPlayer(500) != creator.playerID) handleShipCollisions(obj, creator);
if ((creator.charCurr == CHAR::JAZZ || creator.charCurr == CHAR::LORI) && obj.counter == 1 && obj.state != STATE::EXPLODE) {
obj.xPos = creator.xPos;
obj.yPos = creator.yPos;
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
SPACESHIP@ ship = Ships[play.playerID];
if (canBeHit(play,creator,obj) && obj.state != STATE::EXPLODE) {
ship.xSpeed += recoilX(ship,obj,15);
ship.ySpeed += recoilY(ship,obj,15);
randomHurtSample(play, 0);
if (creator is jjTokenOwner) obj.animSpeed = int(obj.eventID == OBJECT::ELECTROBULLETPU? jjObjectPresets[OBJECT::ELECTROBULLETPU].animSpeed * 1.5 : jjObjectPresets[OBJECT::ELECTROBULLET].animSpeed * 1.5);
if ((ship.health - ship.damageCalc(ship, obj.animSpeed)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, obj.animSpeed);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, obj.animSpeed) * 2;
}
} else {
if (play.isLocal) {
play.hurt(7, true, creator);
}
}
if (!ship.justHit) {
ship.justHit = true;
ship.hitDelay = 0;
}
jjSample(play.xPos, play.yPos, SOUND::COMMON_ELECTRICHIT, 63, 12500 + jjRandom()%2500);
if (ship.armor > 0) jjSample(play.xPos, play.yPos, SOUND::COMMON_LAND1, 63, 12500 + jjRandom()%2500);
obj.state = STATE::EXPLODE;
obj.scriptedCollisions = false;
}
return true;
}
}
bool inView(const jjOBJ@ obj) {
for (int i = 0; i < jjLocalPlayerCount; i++) {
const jjPLAYER@ play = jjLocalPlayers[i];
if (obj.xPos > play.cameraX - 64 && obj.yPos > play.cameraY - 64 && obj.xPos < play.cameraX + jjSubscreenWidth + 64 && obj.yPos < play.cameraY + jjSubscreenHeight + 64)
return true;
}
return false;
}
bool shipInView(jjPLAYER@ play) {
for (int i = 0; i < jjLocalPlayerCount; i++) {
const jjPLAYER@ player = jjLocalPlayers[i];
if (!play.isLocal && play.xPos > player.cameraX - 64 && play.yPos > player.cameraY - 64 && play.xPos < player.cameraX + jjSubscreenWidth + 64 && play.yPos < player.cameraY + jjSubscreenHeight + 64)
return true;
}
return false;
}
void damageNumber(jjPLAYER@ creator, jjPLAYER@ play, int num) {
if (creator.isLocal) {
jjPARTICLE@ text = jjAddParticle(PARTICLE::STRING);
if (text !is null) {
text.xPos = play.xPos;
text.yPos = play.yPos;
text.ySpeed = -0.25;
text.string.text = "" + num;
}
jjSample(creator.xPos, creator.yPos, SOUND::MENUSOUNDS_TYPE, 63, 28500 - (num * 50));
crosshairFlash = true;
crosshairTime = 0;
}
}
class AmmoPickup : 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, obj.eventID == OBJECT::TNTAMMO3? false:true);
if (obj.eventID == OBJECT::TNTAMMO3) {
jjDrawSprite(obj.xPos, getY(obj), ANIM::ROBOT, 0, 0, 0, SPRITE::SINGLEHUE, (jjLocalPlayers[0].powerup[WEAPON::TNT]? 40:72));
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
if (play.ammo[obj.var[4]] < jjWeapons[obj.var[4]].maximum) {
if (play.ammo[obj.var[4]] + obj.var[5] > jjWeapons[obj.var[4]].maximum) {
play.ammo[obj.var[4]] = jjWeapons[obj.var[4]].maximum;
} else {
if (jjAutoWeaponChange && play.ammo[obj.var[4]] == 0) play.currWeapon = obj.var[4];
play.ammo[obj.var[4]] = play.ammo[obj.var[4]] + obj.var[5];
}
if (play.isLocal) jjSample(play.xPos, play.yPos, SOUND::COMMON_PICKUPW1);
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
}
return true;
}
}
class HealthPickup : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.direction = 1;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
SPACESHIP@ ship = Ships[play.playerID];
int amount = ship.health > (maxHealth - int(maxHealth/5))? maxHealth - ship.health : int(maxHealth/5);
if (ship.health < maxHealth && play.blink == 0) {
sendShipRotationPacket(ship);
ship.health += amount;
if (play.isLocal) {
jjSample(play.xPos, play.yPos, SOUND::COMMON_MONITOR);
jjPARTICLE@ text = jjAddParticle(PARTICLE::STRING);
if (text !is null) {
text.xPos = play.xPos;
text.yPos = play.yPos;
text.ySpeed = -0.25;
text.string.text = "|||||+" + amount;
}
}
play.invincibility = 70;
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
}
return true;
}
}
class MegaHealthPickup : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.direction = 1;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
SPACESHIP@ ship = Ships[play.playerID];
int amount = ship.health > maxHealth? (maxHealth*2) - ship.health : maxHealth;
if (ship.health < (maxHealth*2) && play.blink == 0) {
sendShipRotationPacket(ship);
ship.health += amount;
if (play.isLocal) {
jjSample(play.xPos, play.yPos, SOUND::COMMON_ITEMTRE);
jjPARTICLE@ text = jjAddParticle(PARTICLE::STRING);
if (text !is null) {
text.xPos = play.xPos;
text.yPos = play.yPos;
text.ySpeed = -0.25;
text.string.text = "|||||+" + amount;
}
playHappySample(play);
}
play.invincibility = 210;
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
}
return true;
}
}
class ShieldPickup : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.direction = 1;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
SPACESHIP@ ship = Ships[play.playerID];
int amount = (ship.armor > (maxHealth / 2))? maxHealth - ship.armor : int(maxHealth/2);
if (ship.armor < maxHealth) {
sendShipRotationPacket(ship);
ship.armor += amount;
if (play.isLocal) {
jjSample(play.xPos, play.yPos, SOUND::INTRO_SHOTGRN);
jjPARTICLE@ text = jjAddParticle(PARTICLE::STRING);
if (text !is null) {
text.xPos = play.xPos;
text.yPos = play.yPos;
text.ySpeed = -0.25;
text.string.text = "|+" + amount;
}
}
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
}
return true;
}
}
class MegaShieldPickup : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.direction = 1;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
SPACESHIP@ ship = Ships[play.playerID];
int amount = ship.armor > maxHealth? (maxHealth*2) - ship.armor : maxHealth;
if (ship.armor < (maxHealth * 2)) {
sendShipRotationPacket(ship);
ship.armor += amount;
if (play.isLocal) {
jjSample(play.xPos, play.yPos, SOUND::INTRO_SHOTGRN, 0, 18000);
jjPARTICLE@ text = jjAddParticle(PARTICLE::STRING);
if (text !is null) {
text.xPos = play.xPos;
text.yPos = play.yPos;
text.ySpeed = -0.25;
text.string.text = "|+" + amount;
}
playHappySample(play);
}
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
}
return true;
}
}
class PowerOrb : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.behave(BEHAVIOR::PICKUP);
obj.direction = 1;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bull, jjPLAYER@ play, int force) {
SPACESHIP@ ship = Ships[play.playerID];
sendShipRotationPacket(ship);
ship.powerUp = true;
ship.powerTime = 30*70;
if (play.isLocal) {
jjSample(play.xPos, play.yPos, SOUND::BILSBOSS_FIRESTART, 0, 0);
playWarCry(play);
}
obj.behavior = BEHAVIOR::EXPLOSION2;
obj.scriptedCollisions = false;
obj.frameID = 0;
return true;
}
}
class ShipExplosion : jjBEHAVIORINTERFACE {
void onBehave(jjOBJ@ obj) {
obj.frameID++;
if (obj.frameID == 2 && jjGameTicks > 70) {
obj.particlePixelExplosion(1);
jjSample(obj.xPos, obj.yPos, SOUND::INTRO_BOEM2);
}
if (obj.frameID == 84) obj.delete();
jjDrawResizedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 5, obj.frameID / 7, 2, 2, SPRITE::NORMAL);
}
}
void playHappySample(jjPLAYER@ play) {
switch (play.charCurr) {
case CHAR::JAZZ: jjSample(play.xPos, play.yPos, SOUND::JAZZSOUNDS_JUMMY, 0, 0); break;
case CHAR::SPAZ: jjSample(play.xPos, play.yPos, SOUND::SPAZSOUNDS_HAPPY, 0, 0); break;
case CHAR::LORI: jjSample(play.xPos, play.yPos, SOUND::LORISOUNDS_WEHOO, 0, 0); break;
default: break;
}
}
void playWarCry(jjPLAYER@ play) {
switch (play.charCurr) {
case CHAR::JAZZ: jjSample(play.xPos, play.yPos, SOUND::JAZZSOUNDS_IDLE, 0, 0); break;
case CHAR::SPAZ: jjSample(play.xPos, play.yPos, SOUND::SPAZSOUNDS_HAHAHA, 0, 0); break;
case CHAR::LORI: jjSample(play.xPos, play.yPos, SOUND::LORISOUNDS_LORIBOOM, 0, 0); break;
default: break;
}
}
void handleOnPlayer(jjPLAYER@ play) {
SPACESHIP@ ship = Ships[play.playerID];
play.direction = play.keyLeft? 1:-1;
//if (jjKey[0x71]) {
//if (!showInstructions) {
//if (!pressOnce[0]) {
//showInstructions = true;
//pressOnce[0] = true;
//}
//} else {
//if (!pressOnce[0]) {
//showInstructions = false;
//pressOnce[0] = true;
//}
//}
//} else {
//pressOnce[0] = false;
//}
//if (showInstructions) {
//if (jjKey[0xBC]) {
//if (!pressOnce[1]) {
//if (currPage == 1) {
//currPage = 3;
//} else {
//currPage--;
//}
//pressOnce[1] = true;
//}
//} else {
//pressOnce[1] = false;
//}
//if (jjKey[0xBE]) {
//if (!pressOnce[2]) {
//if (currPage == 3) {
//currPage = 1;
//} else {
//currPage++;
//}
//pressOnce[2] = true;
//}
//} else {
//pressOnce[2] = false;
//}
//}
if (ship.hasShip) {
play.spriteMode = SPRITE::INVISIBLE;
play.ballTime = 1;
play.direction = 1;
play.fly = FLIGHT::NONE;
play.jumpStrength = 0;
jjCharacters[play.charCurr].airJump = AIR::NONE;
if (ship.boost) {
ship.boostTime--;
play.xPos += (ship.xSpeed / 2);
play.yPos += (ship.ySpeed / 2);
//if (jjGameTicks % 4 == 0) play.fireBullet(WEAPON::TOASTER, false, false, ((ship.fireAngle+511+(251))/512) * -PI);
if (jjMaskedPixel(int(play.xPos), int(play.yPos)) && play.health > 0 && !ship.kamikaze) {
ship.killShip = true;
kamikazeAttack(play, ship);
}
if (ship.boostTime == 0) ship.boost = false;
}
if (ship.kamikaze) {
ship.kamikazeCooldown++;
if (ship.kamikazeCooldown == 1) {
play.xPos -= ship.xSpeed * 12;
play.yPos -= ship.ySpeed * 12;
}
if (ship.kamikazeCooldown == 14) {
ship.kamikaze = false;
ship.kamikazeCooldown = 0;
ship.boost = false;
}
} else {
play.score = 0;
}
//if (jjGameTicks % 21 == 0 && ship.thrust) jjDebug("" + play.ySpeed, false);
if ((jjGameMode == GAME::BATTLE && (jjGameCustom != GAME::LRS || jjGameCustom != GAME::XLRS || jjGameCustom != GAME::PEST)) || jjGameCustom == GAME::TB) {
if (play.blink != 0) {
ship.health = ship.SDPunishment? 1:maxHealth;
} else ship.SDPunishment = false;
if (play.health == 0) {
ship.health = ship.SDPunishment? 1:maxHealth;
ship.armor = 0;
}
}
if (ship.health > maxHealth && jjGameTicks % (ship.health > int(maxHealth*1.5) && ship.health < (maxHealth*2)? 28:70) == 0 && play.blink == 0 && jjGameState != GAME::STOPPED) {
ship.health--;
}
if (ship.armor < 0) ship.armor = 0;
if (ship.armor > maxHealth && jjGameTicks % (ship.armor > int(maxHealth*1.5) && ship.armor < (maxHealth*2)? 28:70) == 0 && play.blink == 0 && jjGameState != GAME::STOPPED) {
ship.armor--;
}
if (jjMaxHealth == 1) {
ship.health = 1;
ship.armor = 0;
}
if (ship.health > (maxHealth*2)) {
ship.health = (maxHealth*2);
}
if (ship.armor > (maxHealth*2)) {
ship.armor = (maxHealth*2);
}
switch (play.currWeapon) {
case WEAPON::BLASTER:
if (currentWeapon == 1) play.fastfire = jjMaxHealth == 1? 45:13;
break;
case WEAPON::BOUNCER:
if (currentWeapon == 2) play.fastfire = 6;
break;
case WEAPON::ICE:
if (currentWeapon == 3) play.fastfire = 55;
break;
case WEAPON::SEEKER:
if (currentWeapon == 4) play.fastfire = 65;
break;
case WEAPON::RF:
if (currentWeapon == 5) play.fastfire = 110;
break;
case WEAPON::TOASTER:
if (currentWeapon == 6) play.fastfire = 4;
break;
case WEAPON::TNT:
if (currentWeapon == 7) play.fastfire = 65;
break;
case WEAPON::GUN8:
if (currentWeapon == 8) play.fastfire = 50;
break;
case WEAPON::GUN9:
if (currentWeapon == 9) play.fastfire = 11;
break;
default: break;
}
while (play.ammo[currentWeapon] == 0 && play.currWeapon != WEAPON::BLASTER) {
currentWeapon--;
play.currWeapon = currentWeapon;
}
if (ship.powerUp) {
if (jjGameState != GAME::STOPPED) ship.powerTime--;
for (int i = 1; i <= 9; i++) {
play.powerup[i] = true;
}
} else {
for (int i = 1; i <= 9; i++) {
play.powerup[i] = false;
}
}
if (ship.powerTime <= 0 && ship.powerUp) {
ship.powerTime = 0;
ship.powerUp = false;
if (play.isLocal) jjSample(play.xPos, play.yPos, SOUND::COMMON_SHLDOF3, 0, 0);
}
play.xAcc = play.yAcc = 0;
if (jjMaxHealth == 1) {
for (int i = 2; i <= 9; i++) {
play.ammo[i] = 0;
}
}
if (play.health > 0) {
play.xSpeed = ship.xSpeed;
play.ySpeed = ship.ySpeed;
if (ship.ySpeed < 0.05 && ship.ySpeed > -0.05) {
ship.ySpeed = 0;
}
if (ship.ySpeed == 0) {
play.ySpeed = 0;
play.yPos -= 0.125f;
}
if (ship.xSpeed < 0.05 && ship.xSpeed > -0.05) {
ship.xSpeed = 0;
}
if (ship.xSpeed == 0) {
play.xSpeed = 0;
if (play.keyRight && !jjMaskedPixel(int(play.xPos-16), int(play.yPos))) play.xPos -= (play.keyRun? 0.368f : 0.183f);
if (play.keyLeft && !jjMaskedPixel(int(play.xPos+16), int(play.yPos))) play.xPos += (play.keyRun? 0.368f : 0.183f);
}
}
if (jjGameTicks % 70 == 69) {
if (ship.rotationSpeed != 0) {
ship.rotating = true;
}
}
if (jjGameTicks % 70 == 69 && (ship.rotating || play.health == 0 || ship.wasHit)) {
sendShipRotationPacket(ship);
ship.rotating = false;
ship.wasHit = false;
}
if (play.ySpeed > (play.keyRun? 8:6)) play.ySpeed = (play.keyRun? 8:6);
if (play.ySpeed < -6 && !play.keyRun) play.ySpeed = -6;
if (!ship.reverse) {
if (ship.xAcc < 0) ship.xAcc = 0;
if (ship.yAcc < 0) ship.yAcc = 0;
}
if (ship.thrust && !ship.reverse) {
if (!ship.justHit) {
ship.xSpeed = (jjCos(ship.angle) * ship.xAcc) + ship.xMomentum;
ship.ySpeed = (-jjSin(ship.angle) * ship.yAcc) + ship.yMomentum;
}
if (ship.xMomentum > 0) ship.xMomentum -= 0.05;
if (ship.xMomentum < 0) ship.xMomentum += 0.05;
if (ship.yMomentum > 0) ship.yMomentum -= 0.05;
if (ship.yMomentum < 0) ship.yMomentum += 0.05;
if (ship.xAcc < (play.keyRun? ship.maxSpeed:ship.maxTurningSpeed)) ship.xAcc += 0.2;
if (ship.yAcc < (play.keyRun? ship.maxSpeed:ship.maxTurningSpeed)) ship.yAcc += 0.2;
} else {
if (ship.reverse && !ship.thrust) {
if (!ship.justHit) {
ship.xSpeed = (jjCos(ship.angle) * ship.xAcc) + ship.xMomentum;
ship.ySpeed = (-jjSin(ship.angle) * ship.yAcc) + ship.yMomentum;
}
if (ship.xMomentum > 0) ship.xMomentum -= 0.1;
if (ship.xMomentum < 0) ship.xMomentum += 0.1;
if (ship.yMomentum > 0) ship.yMomentum -= 0.1;
if (ship.yMomentum < 0) ship.yMomentum += 0.1;
if (ship.xAcc > (play.keyRun? -ship.maxSpeedRev:-ship.maxTurningSpeedRev)) ship.xAcc -= 0.085;
if (ship.yAcc > (play.keyRun? -ship.maxSpeedRev:-ship.maxTurningSpeedRev)) ship.yAcc -= 0.085;
} else {
ship.xMomentum = play.xSpeed * 0.75;
ship.yMomentum = play.ySpeed * 0.75;
if (jjMaskedHLine(int(play.xPos + ship.xSpeed), -32, int(play.yPos)) || jjMaskedHLine(int(play.xPos - ship.xSpeed), 32, int(play.yPos))) {
ship.xSpeed = ship.xAcc = ship.xMomentum = 0;
}
if (jjMaskedVLine(int(play.xPos), int(play.yPos + ship.ySpeed), -32) || jjMaskedVLine(int(play.xPos), int(play.yPos - ship.ySpeed), 32)) {
ship.ySpeed = ship.yAcc = ship.yMomentum = 0;
}
if (ship.xMomentum > ship.maxSpeed) ship.xMomentum = ship.maxSpeed;
if (ship.xMomentum < -ship.maxSpeed) ship.xMomentum = -ship.maxSpeed;
if (ship.yMomentum > ship.maxSpeed) ship.yMomentum = ship.maxSpeed;
if (ship.yMomentum < -ship.maxSpeed) ship.yMomentum = -ship.maxSpeed;
if (ship.xSpeed > 0) ship.xSpeed -= 0.1;
else if (ship.xSpeed < 0) ship.xSpeed += 0.1;
if (ship.ySpeed > 0) ship.xSpeed -= 0.1;
else if (ship.ySpeed < 0) ship.ySpeed += 0.1;
if (ship.xAcc > (ship.xSpeed * (ship.xSpeed > 0? -1:1))) {
ship.xAcc -= 0.5;
}
if (ship.yAcc > (ship.ySpeed * (ship.ySpeed > 0? -1:1))) {
ship.yAcc -= 0.5;
}
if (ship.ySpeed > 0 && ship.ySpeed < ship.maxSpeed && ship.yAcc <= 0 && !ship.boost) {
ship.ySpeed -= 0.025;
}
if (play.keyDown && !ship.boost) {
ship.xAcc = ship.yAcc = 0;
}
}
}
play.buttstomp = 100;
//if (jjGameTicks % 21 == 0 && ship.thrust) jjDebug("" + ship.angle, false);
if (play.xSpeed > ship.maxSpeed) play.xSpeed = ship.maxSpeed;
if (play.xSpeed < -ship.maxSpeed) play.xSpeed = -ship.maxSpeed;
if (play.ySpeed > ship.maxSpeed) play.ySpeed = ship.maxSpeed;
if (play.ySpeed < -ship.maxSpeed) play.ySpeed = -ship.maxSpeed;
if (!ship.boost) {
if (play.xSpeed > ship.maxDiagonalSpeed && play.ySpeed > ship.maxDiagonalSpeed) {
play.xSpeed = ship.maxDiagonalSpeed;
play.ySpeed = ship.maxDiagonalSpeed;
}
if (play.xSpeed > ship.maxDiagonalSpeed && play.ySpeed < -ship.maxDiagonalSpeed) {
play.xSpeed = ship.maxDiagonalSpeed;
play.ySpeed = -ship.maxDiagonalSpeed;
}
if (play.xSpeed < -ship.maxDiagonalSpeed && play.ySpeed > ship.maxDiagonalSpeed) {
play.xSpeed = -ship.maxDiagonalSpeed;
play.ySpeed = ship.maxDiagonalSpeed;
}
if (play.xSpeed < -ship.maxDiagonalSpeed && play.ySpeed < -ship.maxDiagonalSpeed) {
play.xSpeed = -ship.maxDiagonalSpeed;
play.ySpeed = -ship.maxDiagonalSpeed;
}
}
if (jjMaskedPixel(int(play.xPos) + int(ship.xSpeed), int(play.yPos) + int(ship.ySpeed)) && !ship.thrust) {
ship.xAcc = ship.yAcc = ship.xMomentum = ship.yMomentum = 0;
}
int screenLimitX = (jjLayerWidth[4]*32)-400;
int screenLimitY = (jjLayerHeight[4]*32)-400;
int screenCentreX = (int(play.xPos) <= 400)? int(play.xPos) : int(play.xPos) >= screenLimitX? int(jjSubscreenWidth / 2) + int(abs(screenLimitX - int(play.xPos))) : int(jjSubscreenWidth / 2);
int screenCentreY = (int(play.yPos) <= 400)? int(play.yPos) : int(play.yPos) >= screenLimitY? int(jjSubscreenHeight / 2) + int(abs(screenLimitY - int(play.yPos))) : int(jjSubscreenHeight / 2);
ship.fireAngle = int(atan2(jjMouseY - screenCentreY, -(jjMouseX - screenCentreX)) * (512 / PI)) - 512;
if ((play.keyFire || ((!jjMouseAim || !jjAllowsMouseAim) && jjKey[0x01])) && !ship.fire) {
if (bufferedWeapon > 0) play.currWeapon = bufferedWeapon;
play.fireBullet(WEAPON::CURRENT, true, true, ((ship.fireAngle+256+(play.currWeapon == WEAPON::TOASTER? 512:0))/512) * -PI);
ship.fire = true;
currentWeapon = play.currWeapon;
}
if ((play.keyFire || ((!jjMouseAim || !jjAllowsMouseAim) && jjKey[0x01])) && play.currWeapon == WEAPON::TOASTER && play.ammo[WEAPON::TOASTER] > 0) {
ship.sample2 = jjSampleLooped(play.xPos, play.yPos, SOUND::COMMON_FLAMER, ship.sample2);
}
if (ship.fire) {
ship.fireDelay++;
if (ship.fireDelay >= play.fastfire) {
ship.fire = false;
ship.fireDelay = 0;
if (ship.stopWeaponChange) {
play.currWeapon = bufferedWeapon;
ship.stopWeaponChange = false;
}
}
if (play.currWeapon != currentWeapon) {
bufferedWeapon = play.currWeapon;
play.currWeapon = currentWeapon;
ship.stopWeaponChange = true;
}
} else {
if (ship.stopWeaponChange) {
play.currWeapon = bufferedWeapon;
ship.stopWeaponChange = false;
}
bufferedWeapon = 0;
if (jjGameTicks % 16 == 0) {
if (play.ammo[WEAPON::BLASTER] < jjWeapons[WEAPON::BLASTER].maximum) {
play.ammo[WEAPON::BLASTER] = play.ammo[WEAPON::BLASTER] + 1;
}
}
}
if (play.ammo[WEAPON::BLASTER] < 1 && play.currWeapon != WEAPON::BLASTER) {
play.ammo[WEAPON::BLASTER] = 1;
}
if (jjKey[0x02] && jjKey[0x12]) {
radarX = int(jjMouseX);
radarY = int(jjMouseY);
}
if (jjKey[0x04]) {
radarX = 100;
radarY = jjSubscreenHeight - 220;
}
if (crosshairFlash) {
crosshairTime++;
if (crosshairTime > 21) crosshairFlash = false;
}
} else {
play.spriteMode = SPRITE::PLAYER;
jjCharacters[play.charCurr].airJump = AIR::DOUBLEJUMP;
play.jumpStrength = -10;
}
active = play.isInGame;
if (jjMaxHealth == 1) {
play.currWeapon = currentWeapon = 1;
}
}
void handleOnPlayerInput(jjPLAYER@ play) {
SPACESHIP@ ship = Ships[play.playerID];
if (play.keyJump || ((!jjAllowsMouseAim || !jjMouseAim) && jjKey[0x02])) {
if (play.blink == 0 && (play.xSpeed > 6 || play.xSpeed < -6 || play.ySpeed > 6 || play.ySpeed < -6)) {
if (ship.boostTime == 2.5*70) {
ship.boost = true;
play.keyRun = true;
}
}
play.keyJump = false;
} else {
if (ship.boost && ship.boostTime < 105) ship.boost = false;
if (jjMaskedPixel(int(play.xPos), int(play.yPos)) && play.health > 0 && !ship.kamikaze) {
kamikazeAttack(play, ship);
ship.killShip = true;
}
}
}
void kamikazeAttack(jjPLAYER@ play, SPACESHIP@ ship) {
ship.kamikaze = true;
ship.boost = true;
sendShipRotationPacket(ship);
play.xSpeed *= -8;
play.ySpeed *= -8;
play.score = 1;
if ((ship.health - ship.damageCalc(ship, ship.killShip? 50:35)) > 0) {
if (play.isLocal) {
ship.health -= ship.damageCalc(ship, ship.killShip? 50:35);
if (ship.armor > 0) ship.armor -= ship.damageCalc(ship, ship.killShip? 50:35) * 2;
}
} else {
if (play.isLocal) {
play.blink = -1;
ship.SDPunishment = true;
play.hurt(7, true);
}
}
ship.justHit = true;
ship.hitDelay = 0;
if (ship.killShip) {
ship.angle -= 512;
}
play.fireBullet(WEAPON::RF, false, false, ((ship.angle+512)/512) * -PI);
}
void spawnFireTrail(jjPLAYER@ play, SPACESHIP@ ship) {
jjOBJ@ trail = jjObjects[jjAddObject(OBJECT::EXPLOSION, int(play.xPos - jjCos(ship.angle)), int(play.yPos - jjSin(ship.angle)))];
trail.determineCurAnim(ANIM::AMMO, !ship.reverse? 3:2);
trail.lightType = ship.reverse? LIGHT::NONE : LIGHT::POINT;
trail.playerHandling = HANDLING::PARTICLE;
trail.bulletHandling = HANDLING::IGNOREBULLET;
trail.isBlastable = false;
}
void damagedShipTrail(jjPLAYER@ play) {
jjPARTICLE@ cinders = jjAddParticle(PARTICLE::SMOKE);
cinders.xPos = (play.xPos - 16) + jjRandom()%32;
cinders.yPos = (play.yPos - 16) + jjRandom()%32;
cinders.ySpeed = -1;
}
void boostingShipTrail(jjPLAYER@ play) {
jjPARTICLE@ fire = jjAddParticle(PARTICLE::FIRE);
fire.xPos = (play.xPos - 16) + jjRandom()%32;
fire.yPos = (play.yPos - 16) + jjRandom()%32;
fire.xSpeed = play.xSpeed * -2;
fire.ySpeed = play.ySpeed * -2;
}
void randomHurtSample(jjPLAYER@ play, int volume) {
SOUND::Sample sample = SOUND::JAZZSOUNDS_HEY2;
switch (jjRandom()%4) {
case 0: sample = play.charCurr == CHAR::JAZZ? SOUND::JAZZSOUNDS_HEY2 : play.charCurr == CHAR::SPAZ? SOUND::SPAZSOUNDS_AUTSCH1 : SOUND::LORISOUNDS_HURT0; break;
case 1: sample = play.charCurr == CHAR::JAZZ? SOUND::JAZZSOUNDS_HEY3 : play.charCurr == CHAR::SPAZ? SOUND::SPAZSOUNDS_AUTSCH2 : SOUND::LORISOUNDS_HURT1; break;
case 2: sample = play.charCurr == CHAR::JAZZ? SOUND::JAZZSOUNDS_HEY4 : play.charCurr == CHAR::SPAZ? SOUND::SPAZSOUNDS_AUTSCH1 : SOUND::LORISOUNDS_HURT2; break;
case 3: sample = play.charCurr == CHAR::JAZZ? SOUND::JAZZSOUNDS_JAZZV4 : play.charCurr == CHAR::SPAZ? SOUND::SPAZSOUNDS_OOOH : SOUND::LORISOUNDS_HURT7; break;
}
jjSample(play.xPos, play.yPos, sample, volume, 0);
}
void handleOnMain() {
for (int i = 1; i <= 9; i++) {
if (jjWeapons[i].allowed)
jjWeapons[i].allowedPowerup = true;
}
switch (jjMaxHealth) {
case 1: maxHealth = 1; break;
case 2: maxHealth = 50; break;
case 3: maxHealth = jjGameMode == GAME::CTF? 100:70; break;
case 4: maxHealth = jjGameMode == GAME::CTF? 125:85; break;
case 5: maxHealth = jjGameMode == GAME::CTF? 150:100; break;
case 6: maxHealth = jjGameMode == GAME::CTF? 175:150; break;
case 7: maxHealth = 200; break;
}
if (!jjLocalPlayers[0].isIdle) {
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
if (!play.isInGame)
continue;
SPACESHIP@ ship = Ships[i];
SPACESHIP@ ship2 = Ships[jjLocalPlayers[0].playerID];
float dx = jjLocalPlayers[0].xPos - play.xPos, dy = jjLocalPlayers[0].yPos - play.yPos;
if ((dx * dx + dy * dy < 64 * 64) && jjLocalPlayers[0].health > 0 && jjLocalPlayers[0].blink == 0 && jjLocalPlayers[0] !is play && !ship2.kamikaze && ship2.boost && play.health > 0 && play.blink == 0) {
kamikazeAttack(jjLocalPlayers[0], ship2);
}
if (ship.justHit) {
ship.hitDelay++;
if (ship.hitDelay >= 7) {
ship.justHit = false;
ship.wasHit = true;
}
}
if (ship.hasShip) {
if (play.powerup[WEAPON::TNT]) {
ship.tntPowerup = true;
} else {
if (!ship.powerUp) {
ship.tntPowerup = false;
}
}
if (ship.damageAccumulated > 0) {
ship.accumulationTime++;
if (ship.accumulationTime == 210) {
ship.damageAccumulated = ship.accumulationTime = 0;
}
}
play.lightType = ship.health > maxHealth? LIGHT::LASER : (ship.armor > maxHealth? LIGHT::BRIGHT : LIGHT::PLAYER);
play.light = 12;
if (ship.powerUp) {
jjDrawRotatedSprite(play.xPos, play.yPos, customAnimID, ship.anim, 0, ship.angle - 256, 1.25, 1.25, ship.justHit? SPRITE::SINGLECOLOR : SPRITE::TRANSLUCENTCOLOR, ship.justHit? 15 : 24 + (jjGameTicks % 7), 4, 4);
}
if (ship.thrust || ship.reverse) {
if (!ship.reverse) {
if (jjGameTicks % (play.keyRun? 4:8) == 0) spawnFireTrail(play, ship);
} else {
if (jjGameTicks % (play.keyRun? 8:12) == 0) spawnFireTrail(play, ship);
}
if (play.isLocal) ship.sample = jjSampleLooped(play.xPos, play.yPos, SOUND::FAN_FAN, ship.sample, (ship.boost? 48:24), (!play.keyRun? 7500:ship.boost? 10000:8000));
}
if (jjGameTicks % 3 == 0 && ship.health <= int(maxHealth*0.3)) damagedShipTrail(play);
ship.thrust = play.keyUp || play.keyLeft || play.keyRight || play.keyDown || ship.boost;
//ship.reverse = play.keyDown;
ship.rotationSpeed = !ship.thrust? 0: ship.boost? 18:16;
if (ship.boost) {
boostingShipTrail(play);
} else {
if (ship.boostTime < 2.5*70 && jjGameTicks % 3 == 0) ship.boostTime++;
}
if (ship.angle <= -512) ship.angle = 512;
if (ship.angle == 512 && play.keyDown) {
ship.angle = -511;
}
if (play.keyRight) {
if (play.keyUp) {
setShipAngle(ship, play, ship.angle <= -256? -511:128);
} else if (play.keyDown) {
setShipAngle(ship, play, -128);
} else {
setShipAngle(ship, play, 0);
}
} else if (play.keyLeft) {
if (play.keyUp) {
setShipAngle(ship, play, ship.angle <= -256? -511 : 384);
} else if (play.keyDown) {
setShipAngle(ship, play, ship.angle >= 256? 512 : -384);
} else {
setShipAngle(ship, play, ship.angle <= -256? -511 : ship.angle > 0? 511 : -511);
}
} else if (play.keyUp && !play.keyLeft && !play.keyRight) {
setShipAngle(ship, play, ship.angle <= -256? -511 : 256);
} else if (play.keyDown && !play.keyLeft && !play.keyRight) {
setShipAngle(ship, play, ship.angle >= 256? 512 : -256);
}
if (ship.angle == 511 || ship.angle == -511) ship.angle = 512;
switch (play.charCurr) {
case CHAR::JAZZ: ship.anim = 0; break;
case CHAR::SPAZ: ship.anim = 1; break;
case CHAR::LORI: ship.anim = 2; break;
default: ship.anim = 0; break;
}
if (play.health > 0 && play.isInGame) {
if (jjGameTicks % 7 == 0 || play.blink == 0) {
jjDrawRotatedSprite(play.xPos, play.yPos, customAnimID, ship.anim, 0, ship.angle - 256, 1, 1, ship.justHit? SPRITE::SINGLECOLOR : SPRITE::PLAYER, ship.justHit? 15 : play.playerID, 4, 4);
if (ship.armor > 0) {
jjDrawSprite(play.xPos, play.yPos, ANIM::MENU, 1, (ship.armor <= int(maxHealth*0.3)? 0 : ship.armor >= int(maxHealth*0.7)? 8 : 3), 0, SPRITE::ALPHAMAP, ship.armor > maxHealth? 34 : ship.armor >= int(maxHealth*0.7)? 80 : ship.armor > int(maxHealth*0.3)? 41 : 24);
}
}
} else if (play.health == 0 && play.isInGame) {
if (play.blink <= 0) {
play.blink = 210;
jjOBJ@ dummy = jjObjects[jjAddObject(OBJECT::PURPLEGEM, play.xPos, play.yPos)];
}
}
}
}
}
if (jjGameMode <= GAME::COOP)
return;
jjOBJ@ bogus = jjObjects[0];
bogus.creator = CREATOR::PLAYER;
jjPLAYER@ creator = jjPlayers[bogus.creatorID];
for (uint playerID = 0; playerID < 32; ++playerID, ++bogus.creator) {
const jjPLAYER@ play = jjPlayers[playerID];
if (play.isInGame) {
bogus.xPos = play.xPos;
bogus.yPos = play.yPos;
closestPlayers[playerID] = MLLEWeapons::HelpfulBulletFunctions::GetNearestEnemyPlayer(bogus, 350);
}
}
}
void setShipAngle(SPACESHIP@ ship, jjPLAYER@ play, int targetAngle) {
if (ship.angle < targetAngle) ship.angle += ship.rotationSpeed;
else if (ship.angle > targetAngle) ship.angle -= ship.rotationSpeed;
if (ship.angle >= targetAngle - ship.rotationSpeed && ship.angle <= targetAngle + ship.rotationSpeed) {
ship.angle = targetAngle;
}
}
void handleOnReceive(jjSTREAM &in packet, int clientID) {
if (jjIsServer) {
int angle, health, armor;
bool hasShip, powerUp, kamikaze, boost;
packet.pop(angle);
packet.pop(health);
packet.pop(armor);
packet.pop(hasShip);
packet.pop(powerUp);
packet.pop(kamikaze);
packet.pop(boost);
jjPLAYER@ play = jjPlayers[clientID];
Ships[play.playerID].angle = angle;
Ships[play.playerID].health = health;
Ships[play.playerID].armor = armor;
Ships[play.playerID].hasShip = hasShip;
Ships[play.playerID].powerUp = powerUp;
Ships[play.playerID].kamikaze = kamikaze;
Ships[play.playerID].boost = boost;
updateShipAnglesForClients(clientID, angle, health, armor, hasShip, powerUp, kamikaze, boost);
} else {
int id, angle, health, armor;
bool hasShip, powerUp, kamikaze, boost;
packet.pop(id);
packet.pop(angle);
packet.pop(health);
packet.pop(armor);
packet.pop(hasShip);
packet.pop(powerUp);
packet.pop(kamikaze);
packet.pop(boost);
jjPLAYER@ play = jjPlayers[id];
if (!play.isLocal) {
Ships[id].angle = angle;
Ships[id].health = health;
Ships[id].armor = armor;
Ships[id].hasShip = hasShip;
Ships[id].powerUp = powerUp;
Ships[id].kamikaze = kamikaze;
Ships[id].boost = boost;
}
}
}
void sendShipRotationPacket(SPACESHIP@ ship) {
if (!jjIsServer) {
jjSTREAM packet;
packet.push(ship.angle);
packet.push(ship.health);
packet.push(ship.armor);
packet.push(ship.hasShip);
packet.push(ship.powerUp);
packet.push(ship.kamikaze);
packet.push(ship.boost);
jjSendPacket(packet);
//jjDebug("send", false);
} else {
updateShipAnglesForClients(0, ship.angle, ship.health, ship.armor, ship.hasShip, ship.powerUp, ship.kamikaze, ship.boost);
//jjDebug("send", false);
}
}
void updateShipAnglesForClients(int id, int angle, int health, int armor, bool hasShip, bool powerUp, bool kamikaze, bool boost) {
jjSTREAM packet;
packet.push(id);
packet.push(angle);
packet.push(health);
packet.push(armor);
packet.push(hasShip);
packet.push(powerUp);
packet.push(kamikaze);
packet.push(boost);
jjSendPacket(packet);
}
bool handleOnDrawAmmo(jjPLAYER@ play, jjCANVAS@ canvas) {
SPACESHIP@ ship = Ships[play.playerID];
int box_X = 64, box_Y = 64;
int boxWidth = jjSubscreenWidth - (box_X * 2);
int boxHeight = jjSubscreenHeight - (box_Y * 2);
//array<string> controls = {
//"||||Use the |||||MOVEMENT KEYS||| to pilot your ship",
//"",
//"||||Press and hold |||||RUN||| to move faster",
//"",
//"||||Move the |||||MOUSE||| to aim your weapon",
//"",
//"||||Press |||||FIRE||| or |||||LEFT MOUSE||| to shoot",
//"",
//"||||Press and hold |||||JUMP||| to activate your ship's boosters",
//"",
//"||||Click and drag |||||LEFT MOUSE||| while holding |||||ALT||| to reposition",
//"||||the ship's radar HUD",
//"",
//"||||Click |||||RIGHT MOUSE||| while holding |||||ALT||| to reset the ",
//"||||ship's radar HUD position to default"
//};
//array<string> weaponNames = {
//"|1. Blaster",
//"|2. Rapid Blaster",
//"|3. Burster",
//"|4. Homing Missile",
//"|5. Super Missile",
//"|6. Flamethrower",
//"|7. Spike Mine",
//"|8. Laser Cannon",
//"|9. Electro Blaster"
//};
//array<string> weaponDamages = {
//"Damage: 12",
//"Damage: 4",
//"Damage: 25-75",
//"Damage: 30",
//"Damage: 90 (1-89 for explosion)",
//"Damage: 6",
//"Damage: 75 (1-74 for explosion)",
//"Damage: 40",
//"Damage: 18"
//};
//array<string> weaponMaxAmmo = {
//"Max Ammo: 25 (regenerates)",
//"Max Ammo: 100 (+5 per pickup)",
//"Max Ammo: 25 (+2 per pickup)",
//"Max Ammo: 15 (+2 per pickup)",
//"Max Ammo: 10 (+1 per pickup)",
//"Max Ammo: 50 (+3 per pickup)",
//"Max Ammo: 10 (+1 per pickup)",
//"Max Ammo: 35 (+3 per pickup)",
//"Max Ammo: 70 (+4 per pickup)"
//};
[preview ends here]
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.