Downloads containing HH24_level01.j2as

Downloads
Name Author Game Mode Rating
TSF with JJ2+ Only: Holiday Hare 24Featured Download PurpleJazz Single player 10 Download file

File preview

const bool MLLESetupSuccessful = MLLE::Setup(array<MLLEWeaponApply@> = {null, null, null, null, null, null, null, null, se::FireworkMLLEWrapper()}); ///@MLLE-Generated
#include "MLLE-Include-1.7w.asc" ///@MLLE-Generated
#pragma require "HH24_level01-MLLE-Data-3.j2l" ///@MLLE-Generated
#pragma require "HH24_level01-MLLE-Data-2.j2l" ///@MLLE-Generated
#pragma require "HH24_level01-MLLE-Data-1.j2l" ///@MLLE-Generated
#pragma require "XMas 2 Feaw.j2t" ///@MLLE-Generated
#pragma require "HH24_level01.j2l" ///@MLLE-Generated
#include "SEfirework-mlle.asc" ///@MLLE-Generated
#pragma require "SEfirework-mlle.asc" ///@MLLE-Generated
#pragma require "SEweapon.asc"
#pragma require "SExmas.j2a"
#pragma require "crayonbridge.j2a"
#pragma offer "SEfirework1.wav"
#pragma offer "SEfirework2.wav"
#include "SEweapon.asc"
#include "HH17Enemies_HH24.asc"
#include "HH18Smoke_HH24.asc"
#include "HH24.asc"

