Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Anniversary Bash 23 levels | Jazz2Online | Multiple | N/A |
#include "MLLE-Include-1.5w.asc" ///@MLLE-Generated
#pragma require "ab23btl12.j2l" ///@MLLE-Generated
#include "SEfirework-mlle.asc" ///@MLLE-Generated
#pragma require "SEfirework-mlle.asc" ///@MLLE-Generated
class CustomWeaponHook : se::DefaultWeaponHook {
bool drawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) override {
int x, y;
STRING::Size font;
string text;
const jjWEAPON@ weapon = jjWeapons[player.currWeapon];
if (jjSubscreenWidth > 400) {
x = jjSubscreenWidth - 88;
y = jjSubscreenHeight - 14;
font = STRING::MEDIUM;
} else {
x = jjSubscreenWidth - 48;
y = jjSubscreenHeight - 9;
font = STRING::SMALL;
}
if (weapon.infinite || weapon.replacedByShield && player.shieldTime > 0) {
text = "x^";
} else {
int ammo = player.ammo[WEAPON::CURRENT];
text = "x" + (ammo > 0 ? ammo : 0);
}
drawAmmoSprite(canvas, x, y, getWeaponAnimation(player.currWeapon, player.powerup[WEAPON::CURRENT]));
canvas.drawString(x + 8, y, text, font);
return true;
}
}
array<int> lastFired(jjLocalPlayerCount);
array<int> lenientLastFired(jjLocalPlayerCount);
array<bool> missileFired(jjLocalPlayerCount);
array<bool> selectPressed(jjLocalPlayerCount);
array<bool> tongueUsed(jjLocalPlayerCount);
bool canFire(const jjPLAYER@ player) {
switch (jjWeapons[player.currWeapon].style) {
case WEAPON::MISSILE:
return !missileFired[player.localPlayerID];
case WEAPON::POPCORN:
return jjGameTicks - lenientLastFired[player.localPlayerID] >= 6;
case WEAPON::CAPPED:
return jjGameTicks - lastFired[player.localPlayerID] >= player.fastfire;
}
return jjGameTicks - lenientLastFired[player.localPlayerID] >= player.fastfire;
}
void processFiring(const jjPLAYER@ player) {
if (jjWeapons[player.currWeapon].style == WEAPON::MISSILE)
missileFired[player.localPlayerID] = true;
lastFired[player.localPlayerID] = jjGameTicks;
lenientLastFired[player.localPlayerID] = jjGameTicks;
}
void processNotFiring(const jjPLAYER@ player) {
missileFired[player.localPlayerID] = false;
lenientLastFired[player.localPlayerID] = -252000;
}
void cycleWeapon(jjPLAYER@ player) {
auto initial = player.currWeapon;
do {
player.currWeapon = player.currWeapon % 9 + 1;
} while (player.currWeapon != initial && getRealAmmo(player, WEAPON::CURRENT) == 0);
}
jjANIMATION@ getWeaponAnimation(int weapon, bool powerup) {
int modifier = powerup ? 1 : 0;
switch (weapon) {
case WEAPON::BLASTER:
return jjAnimations[powerup ? jjAnimSets[ANIM::AMMO] + 18 : jjAnimSets[ANIM::PICKUPS] + 29];
case WEAPON::BOUNCER:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 25 - modifier];
case WEAPON::ICE:
return jjAnimations[jjAnimSets[ANIM::CUSTOM[0]] + modifier];
case WEAPON::SEEKER:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 34 - modifier];
case WEAPON::RF:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 49 - modifier];
case WEAPON::TOASTER:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 57 - modifier];
case WEAPON::TNT:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 59];
case WEAPON::GUN8:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 62 - modifier];
case WEAPON::GUN9:
return jjAnimations[jjAnimSets[ANIM::AMMO] + 68 - modifier];
}
return null;
}
int getWeaponEventID(int weapon, bool powerup, bool &out pepper) {
auto spread = jjWeapons[weapon].spread;
if (spread == SPREAD::PEPPERSPRAY || spread == SPREAD::GUN8 && !jjAllowsFireball) {
pepper = true;
return OBJECT::BULLET;
}
pepper = false;
int modifier = powerup ? 8 : 0;
switch (weapon) {
case WEAPON::BLASTER:
return OBJECT::BLASTERBULLET + modifier;
case WEAPON::BOUNCER:
return OBJECT::BOUNCERBULLET + modifier;
case WEAPON::ICE:
return OBJECT::ICEBULLET + modifier;
case WEAPON::SEEKER:
return OBJECT::SEEKERBULLET + modifier;
case WEAPON::RF:
return OBJECT::RFBULLET + modifier;
case WEAPON::TOASTER:
return OBJECT::TOASTERBULLET + modifier;
case WEAPON::TNT:
return OBJECT::TNT;
case WEAPON::GUN8:
return OBJECT::FIREBALLBULLET + modifier;
case WEAPON::GUN9:
return OBJECT::ELECTROBULLET + modifier;
}
return 0;
}
void drawAmmoSprite(jjCANVAS@ canvas, int x, int y, const jjANIMATION@ anim) {
if (anim !is null)
canvas.drawSpriteFromCurFrame(x, y, anim + (::jjGameTicks >> 2) % anim.frameCount);
}
void fireBullet(const jjPLAYER@ player, int angle, float x, float y) {
bool pepper;
auto eventID = getWeaponEventID(player.currWeapon, player.powerup[WEAPON::CURRENT], pepper);
int id = jjAddObject(eventID, x, y, player.playerID, CREATOR::PLAYER, pepper ? BEHAVIOR::PEPPERBULLET : BEHAVIOR::DEFAULT);
if (id > 0) {
auto@ obj = jjObjects[id];
if (pepper) {
bool powerup = jjStrongPowerups && player.powerup[WEAPON::CURRENT];
obj.playerHandling = HANDLING::PLAYERBULLET;
obj.determineCurAnim(ANIM::AMMO, powerup ? 10 : 9);
obj.determineCurFrame();
obj.animSpeed = player.powerup[WEAPON::CURRENT] ? 2 : 1;
obj.var[3] = 8;
obj.xSpeed = 4.f;
if (powerup) {
obj.lightType = LIGHT::POINT2;
obj.state = STATE::FLY;
obj.var[6] = obj.var[6] | 8;
}
}
float speed = obj.xSpeed;
float acc = obj.xAcc;
obj.xSpeed = jjCos(angle << 7) * speed;
obj.ySpeed -= jjSin(angle << 7) * speed;
obj.xAcc = jjCos(angle << 7) * acc;
obj.yAcc -= jjSin(angle << 7) * acc;
obj.direction = angle < 2 ? 1 : angle > 2 ? -1 : 0;
}
}
int getRealAmmo(const jjPLAYER@ player, int weapon) {
if (weapon == WEAPON::CURRENT)
weapon = player.currWeapon;
auto@ preset = jjWeapons[weapon];
int multiplier = preset.multiplier;
preset.multiplier = 1;
int result = player.ammo[weapon];
preset.multiplier = multiplier;
return result;
}
void decrementRealAmmo(jjPLAYER@ player, int weapon) {
if (weapon == WEAPON::CURRENT)
weapon = player.currWeapon;
auto@ preset = jjWeapons[weapon];
int multiplier = preset.multiplier;
preset.multiplier = 1;
player.ammo[weapon] = player.ammo[weapon] - 1;
preset.multiplier = multiplier;
}
void coinMorph(jjOBJ@ obj) {
if (obj.state == STATE::DEACTIVATE) {
obj.deactivate();
return;
}
if (obj.state == STATE::START) {
int x = int(obj.xOrg) >>> 5;
int y = int(obj.yOrg) >>> 5;
if (jjParameterGet(x, y, 17, 1) == 0) {
obj.delete();
return;
}
obj.state = STATE::STILL;
obj.var[0] = jjParameterGet(x, y, 8, 8);
obj.var[1] = jjParameterGet(x, y, 0, 8);
obj.var[2] = jjParameterGet(x, y, 16, 1);
obj.var[3] = jjParameterGet(x, y, 18, 1);
obj.xPos -= 16.f;
obj.yPos -= 16.f;
obj.putOnGround(true);
return;
}
auto@ bunny = jjAnimations[obj.curAnim];
auto@ booth = jjAnimations[obj.special];
obj.counter++;
if (obj.counter & 7 == 0) {
obj.frameID++;
if (obj.frameID >= int(bunny.frameCount))
obj.frameID = 0;
obj.determineCurFrame();
}
jjDrawSpriteFromCurFrame(obj.xPos - 1.f, obj.yPos + 3.f, booth + (obj.counter >> 3) % booth.frameCount, obj.direction, SPRITE::PALSHIFT, 16);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame + bunny.frameCount, obj.direction);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::PALSHIFT, 40);
if (obj.var[0] != 0) {
jjTEXTAPPEARANCE style(STRING::BOUNCE);
style.align = STRING::CENTER;
jjDrawString(obj.xPos - 4.f, obj.yPos - 12.f, formatInt(obj.var[0]), STRING::SMALL, style, 0, SPRITE::PALSHIFT, 224);
}
for (int i = 0; i < jjLocalPlayerCount; i++) {
auto@ player = jjLocalPlayers[i];
float dx = player.xPos - obj.xPos;
float dy = player.yPos - obj.yPos;
if (dx * dx + dy * dy < 1024.f && player.charCurr != CHAR::BIRD && player.testForCoins(obj.var[0])) {
player.morphTo(CHAR::BIRD);
jjSample(player.xPos, player.yPos, SOUND::COMMON_BUBBLGN1);
}
}
}
bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
return MLLE::WeaponHook.drawAmmo(player, canvas);
}
void onLevelLoad() {
@MLLE::WeaponHook = CustomWeaponHook();
MLLE::Setup(array<MLLEWeaponApply@> = {null, null, se::FireworkMLLEWrapper(), null, null, null, null, null, null});
jjCharacters[CHAR::FROG].canHurt = true;
jjCharacters[CHAR::FROG].canRun = true;
jjCharacters[CHAR::BIRD].canHurt = true;
jjCharacters[CHAR::BIRD].canRun = true;
jjObjectPresets[OBJECT::WARP].behavior = coinMorph;
}
void onPlayerInput(jjPLAYER@ player) {
auto@ weapon = jjWeapons[player.currWeapon];
auto style = weapon.style;
if (player.charCurr == CHAR::FROG || player.charCurr == CHAR::BIRD) {
if (player.keySelect) {
if (!selectPressed[player.localPlayerID]) {
selectPressed[player.localPlayerID] = true;
cycleWeapon(player);
}
} else {
selectPressed[player.localPlayerID] = false;
}
}
if (player.charCurr == CHAR::BIRD) {
if (player.keyFire) {
player.keyFire = false;
if (canFire(player) && player.currWeapon != WEAPON::BLASTER) {
int anim = player.curAnim - jjAnimSets[ANIM::BIRD];
if (anim >= 9 && anim != 10 && anim != 19) {
if (anim != 9)
player.keyUp = true;
player.fireBullet();
processFiring(player);
if (getRealAmmo(player, WEAPON::CURRENT) == 0 && !weapon.infinite)
cycleWeapon(player);
}
}
} else {
processNotFiring(player);
}
if (player.keyJump) {
player.keyFire = true;
player.keyJump = false;
}
}
}
void onPlayer(jjPLAYER@ player) {
if (player.xSpeed > 6.f)
player.xSpeed = 6.f;
if (player.xSpeed < -6.f)
player.xSpeed = -6.f;
if (player.charCurr == CHAR::FROG) {
int anim = player.curAnim - jjAnimSets[ANIM::FROG] + (jjIsTSF ? 0 : 1);
if (anim >= 8 && anim <= 10 && player.frameID == 6) {
if (!tongueUsed[player.localPlayerID]) {
tongueUsed[player.localPlayerID] = true;
if (player.currWeapon != WEAPON::BLASTER) {
if (getRealAmmo(player, WEAPON::CURRENT) > 0) {
decrementRealAmmo(player, WEAPON::CURRENT);
int angle = anim == 10 ? 2 : player.direction < 0 ? anim - 5 : 9 - anim;
float x = player.xPos + jjCos(angle << 7) * 76.f + (player.direction < 0 ? 4.f : -4.f);
float y = player.yPos - jjSin(angle << 7) * 76.f + 8.f;
jjSTREAM packet;
packet.push(uint8(player.playerID));
packet.push(uint8(player.currWeapon));
packet.push(bool(player.powerup[WEAPON::CURRENT]));
packet.push(uint(player.ammo[WEAPON::CURRENT]));
packet.push(uint8(angle));
packet.push(float(x));
packet.push(float(y));
jjSendPacket(packet);
fireBullet(player, angle, x, y);
}
if (getRealAmmo(player, WEAPON::CURRENT) == 0 && !jjWeapons[player.currWeapon].infinite)
cycleWeapon(player);
}
}
} else {
tongueUsed[player.localPlayerID] = false;
}
} else if (player.charCurr != CHAR::BIRD) {
player.morphTo(CHAR::FROG);
}
}
void onReceive(jjSTREAM &in packet, int clientID) {
jjSTREAM backup = packet;
uint8 playerID, weapon, angle;
uint ammo;
bool powerup;
float x, y;
if (!packet.pop(playerID) || !packet.pop(weapon) || !packet.pop(powerup) || !packet.pop(ammo) || !packet.pop(angle) || !packet.pop(x) || !packet.pop(y))
return;
if (playerID >= 32 || weapon <= 1 || weapon >= 10 || angle >= 5)
return;
auto@ player = jjPlayers[playerID];
if (jjIsServer && player.clientID != clientID || player.isLocal)
return;
if (jjIsServer)
jjSendPacket(backup, -clientID);
player.currWeapon = weapon;
player.powerup[weapon] = powerup;
player.ammo[weapon] = ammo;
fireBullet(player, angle, x, y);
}
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.