Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Mystery of the Four... | chandie | Single player | 6.6 | |||||
Multi-Layer Level Editor... | Violet CLM | Utility | 9.6 |
#include "MLLE-Weapons.asc"
namespace DefaultWeapons {
class Blaster : MLLEWeapons::WeaponInterface {
Blaster() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 6,
xAcc: 0.125,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 17,
lightType: LIGHT::POINT2,
counterEnd: 35
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 7,
xAcc: 0.1875,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 20,
lightType: LIGHT::POINT,
counterEnd: 30
),
pickupAnimation: jjAnimSets[ANIM::PICKUPS] + 29,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 18,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 60,
behavior: function(obj, powerup) {
obj.behavior = BEHAVIOR::BULLET;
if (obj.eventID == OBJECT::ICEBULLET) obj.eventID = OBJECT::BLASTERBULLET;
DefaultSample(obj, WEAPON::BLASTER);
},
onDrawAmmo: function(player, canvas, ignore) { //character-specific animations:
if (player !is null && !player.noFire && player.charCurr != CHAR::FROG && player.charCurr != CHAR::BIRD) {
const uint number = player.currWeapon;
const bool powerup = player.powerup[WEAPON::CURRENT];
const CHAR::Char charCurr = player.charCurr != CHAR::BIRD2 ? player.charCurr : player.charOrig;
const ::jjANIMATION@ anim = jjAnimations[
charCurr == CHAR::SPAZ ? (powerup ? (::jjAnimSets[ANIM::AMMO] + 19) : (::jjAnimSets[ANIM::PICKUPS] + 30)) :
(::jjIsTSF && charCurr == CHAR::LORI) ? (powerup ? (::jjAnimSets[ANIM::PLUS_AMMO] + 6) : (::jjAnimSets[ANIM::PLUS_AMMO] + 5)) :
(powerup ? (::jjAnimSets[ANIM::AMMO] + 18) : (::jjAnimSets[ANIM::PICKUPS] + 29))
];
int x, y;
STRING::Size font;
::string text;
if (::jjSubscreenWidth > 400) {
x = ::jjSubscreenWidth - 88;
y = ::jjSubscreenHeight - 14;
font = STRING::MEDIUM;
} else {
x = ::jjSubscreenWidth - 48;
y = ::jjSubscreenHeight - 9;
font = STRING::SMALL;
}
canvas.drawSpriteFromCurFrame(x, y, anim + (::jjGameTicks >> 2) % anim.frameCount);
const ::jjWEAPON@ weapon = ::jjWeapons[number];
if (weapon.infinite || weapon.replacedByShield && player.shieldTime > 0) {
text = "x^";
} else {
const int ammo = player.ammo[number];
text = "x" + (ammo > 0 ? ammo : 0);
}
canvas.drawString(x + 8, y, text, font);
}
return true;
}
);
}
}
class Bouncer : MLLEWeapons::WeaponInterface {
bool ReverseBehaviors = false;
bool BounceThroughWalls = true;
Bouncer() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 5,
ySpeed: 1,
xAcc: 0.25,
yAcc: 0.0915527344f,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 4,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 23,
lightType: LIGHT::POINT2,
counterEnd: (70*3)/2
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 5,
ySpeed: 1,
xAcc: 0.25,
yAcc: 0.0915527344f,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 4,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 26,
lightType: LIGHT::POINT2,
counterEnd: (70*3)/2
),
pickupAnimation: jjAnimSets[ANIM::AMMO] + 25,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 24,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 61,
ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 54,
traits: se::weapon_default_traits | se::weapon_goes_through_thin_walls,
behavior: MLLEWeapons::behaviorFunction(DetermineBehavior),
apply: MLLEWeapons::applyFunction(DetermineReversedness)
);
}
void DetermineBehavior(jjOBJ@ obj, bool powerup) const {
DefaultSample(obj, WEAPON::BOUNCER);
if (BounceThroughWalls)
obj.behavior = (powerup != ReverseBehaviors) ? BEHAVIOR::BOUNCERBULLETPU : BEHAVIOR::BOUNCERBULLET;
else
obj.behavior = (powerup != ReverseBehaviors) ? BouncerPUNoWallWrapper : BouncerNoWallWrapper;
}
bool DetermineReversedness(uint, se::WeaponHook@, jjSTREAM@ parameter) {
if (parameter !is null && parameter.getSize() >= 2) {
parameter.pop(ReverseBehaviors);
parameter.pop(BounceThroughWalls);
}
return true;
}
}
void BouncerNoWallWrapper(jjOBJ@ obj) {
const bool right = obj.xSpeed >= 0;
obj.behave(BEHAVIOR::BOUNCERBULLET);
if (right != (obj.xSpeed >= 0))
obj.var[7] = -obj.var[7];
}
void BouncerPUNoWallWrapper(jjOBJ@ obj) {
const bool right = obj.xSpeed >= 0;
obj.behave(BEHAVIOR::BOUNCERBULLETPU);
if (right != (obj.xSpeed >= 0))
obj.var[7] = -obj.var[7];
}
class Ice : MLLEWeapons::WeaponInterface {
bool FiringUnfreezesFaster = true;
Ice() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 6,
xAcc: 0.125,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 82,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 27,
lightType: LIGHT::POINT2,
counterEnd: 35,
freeze: 200
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 7,
xAcc: 0.1875,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 82,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 30,
special: jjAnimSets[ANIM::AMMO].firstAnim + 32,
lightType: LIGHT::POINT2,
counterEnd: 30,
freeze: 254
),
spread: SPREAD::ICE,
traits: se::weapon_is_effective_against_all_targets | se::weapon_supports_mouse_aim | se::weapon_works_in_all_modes | se::weapon_has_all_pickups | se::weapon_inflicts_status_condition | se::weapon_freezes_objects | se::weapon_melts_ice,
pickupAnimation: jjAnimSets[ANIM::AMMO] + 29,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 28,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 62,
ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 55,
onPlayerInput: se::PlayerCallback(playerInput),
apply: MLLEWeapons::applyFunction(DetermineUnfreezing),
behavior: function(obj, powerup) {
DefaultSample(obj, WEAPON::ICE);
if (powerup) {
if (obj.xSpeed == 0 || obj.ySpeed == 0) {
obj.behavior = BEHAVIOR::ICEBULLETPU;
obj.eventID = OBJECT::ICEBULLETPU;
} else {
obj.behavior = BEHAVIOR::BULLET;
if (powerup) obj.curAnim = jjAnimSets[ANIM::AMMO].firstAnim + 30;
}
if (obj.xSpeed != 0) obj.counterEnd = 30;
obj.var[0] = AlternatingPoweredUpIce ^= 512;
} else {
obj.behavior = BEHAVIOR::BULLET;
obj.eventID = OBJECT::ICEBULLET;
}
}
);
}
uint getMaxDamage(bool powerup) const override { return 0; }
bool DetermineUnfreezing(uint, se::WeaponHook@, jjSTREAM@ parameter) {
if (parameter !is null && !parameter.isEmpty())
parameter.pop(FiringUnfreezesFaster);
return true;
}
void playerInput(jjPLAYER@ play, int) {
if (!FiringUnfreezesFaster && play.frozen != 0)
play.keyFire = false;
}
}
int AlternatingPoweredUpIce = 0;
class Seeker : MLLEWeapons::WeaponInterface {
Seeker() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 2,
xAcc: 0.25,
yAcc: 0.00390625f,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 5,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 37,
lightType: LIGHT::POINT2,
counterEnd: 140
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 1.5,
xAcc: 0.25,
yAcc: 0.00390625f,
animSpeed: 3,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 5,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 42,
lightType: LIGHT::POINT2,
counterEnd: 140
),
style: WEAPON::MISSILE,
pickupAnimation: jjAnimSets[ANIM::AMMO] + 34,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 33,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 63,
ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 56,
behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::SEEKERBULLET; DefaultSample(obj, WEAPON::SEEKER); }
);
}
}
class RFs : MLLEWeapons::WeaponInterface {
RFs() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 1,
xAcc: 0.1875,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 3,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 45,
lightType: LIGHT::POINT2,
counterEnd: 40
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 1.5,
xAcc: 0.1875,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 3,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 50,
lightType: LIGHT::POINT2,
counterEnd: 35
),
isRFMissile: true,
spread: SPREAD::RF,
style: WEAPON::MISSILE,
pickupAnimation: jjAnimSets[ANIM::AMMO] + 49,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 48,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 64,
ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 57,
traits: se::weapon_default_traits | se::weapon_causes_splash_damage | se::weapon_increases_mobility,
behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::RFBULLET; DefaultSample(obj, WEAPON::RF); }
);
}
}
class Toaster : MLLEWeapons::WeaponInterface {
Toaster() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 1,
xAcc: 0.125,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 55,
var: array<int> = {0,0,0,0,0,0,2},
counterEnd: 35
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 1,
xAcc: 0.125,
animSpeed: 2,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 58,
var: array<int> = {0,0,0,0,0,0,2},
counterEnd: 35
),
spread: SPREAD::TOASTER,
style: WEAPON::POPCORN,
pickupAnimation: jjAnimSets[ANIM::AMMO] + 57,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 56,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 65,
ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 58,
replacedByBubbles: true,
multiplier: 32,
traits: se::weapon_default_traits | se::weapon_melts_ice | se::weapon_fails_underwater,
behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::TOASTERBULLET; if (powerup) obj.eventID = OBJECT::TOASTERBULLETPU; DefaultSample(obj, WEAPON::TOASTER); }
);
}
}
class TNT : MLLEWeapons::WeaponInterface {
bool IncludePowerup = true;
TNT() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
energy: 1,
playerHandling: HANDLING::SPECIAL,
curAnim: jjAnimSets[ANIM::AMMO] + 59,
killAnim: jjAnimSets[ANIM::AMMO] + 77,
lightType: LIGHT::POINT,
counterEnd: 255
),
style: WEAPON::MISSILE,
pickupAnimation: jjAnimSets[ANIM::AMMO] + 59,
ammoCrateAnimation: jjAnimSets[ANIM::PICKUPS] + 59,
traits: se::weapon_default_traits | se::weapon_causes_splash_damage | se::weapon_increases_mobility,
behavior: MLLEWeapons::behaviorFunction(DetermineBehavior),
apply: MLLEWeapons::applyFunction(DeterminePowerup)
);
}
void DetermineBehavior(jjOBJ@ obj, bool powerup) const {
obj.eventID = OBJECT::TNT; //use TNTdamage
if (!IncludePowerup || !powerup || PoweredUpPickupAnimation <= 0)
obj.behavior = BEHAVIOR::TNT;
else {
obj.behavior = TNTPowerupBehavior;
obj.counter = -256; //double lifetime
obj.curAnim = PoweredUpPickupAnimation;
}
}
bool DeterminePowerup(uint, se::WeaponHook@, jjSTREAM@ parameter) {
if (parameter !is null && !parameter.isEmpty())
parameter.pop(IncludePowerup);
return true;
}
uint getMaxDamage(bool powerup) const override { return 1; }
}
void TNTPowerupBehavior(jjOBJ@ obj) {
if (obj.state == STATE::EXPLODE && obj.counter == 0) //beginning of explosion sequence
obj.blast(96*96, true); //hurt nearby players NOW, not just 20 ticks from now after they've already run far away
obj.behave(BEHAVIOR::TNT);
if (obj.light == 17) //just created an explosion object
for (uint objectID = jjObjectCount; --objectID != 0;) {
jjOBJ@ obj2 = jjObjects[objectID];
if (obj2.eventID == OBJECT::EXPLOSION && obj2.curAnim == obj.killAnim && obj2.xPos == obj.xPos && obj2.yPos == obj.yPos) {
obj2.frameID = 4; //skip part where TNT is still visible (using the non-powerup colors)
break;
}
}
}
class Gun8 : MLLEWeapons::WeaponInterface {
Gun8() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 11,
xAcc: 0.125,
animSpeed: 2,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 60,
var: array<int> = {0,0,0,0,0,0,16},
lightType: LIGHT::POINT2,
counterEnd: 45
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 11,
xAcc: 0.25,
animSpeed: 3,
killAnim: jjAnimSets[ANIM::AMMO].firstAnim + 80,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 63,
var: array<int> = {0,0,0,0,0,0,16},
lightType: LIGHT::POINT,
counterEnd: 70
),
spread: SPREAD::NORMAL,
gradualAim: false,
pickupAnimation: jjAnimSets[ANIM::AMMO] + 62,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 61,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 66,
ammoCrateAnimation: jjAnimSets[ANIM::PLUS_COMMON] + 0,
behavior: function(obj, powerup) {
obj.behavior = BEHAVIOR::BULLET;
if (obj.eventID == OBJECT::ICEBULLET)
obj.eventID = OBJECT::FIREBALLBULLET;
DefaultSample(obj, WEAPON::GUN8);
},
apply: MLLEWeapons::applyFunction(DetermineSpread)
);
}
bool DetermineSpread(uint, se::WeaponHook@, jjSTREAM@ parameter) {
if (parameter !is null && !parameter.isEmpty()) {
GradualAim = true;
uint8 pbyte;
parameter.pop(pbyte);
if (pbyte == 0)
Spread = SPREAD::GUN8;
else if (pbyte == 1)
Spread = SPREAD::PEPPERSPRAY;
else if (pbyte >= 2) {
Spread = SPREAD::NORMAL;
if (pbyte == 2)
GradualAim = false;
}
}
return true;
}
}
class ElectroBlaster : MLLEWeapons::WeaponInterface {
ElectroBlaster() {
super(
regularObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 4,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 75,
frameID: 4,
var: array<int> = {0,40,0,0,0,0,2},
lightType: LIGHT::POINT2,
counterEnd: 35
),
powerupObjectTemplate: MLLEWeapons::ObjectTemplate(
xSpeed: 4,
animSpeed: 3,
curAnim: jjAnimSets[ANIM::AMMO].firstAnim + 75,
frameID: 4,
var: array<int> = {0,32,0,0,0,0,2},
lightType: LIGHT::POINT2,
counterEnd: 35
),
pickupAnimation: jjAnimSets[ANIM::AMMO] + 68,
poweredUpPickupAnimation: jjAnimSets[ANIM::AMMO] + 67,
powerupAnimation: jjAnimSets[ANIM::PICKUPS] + 67,
ammoCrateAnimation: jjAnimSets[ANIM::PLUS_COMMON] + 1,
traits: se::weapon_default_traits | se::weapon_goes_through_walls | se::weapon_melts_ice,
behavior: function(obj, powerup) { obj.behavior = BEHAVIOR::ELECTROBULLET; if (powerup) obj.eventID = OBJECT::ELECTROBULLETPU; DefaultSample(obj, WEAPON::GUN9); }
);
}
}
}
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.