shared interface MLLEWeaponApply { bool Apply(uint, se::WeaponHook@ = null, jjSTREAM@ = null, uint8 = 0); }
namespace se {
	class FireworkEditMLLEWrapper : FireworkWeaponEdit, MLLEWeaponApply {
		bool Apply(uint number, se::WeaponHook@ weaponHook = null, jjSTREAM@ = null, uint8 ammo15EventID = 0) {
			if (getAnimSet() is null) {
				uint8 animSetID = 0;
				while (jjAnimSets[ANIM::CUSTOM[animSetID]] != 0)
					++animSetID;
				loadAnims(jjAnimSets[ANIM::CUSTOM[animSetID]]);
			}
			
			if (getSamples()[0] == SOUND::AMMO_GUNVELOCITY) {
				array<SOUND::Sample> samples;
				int sampleID = SOUND::BAT_BATFLY1;
				while (samples.length < getSampleCount()) {
					while (jjSampleIsLoaded(SOUND::Sample(sampleID)))
						++sampleID;
					samples.insertLast(SOUND::Sample(sampleID++));
				}
				loadSamples(samples);
			}
			
			if (ammo15EventID != 0) {
				jjOBJ@ ammo15 = @jjObjectPresets[ammo15EventID];
				ammo15.curAnim = getAnimSet() + 2;
				ammo15.frameID = 0;
				ammo15.determineCurFrame();
			}
			
			return setAsWeapon(number, weaponHook);
		}
	}

shared class FireworkWeaponEdit : WeaponInterface {
	private ::jjANIMSET@ m_animSet;
	private ::array<SOUND::Sample> m_samples = {SOUND::AMMO_GUNVELOCITY, SOUND::COMMON_BASE1};
	protected ::jjANIMSET@ getAnimSet() const {
		return @m_animSet;
	}
	protected const array<SOUND::Sample>& getSamples() const {
		return m_samples;
	}
	protected bool loadAnimSet(::jjANIMSET@ animSet, const ::string &in filename, uint setID) {
		if (animSet !is null && !::jjSTREAM(filename).isEmpty()) {
			@m_animSet = @animSet.load(setID, filename);
			return true;
		}
		return false;
	}
	protected bool loadSample(SOUND::Sample sample, const ::string &in filename, int index) {
		if (::jjSampleLoad(sample, filename)) {
			m_samples[index] = sample;
			return true;
		}
		return false;
	}
	protected void behaveParticle(::jjOBJ@ obj) const {
		switch (obj.state) {
			case STATE::START:
				obj.state = STATE::FALL;
				break;
			case STATE::FALL:
				if (obj.xAcc * obj.xSpeed >= 0.f)
					obj.xSpeed = obj.xAcc = 0.f;
				else
					obj.xPos += obj.xSpeed += obj.xAcc;
				if (obj.yAcc * obj.ySpeed >= 0.f)
					obj.yAcc = 0.f;
				obj.yPos += obj.ySpeed += obj.yAcc + 0.0625f;
				if (::jjMaskedPixel(int(obj.xPos), int(obj.yPos)) || obj.counter++ > int(obj.counterEnd)) {
					obj.counter = obj.counterEnd;
					obj.state = STATE::EXPLODE;
				} else if (obj.playerHandling == HANDLING::PARTICLE && obj.counter << 2 > int(obj.counterEnd)) {
					obj.playerHandling = HANDLING::PLAYERBULLET;
				}
				::jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::ALPHAMAP, obj.var[1]);
				break;
			case STATE::EXPLODE:
				obj.counter -= obj.counterEnd >> 3;
				if (obj.counter > 0) {
					float scale = float(obj.counter) / float(obj.counterEnd);
					::jjDrawResizedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, scale, scale, SPRITE::ALPHAMAP, obj.var[1]);
				} else {
					obj.delete();
				}
				break;
			case STATE::KILL:
			case STATE::DEACTIVATE:
				obj.delete();
				break;
		}
	}
	protected void behave(::jjOBJ@ obj) const {
		switch (obj.state) {
			case STATE::START:
				if (obj.creatorType == CREATOR::PLAYER && ::jjPlayers[obj.creatorID].isLocal)
					::jjSample(obj.xPos, obj.yPos, m_samples[0]);
				obj.counterEnd = ::jjObjectPresets[obj.eventID].counterEnd;
				obj.yAcc = -0.25f;
				obj.xSpeed += obj.var[7] / 2e5f;
				obj.state = STATE::ROCKETFLY;
			case STATE::ROCKETFLY:
				if (obj.xAcc * obj.xSpeed >= 0.f)
					obj.xSpeed = obj.xAcc = 0.f;
				else
					obj.xPos += obj.xSpeed += obj.xAcc;
				if (obj.ySpeed < -9.f) {
					obj.yAcc = 0.f;
					obj.ySpeed = -9.f;
				}
				obj.yPos += obj.ySpeed += obj.yAcc;
				if (::jjMaskedPixel(int(obj.xPos), int(obj.yPos)) && ::jjEventAtLastMaskedPixel != AREA::ONEWAY && ::jjEventAtLastMaskedPixel != AREA::VINE) {
					obj.xPos -= obj.xSpeed;
					obj.yPos -= obj.ySpeed;
					obj.state = STATE::EXTRA;
				} else if (obj.counter++ > int(obj.counterEnd)) {
					obj.state = STATE::EXTRA;
				}
				obj.draw();
				break;
			case STATE::EXTRA:
			case STATE::EXPLODE:
				::jjSample(obj.xPos, obj.yPos, m_samples[1]);
				for (int i = 0; i < 6; i++) {
					::jjSample(obj.xPos + ::jjSin((i << 10) / 6) * 320.f, obj.yPos + ::jjCos((i << 10) / 6) * 320.f, m_samples[1]);
				}
				{
					array<int> colors = {34, 81, 24, 50};
					int particles = 12 + (obj.var[6] >> 1 & 4);
					for (int i = 0; i < particles; i++) {
						int id = ::jjAddObject(obj.eventID, obj.xPos, obj.yPos, obj.creatorID, obj.creatorType, @::jjVOIDFUNCOBJ(behaveParticle));
						if (id > 0) {
							::jjOBJ@ other = @::jjObjects[id];
							other.animSpeed >>= 1;
							other.counterEnd -= 10;
							other.curAnim = obj.killAnim;
							other.determineCurFrame();
							other.var[1] = colors[obj.var[6] >> 2 & 2 | i & 1];
							other.xSpeed = ::jjSin((i << 10) / particles) * 6.f;
							other.ySpeed = ::jjCos((i << 10) / particles) * 6.f;
							other.xAcc = other.xSpeed / -64.f;
							other.yAcc = other.ySpeed / -64.f;
							if (obj.state == STATE::EXPLODE)
								other.playerHandling = HANDLING::PARTICLE;
						}
					}
				}
				obj.draw();
			case STATE::KILL:
			case STATE::DEACTIVATE:
				obj.delete();
				break;
		}
	}
	protected void behaveTNT(::jjOBJ@ obj) const {
		if (obj.creatorType == CREATOR::PLAYER && ::jjPlayers[obj.creatorID].powerup[WEAPON::TNT]) {
			obj.animSpeed = 4;
			obj.curFrame = ::jjAnimations[obj.curAnim = obj.special = m_animSet + 4];
			obj.var[6] = 0;
		} else {
			obj.animSpeed = 2;
			obj.curFrame = ::jjAnimations[obj.curAnim = obj.special = m_animSet + 5];
			obj.var[6] = 8;
		}
		obj.behavior = @::jjVOIDFUNCOBJ(behave);
		obj.behave();
	}
	protected void prepareWeaponProfile(::jjWEAPON@ weapon) const {
		weapon.defaultSample = false;
		weapon.gradualAim = false;
		weapon.multiplier = 1;
		weapon.replacedByBubbles = false;
		weapon.spread = SPREAD::NORMAL;
		weapon.style = WEAPON::MISSILE;
	}
	protected void prepareBulletPresets(::jjOBJ@ basic, ::jjOBJ@ powerup, uint number) const {
		if (basic is powerup)
			basic.behavior = @::jjVOIDFUNCOBJ(behaveTNT);
		else
			basic.behavior = powerup.behavior = @::jjVOIDFUNCOBJ(behave);
		basic.animSpeed = 2;
		powerup.animSpeed = 4;
		basic.counterEnd = powerup.counterEnd = 70;
		basic.curFrame = ::jjAnimations[basic.curAnim = basic.special = m_animSet + 4];
		powerup.curFrame = ::jjAnimations[powerup.curAnim = powerup.special = m_animSet + 5];
		basic.direction = powerup.direction = 0;
		basic.energy = powerup.energy = basic.freeze = powerup.freeze = 0;
		basic.frameID = powerup.frameID = 0;
		basic.killAnim = powerup.killAnim = m_animSet + 6;
		basic.lightType = powerup.lightType = LIGHT::POINT;
		basic.playerHandling = powerup.playerHandling = HANDLING::PLAYERBULLET;
		basic.var[3] = powerup.var[3] = number;
		basic.var[6] = 0;
		powerup.var[6] = 8;
		basic.xAcc = powerup.xAcc = -0.125f;
		basic.yAcc = powerup.yAcc = 0.f;
		basic.xSpeed = powerup.xSpeed = 3.f;
		basic.ySpeed = powerup.ySpeed = 0.f;
	}
	protected void preparePickupPresets(::jjOBJ@ ammo3, ::jjOBJ@ ammo15, ::jjOBJ@ powerup) const {
		if (ammo3 !is null) {
			ammo3.behavior = @AmmoPickup(::jjAnimations[m_animSet], ::jjAnimations[m_animSet + 1]);
			ammo3.curAnim = m_animSet;
			ammo3.frameID = 0;
			ammo3.determineCurFrame();
		}
		if (ammo15 !is null) {
			ammo15.curAnim = m_animSet + 2;
			ammo15.frameID = 0;
			ammo15.determineCurFrame();
		}
		if (powerup !is null) {
			powerup.curAnim = m_animSet + 3;
			powerup.frameID = 0;
			powerup.determineCurFrame();
		}
	}
	::jjANIMSET@ loadAnims(::jjANIMSET@ animSet) override {
		loadAnimSet(animSet, "SEfirework.j2a", 0);
		return @animSet;
	}
	::array<bool>@ loadSamples(const ::array<SOUND::Sample>& samples) override {
		if (samples.length() != 2)
			return @::array<bool>(2, false);
		::array<bool> result = {loadSample(samples[0], "SEfirework1.wav", 0), loadSample(samples[1], "SEfirework2.wav", 1)};
		return @result;
	}
	uint getSampleCount() const override {
		return 2;
	}
	uint getTraits(bool) const override {
		return weapon_default_traits;
	}
	uint getMaxDamage(bool powerup) const override {
		return powerup ? 2 : 1;
	}
	bool setAsWeapon(uint number, WeaponHook@ weaponHook = null) override {
		if (m_animSet !is null && isValidWeapon(number)) {
			uint basic = getBasicBulletOfWeapon(number);
			uint powered = getPoweredBulletOfWeapon(number);
			uint ammo3 = getAmmoPickupOfWeapon(number);
			uint ammo15 = getAmmoCrateOfWeapon(number);
			uint powerup = getPowerupMonitorOfWeapon(number);
			if (weaponHook !is null) {
				weaponHook.resetCallbacks(number);
				weaponHook.setWeaponSprite(number, false, ::jjAnimations[m_animSet]);
				weaponHook.setWeaponSprite(number, true, ::jjAnimations[m_animSet + 1]);
			}
			prepareWeaponProfile(@::jjWeapons[number]);
			prepareBulletPresets(@::jjObjectPresets[basic], @::jjObjectPresets[powered], number);
			preparePickupPresets(ammo3 != 0 ? @::jjObjectPresets[ammo3] : null, ammo15 != 0 ? @::jjObjectPresets[ammo15] : null, @::jjObjectPresets[powerup]);
			return true;
		}
		return false;
	}
}
FireworkWeaponEdit fireworkEdit;
}


