#pragma require "SEweapon.asc"
#pragma require "SEfirework.j2a"
#pragma offer "SEfirework1.wav"
#pragma offer "SEfirework2.wav"
#include "SEweapon.asc"
namespace se {
shared class FireworkWeapon : 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) {
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;
}
}
FireworkWeapon firework;
}
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.