Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Holiday Hare '18 | SmokeNC | Single player | 8.9 |
#pragma require "HH18E1.j2a"
#pragma require "SExmas.j2a"
#pragma require "hh17enemies.asc"
#include "HH18Smoke.asc"
#include "hh17enemies.asc"
#include "HH18savegems.asc"
/*** Copypasted and adapted by Slaz, scripted visuals by Violet CLM, xmas sprites by Sir Ementaler and Smoke ***/
/*** Feel free to use/edit this script like I did :P ***/
class Imitation : jjBEHAVIORINTERFACE {
private uint8 eventID;
private jjBEHAVIOR behavior;
Imitation(uint8 realEventID, uint8 fakeEventID) {
jjOBJ@ obj = jjObjectPresets[realEventID];
eventID = obj.eventID;
behavior = obj.behavior;
obj.eventID = fakeEventID;
obj.behavior = this;
}
void onBehave(jjOBJ@ obj) override {
if (obj.state == STATE::DEACTIVATE)
obj.eventID = eventID;
obj.behave(behavior);
}
}
class GiftBox : jjBEHAVIORINTERFACE {
void destroy(jjOBJ@ obj) {
jjSample(obj.xPos, obj.yPos, SOUND::COMMON_WOOD1);
{
int id = jjAddObject(OBJECT::EXPLOSION, obj.xPos, obj.yPos);
if (id != 0) {
jjOBJ@ other = jjObjects[id];
other.determineCurAnim(ANIM::PICKUPS, 4);
}
}
for (int i = jjRandom() & 7 | 8; i-- != 0;) {
int id = jjAddObject(OBJECT::SHARD, obj.xPos, obj.yPos);
if (id != 0) {
jjOBJ@ other = jjObjects[id];
other.determineCurAnim(ANIM::PICKUPS, 93 + (jjRandom() & 1));
}
}
obj.yPos -= 8.f;
for (int i = obj.var[1]; i-- != 0;) {
int id = jjAddObject(obj.var[0], obj.xPos, obj.yPos);
if (id != 0) {
jjOBJ@ other = jjObjects[id];
if (other.playerHandling == HANDLING::PICKUP) {
int angle = (jjRandom() & 255) + 128;
other.xSpeed = jjCos(angle) * 5.f;
other.ySpeed = jjSin(angle) * -3.f;
} else if (other.playerHandling == HANDLING::SPECIAL) {
other.deactivates = false;
}
}
}
obj.clearPlatform();
obj.delete();
}
void onBehave(jjOBJ@ obj) override {
switch (obj.state) {
case STATE::START:
{
uint16 x = int(obj.xOrg) >>> 5;
uint16 y = int(obj.yOrg) >>> 5;
obj.var[0] = jjParameterGet(x, y, 0, 8);
obj.var[1] = jjParameterGet(x, y, 8, 4);
obj.curAnim += jjParameterGet(x, y, 12, 2);
obj.determineCurFrame();
obj.bulletHandling = HANDLING::DESTROYBULLET;
obj.scriptedCollisions = true;
}
break;
case STATE::FALL:
obj.var[2] = 1;
break;
case STATE::FREEZE:
case STATE::SLEEP:
if (obj.var[2] != 0) {
destroy(obj);
return;
}
}
obj.behave(BEHAVIOR::MONITOR);
}
bool onObjectHit(jjOBJ@, jjOBJ@, jjPLAYER@, int) {
return true;
}
bool onIsSolid(jjOBJ@) {
return true;
}
}
const uint16 LollipopTileID = 390;
array<uint16> tilesToTurnIntoSprites = {
585,625,
604,605,606,607,608,
LollipopTileID
};
class Sprite {
Sprite(){}
float x, y;
uint age;
uint color;
Sprite(float xx, float yy, uint a, uint c = 0) {
x = xx; y = yy; age = a; color = c;
}
}
uint firstSingleTileFrameID, firstMultiTileFrameID, firstCandyCaneFrameID;
const uint levelWidth = jjLayerWidth[4];
const uint levelHeight = jjLayerHeight[4];
array<Sprite> Lollipops, Spazzes, Jacks, CandyCanes;
array<array<Sprite>> Lights(2);
void onLevelLoad() {
gem::restorePlayerGems();
jjUseLayer8Speeds = true;
jjTexturedBGTexture = TEXTURE::XARGON;
SMOKE::PENGUINATOR(OBJECT::LIZARD, 1+jjDifficulty);
SMOKE::SANTAGHOST(OBJECT::FATCHICK, 2+jjDifficulty);
SMOKE::SNOWMAN(OBJECT::STANDMONKEY, 0, 5, 6, 20, 100, 256, 1+jjDifficulty);
SMOKE::FROZENALIEN(OBJECT::LABRAT, 2+jjDifficulty);
SMOKE::FROZENSHADE(OBJECT::HELMUT, 1+jjDifficulty);
HH17::setEnemy(OBJECT::DOGGYDOGG);
HH17::setEnemy(OBJECT::TUFTURT);
HH17::setEnemy(OBJECT::BAT);
HH17::setEnemy(OBJECT::FLOATSUCKER);
Imitation(OBJECT::TACO, OBJECT::MILK);
uint src = jjAnimSets[ANIM::CUSTOM[255]].load(0, "SExmas.j2a");
uint dest = jjAnimSets[ANIM::PICKUPS];
for (int i = 0; i < 95; i++) {
const jjANIMATION@ anim = jjAnimations[src + i];
if (anim.frameCount != 0)
jjAnimations[dest + i] = anim;
}
jjAnimSets[ANIM::BRIDGE].load(1, "SExmas.j2a");
jjAnimSets[ANIM::CUSTOM[0]].load(2, "SExmas.j2a");
jjAnimSets[ANIM::SPIKEPLAT].load(4, "SExmas.j2a");
jjObjectPresets[OBJECT::BOMBCRATE].behavior = GiftBox();
jjObjectPresets[OBJECT::BOMBCRATE].determineCurAnim(ANIM::CUSTOM[0], 0);
jjObjectPresets[OBJECT::SPIKEPLATFORM].killAnim = jjObjectPresets[OBJECT::SPIKEPLATFORM].determineCurAnim(ANIM::SPIKEPLAT, 0) + 1;
array<jjLAYER@> layerOrder = {jjLayers[1], jjLayers[2], jjLayers[3], jjLayers[4], jjLayers[5], jjLayers[6]};
for (uint i = 0; i < 5*2; ++i) {
jjLAYER rocksInChocolate(4, 1);
rocksInChocolate.tileWidth = true;
rocksInChocolate.ySpeed = 0.24 - i * 0.003;
rocksInChocolate.xSpeed = 0.7 - i * 0.04;
rocksInChocolate.xOffset = jjRandom();
rocksInChocolate.yOffset = -666 + int(i*20);
rocksInChocolate.generateSettableTileArea();
for (uint x = 0; x < 4; ++x)
rocksInChocolate.tileSet(x, 0, 680 + 8 - (i & ~1) + (x & 1));
layerOrder.insertLast(@rocksInChocolate);
}
{
jjLAYER bigTrees(4, 8), smallTrees(4, 5);
bigTrees.tileWidth = smallTrees.tileWidth = true;
bigTrees.limitVisibleRegion = smallTrees.limitVisibleRegion = true;
bigTrees.yOffset = -180; smallTrees.yOffset = -300;
bigTrees.generateSettableTileArea();
smallTrees.generateSettableTileArea();
for (uint x = 0; x < 4; ++x) {
for (int y = 0; y < bigTrees.height; ++y) {
if (y < 3) { if (!(y == 0 && x > 1))
bigTrees.tileSet(x, y, 578 + (x & 1) + (y - x/2) * 10);
} else
bigTrees.tileSet(x, y, 598 + (x & 1));
}
for (int y = 0; y < smallTrees.height; ++y) {
if (y < 2)
smallTrees.tileSet(x, y, 576 + (x & 1) + (y * 10));
else
smallTrees.tileSet(x, y, 586);
}
}
for (uint i = 0; i < 8; ++i) {
jjLAYER trees(i < 5 ? bigTrees : smallTrees);
trees.ySpeed = 0.13 - i * 0.02;
trees.xSpeed = 0.3 - i * 0.024;
trees.xOffset = jjRandom();
trees.yOffset += (i < 5) ? int(i*60) : (210 + int(i*30));
layerOrder.insertLast(@trees);
}
}
layerOrder.insertLast(jjLayers[7]);
jjLAYER secondBackgroundMountains(jjLayers[7]);
secondBackgroundMountains.yOffset = 64;
secondBackgroundMountains.ySpeed *= 0.85;;
secondBackgroundMountains.xSpeed *= 0.7;
layerOrder.insertLast(@secondBackgroundMountains);
layerOrder.insertLast(jjLayers[8]);
jjLayerOrderSet(layerOrder);
firstSingleTileFrameID = jjAnimations[jjAnimSets[ANIM::CUSTOM[0]].allocate(array<uint> = {tilesToTurnIntoSprites.length, 2, 4})];
firstMultiTileFrameID = firstSingleTileFrameID + tilesToTurnIntoSprites.length;
firstCandyCaneFrameID = firstMultiTileFrameID + 2;
jjANIMFRAME@ frame;
for (uint i = 0; i < tilesToTurnIntoSprites.length; ++i) {
@frame = jjAnimFrames[firstSingleTileFrameID + i];
jjPIXELMAP(tilesToTurnIntoSprites[i]).save(frame);
frame.hotSpotX = frame.hotSpotY = -16;
}
jjObjectPresets[OBJECT::CHOCBAR].curFrame = jjAnimations[jjObjectPresets[OBJECT::CHOCBAR].curAnim].firstFrame = firstSingleTileFrameID;
jjObjectPresets[OBJECT::ICECREAM].curFrame = jjAnimations[jjObjectPresets[OBJECT::ICECREAM].curAnim].firstFrame = firstSingleTileFrameID + 1;
@frame = jjAnimFrames[firstMultiTileFrameID];
jjPIXELMAP(32, 0, 128,128).save(frame);
frame.hotSpotX = frame.hotSpotY = 0;
@frame = jjAnimFrames[firstMultiTileFrameID + 1];
jjPIXELMAP(160, 0, 64,96).save(frame);
frame.hotSpotX = 0; frame.hotSpotY = -64;
for (uint i = 0; i < 4; ++i) {
@frame = jjAnimFrames[firstCandyCaneFrameID + i];
jjPIXELMAP(7*32, i * 20, 12, 96 - i*20).save(frame);
frame.hotSpotX = -6; frame.hotSpotY = 0;
}
for (uint x = 0; x < levelWidth; ++x) {
for (uint y = 0; y < levelHeight; ++y) {
const uint16 tileID1 = jjTileGet(4, x, y), tileID2 = jjTileGet(5, x, y);
if (tileID1 == LollipopTileID || tileID2 == LollipopTileID)
Lollipops.insertLast(Sprite(x * 32 + 16, y * 32 + 16, jjRandom()));
else if (tileID1 == 301)
Spazzes.insertLast(Sprite((x - 1) * 32, y * 32, 0));
else if (tileID1 >= 340 && tileID1 <= 343)
jjTileSet(4, x,y, 56);
else if (tileID1 >= 395 && tileID1 <= 398)
jjTileSet(4, x,y, 5);
else if (tileID1 == 334 || tileID1 == 335) {
jjTileSet(4, x,y, tileID1 - 30);
if (tileID1 == 334)
Jacks.insertLast(Sprite(x * 32, y * 32, jjRandom()));
}
if (jjEventGet(x, y) == 255)
CandyCanes.insertLast(Sprite(x * 32 + 16, y * 32 + 16, jjRandom(), 3 - jjParameterGet(x, y, 0, 2)));
}
}
const uint16 firstTreeTileID = 592;
array<jjPIXELMAP@> foregroundTreeTileImages(679 - firstTreeTileID + 1, null);
for (uint i = 0; i < 2; ++i) {
const jjLAYER@ layer = jjLayers[1 + i];
for (int x = layer.width - 1; x >= 0; --x)
for (int y = layer.height - 1; y >= 0; --y) {
const uint16 tileID = layer.tileGet(x, y);
if (tileID >= firstTreeTileID) {
const uint16 adjustedTileID = tileID - firstTreeTileID;
if (foregroundTreeTileImages[adjustedTileID] is null)
@foregroundTreeTileImages[adjustedTileID] = jjPIXELMAP(tileID);
const jjPIXELMAP@ tileImage = foregroundTreeTileImages[adjustedTileID];
uint8 xx, yy;
while (tileImage[xx = jjRandom() & 31, yy = jjRandom() & 31] == 0);
Lights[i].insertLast(Sprite(x * 32 + xx, y * 32 + yy, jjRandom(), jjRandom() % 5));
}
}
}
}
void onDrawLayer4(jjPLAYER@ play, jjCANVAS@ screen) {
for (uint i = 0; i < Lollipops.length; ++i) {
const Sprite@ sprite = Lollipops[i];
screen.drawRotatedSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstSingleTileFrameID + 7, sprite.age - (jjGameTicks << 4));
}
for (uint i = 0; i < Spazzes.length; ++i) {
const Sprite@ sprite = Spazzes[i];
screen.drawSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstMultiTileFrameID, 1, SPRITE::SHADOW);
}
for (uint i = 0; i < CandyCanes.length; ++i) {
const Sprite@ sprite = CandyCanes[i];
screen.drawSwingingVineSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstCandyCaneFrameID + sprite.color, 96 - sprite.color*20, int(jjSin(sprite.age + jjGameTicks * 6) * 0x4000));
}
}
void onDrawLayer5(jjPLAYER@, jjCANVAS@ screen) {
for (uint i = 0; i < Jacks.length; ++i) {
const Sprite@ sprite = Jacks[i];
screen.drawRotatedSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstMultiTileFrameID + 1, int(jjSin(jjGameTicks << 2) * 28));
}
}
void drawLights(uint id, jjCANVAS@ screen) {
const array<Sprite>@ lights = @Lights[id];
for (uint i = 0; i < lights.length; ++i) {
const Sprite@ sprite = lights[i];
screen.drawSpriteFromCurFrame(int(sprite.x), int(sprite.y), firstSingleTileFrameID + 2 + sprite.color, 1, SPRITE::BRIGHTNESS, 128 + int(jjSin(sprite.age + (jjGameTicks << 3)) * 40));
}
}
void onDrawLayer1(jjPLAYER@, jjCANVAS@ screen) { drawLights(0, screen); }
void onDrawLayer2(jjPLAYER@, jjCANVAS@ screen) { drawLights(1, screen); }
void onPlayer(jjPLAYER@ play) {
jjPARTICLE@ part = jjAddParticle(PARTICLE::ICETRAIL);
if (part !is null) {
part.icetrail.colorDelta = -1;
part.xPos = play.cameraX + (jjRandom() % jjSubscreenWidth);
part.yPos = play.cameraY;
}
gem::trackPlayerGems(play);
gem::upgradeHealth(play);
}
bool onDrawLives(jjPLAYER@ play, jjCANVAS@ canvas) { return true; }
void onLevelReload() {
HH17::processEnemyColors();
gem::restorePlayerGems();
}
void onMain() {
gem::deleteCollectedGems();
}
void onFunction0(jjPLAYER@ play) {
gem::saveGemData();
jjNxt(false, false);
}
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.