array<bool> SavedTriggers(32, false);

void CheckpointWrapper(jjOBJ@ obj) {
  if (obj.state == STATE::STOP) { //don't do anything anymore
    jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame);
  } else if (obj.state == STATE::DEACTIVATE) { //due to death
    obj.deactivate();
  } else {
    obj.behave(BEHAVIOR::CHECKPOINT);
    if (obj.state == STATE::DONE) { //triggered by the player hitting it
      obj.state = STATE::STOP;
      //save the current state of some properties
      for (uint i = 0; i < 32; ++i)
        SavedTriggers[i] = jjTriggers[i];
    }
  }
}

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;
	}
}
	
void onLevelLoad() {
	SMOKE::SANTAGHOST(OBJECT::FATCHICK, 1 + jjDifficulty);
	HH17::setEnemy(OBJECT::DRAGON);
	
	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;
	}
	
	src = jjAnimSets[ANIM::CUSTOM[254]].load(0, "HH24.j2a");
    
    jjAnimations[dest + 11] = jjAnimations[src + 2]; // Burger -> Gingerbread Man
    jjAnimations[dest + 15] = jjAnimations[src + 4]; // Cheese -> Peppermint
    jjAnimations[dest + 32] = jjAnimations[src + 1]; // Fries -> Candy Cane (Red)
    jjAnimations[dest + 77] = jjAnimations[src]; // Pizza -> Candy Cane (Green)
    jjAnimations[dest + 88] = jjAnimations[src + 3]; // Taco -> Hot Cocoa
	
    jjAnimSets[ANIM::TUFTUR].load(1, "HH24.j2a");
    jjObjectPresets[OBJECT::TUFTURT].determineCurAnim(ANIM::TUFTUR, 0);
	
	//jjObjectPresets[OBJECT::ELECTROBULLET].behavior = se::FireworkWeapon.behave;
	se::FireworkEditMLLEWrapper fireworkEditMLLEWrapper;
	fireworkEditMLLEWrapper.Apply(9);
	
	jjAnimSets[ANIM::CUSTOM[0]].load(2, "SExmas.j2a");
	jjObjectPresets[OBJECT::BOMBCRATE].behavior = GiftBox();
	jjObjectPresets[OBJECT::BOMBCRATE].determineCurAnim(ANIM::CUSTOM[0], 0);
	
	jjAnimSets[ANIM::BRIDGE].load(0, "crayonbridge.j2a");
	
	jjObjectPresets[OBJECT::SAVEPOST].behavior = CheckpointWrapper;
    jjObjectPresets[OBJECT::SAVEPOST].deactivates = false;
	
	HH24::gem::loadSettings();
	jjLocalPlayers[0].lives++;
	
	HH17::setEnemy(OBJECT::BAT);
	
	jjObjectPresets[OBJECT::TRIGGERCRATE].behavior = Crate();
}

class Crate : jjBEHAVIORINTERFACE {
	void onBehave(jjOBJ@ obj) {
		obj.behave(BEHAVIOR::CRATE, true);
		
		if (obj.state == STATE::KILL) {
			for (uint i = 0; i < 32; ++i) {
				SavedTriggers[i] = jjTriggers[i];
			}
			jjEventSet(uint(obj.xOrg) >> 5, uint(obj.yOrg) >> 5, 0);
		}
	}
}

void onLevelBegin() {
	MLLE::SpawnOffgrids();
	jjTexturedBGFadePositionY = 0.43;
}

void onMain() {
	HH17::handleEnemyProjectiles();
	
	jjDrawSprite(207*32 + 8, 121*32 + 6, ANIM::FLAG, 1, 0, 0, SPRITE::NORMAL, 0, 5);
	jjDrawSprite(207*32 + 26, 120*32 - 15, ANIM::FLAG, 2, jjGameTicks >> 3, 0, SPRITE::NORMAL, 0, 5);
		
	array<jjLAYER@> layers = jjLayerOrderGet();
	layers[13].xOffset += 6.0f;
	layers[14].xOffset += 4.0f;
	layers[21].xOffset += 0.05f;
	if (layers[13].xOffset % (layers[13].widthReal*32) == 0) layers[13].xOffset = 0;
	if (layers[14].xOffset % (layers[14].widthReal*32) == 0) layers[14].xOffset = 0;
	if (layers[21].xOffset % (layers[21].widthReal*32) == 0) layers[21].xOffset = 0;
	
	HH24::main();
	
	//test
	// if (jjLocalPlayers[0].keySelect) jjPrint( "Food: " + jjLocalPlayers[0].food + " | Gems: " + (jjLocalPlayers[0].gems[GEM::RED] + 5 * jjLocalPlayers[0].gems[GEM::GREEN] + 10 * jjLocalPlayers[0].gems[GEM::BLUE] + 20 * jjLocalPlayers[0].gems[GEM::PURPLE]) + " | Coins: " + jjLocalPlayers[0].coins);
}

void onLevelReload() {
	MLLE::SpawnOffgridsLocal();
	HH17::processEnemyColors();
	MLLE::ReapplyPalette();
	HH24::levelReload();
	
	for (uint i = 0; i < 32; ++i) { jjTriggers[i] = SavedTriggers[i]; }
}

void onPlayer(jjPLAYER@ player) {
	HH24::player(player);
}

void onFunction0(jjPLAYER@ player) {
	jjIsSnowing = false;
	player.lighting = 75;
}

void onFunction1(jjPLAYER@ player) {
	jjIsSnowing = true;
	player.lighting = 80;
}

void onFunction100(jjPLAYER@ play) {
	HH24::endLevel();
}

bool onDrawAmmo(jjPLAYER@ player, jjCANVAS@ canvas) {
	return MLLE::WeaponHook.drawAmmo(player, canvas);
}

bool onDrawScore(jjPLAYER@ player, jjCANVAS@ canvas) {
	HH24::score(player, canvas, true);
	return false;
}