Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Academy | Superjazz | Battle | N/A |
class AbstractBullet : jjBEHAVIORINTERFACE {
private jjBEHAVIOR nativeBehavior;
private HANDLING::Bullet nativeBulletHandling;
private HANDLING::Player nativePlayerHandling;
AbstractBullet(const jjBEHAVIOR &in setNativeBehavior,
const HANDLING::Bullet &in setNativeBulletHandling,
const HANDLING::Player &in setNativePlayerHandling) {
nativeBehavior = setNativeBehavior;
nativeBulletHandling = setNativeBulletHandling;
nativePlayerHandling = setNativePlayerHandling;
}
void onBehave(jjOBJ@ obj) {
initBullet(obj);
}
bool onIsRFBullet(jjOBJ@ obj) {
return nativeBehavior == BEHAVIOR::RFBULLET;
}
void initBullet(jjOBJ@ obj) {
int ammoCount = jjPlayers[obj.creatorID].ammo[WEAPON::BLASTER];
obj.bulletHandling = HANDLING::IGNOREBULLET;
obj.playerHandling = HANDLING::SPECIAL;
if (debugModeOn) jjAlert("ammoCount: " + ammoCount);
if (ammoCount >= BULLET_MAGIC_ARROW-1 && ammoCount <= BULLET_MAGIC_ARROW) {
obj.scriptedCollisions = true;
obj.behavior = MagicArrow();
} else if (ammoCount >= BULLET_ICE_BOLT-1 && ammoCount <= BULLET_ICE_BOLT) {
obj.scriptedCollisions = true;
obj.behavior = IceBolt();
} else if (ammoCount >= BULLET_FIREBALL-1 && ammoCount <= BULLET_FIREBALL) {
obj.behavior = Fireball();
} else if (fullFeatures) {
obj.scriptedCollisions = true;
obj.behavior = BulletWrapper(obj, nativeBehavior, nativePlayerHandling);
} else {
obj.behavior = nativeBehavior;
obj.bulletHandling = nativeBulletHandling;
obj.playerHandling = nativePlayerHandling;
}
jjPlayers[obj.creatorID].ammo[WEAPON::BLASTER] = 50;
}
}
abstract class AreaOfEffect {
float xPos;
float yPos;
float radius;
int damage;
uint elapsed;
uint duration;
jjPLAYER@ caster;
AreaOfEffect(float setXPos, float setYPos, float setRadius, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
xPos = setXPos;
yPos = setYPos;
radius = setRadius;
damage = setDamage;
elapsed = duration = setDuration;
@caster = setCaster;
}
void animate() {}
void control(jjPLAYER@ play) {
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::FLARE, 5);
float xDistance = play.xPos - xPos;
float yDistance = play.yPos - yPos;
if (xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius && acUtils::gameIsRunning()) {
play.hurt(damage - players[play.playerID].magicResist, false, caster);
}
}
}
class Armageddon : AreaOfEffect {
int frame;
float meteorY;
bool exploding;
Armageddon(float setXPos, float setYPos, float setRadius, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
super(setXPos, setYPos, setRadius, setDamage, setDuration, setCaster);
meteorY = setYPos - 640;
exploding = false;
frame = 4;
}
void animate() override {
if (exploding) {
jjDrawResizedSprite(xPos, yPos, ANIM::AMMO, 81, frame, 14, 14, SPRITE::NORMAL, 0, 1);
if (jjGameTicks % 7 == 0) {
if (frame < 11) {
frame++;
}
}
} else {
jjDrawRotatedSprite(xPos, meteorY, ANIM::ROCK, 0, 0, 0, 5, 5, SPRITE::TINTED, 24, 1);
}
if (meteorY < yPos) {
meteorY += 32;
} else if (!exploding) {
exploding = true;
jjSamplePriority(SOUND::INTRO_BOEM2);
}
}
void control(jjPLAYER@ play) override {
if (playerInRange(play, true) && exploding) {
play.hurt(damage - players[play.playerID].magicResist, false, caster);
}
}
bool playerInRange(jjPLAYER@ play, bool vulnerable) {
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::FLARE, 5);
float xDistance = play.xPos - xPos;
float yDistance = play.yPos - yPos;
if (vulnerable) {
return xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius && acUtils::gameIsRunning()
&& acUtils::checkIfPlayerIsVulnerable(caster, play, cast<Spell@>(spells["A"]));
}
return xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius;
}
}
class Bless : Effect {
Bless(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration);
}
void affect() override {}
}
class BloodLust : Effect {
int originalFastFire;
BloodLust(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration, bool setIsLocal) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration, setIsLocal);
originalFastFire = setPlay.fastfire;
}
~BloodLust() {
play.fastfire = originalFastFire;
}
void affect() override {
play.fastfire = 6;
}
}
class BulletWrapper : jjBEHAVIORINTERFACE {
private jjBEHAVIOR nativeBehavior;
private HANDLING::Player nativePlayerHandling;
BulletWrapper(jjOBJ@ obj, const jjBEHAVIOR &in setNativeBehavior, const HANDLING::Player &in setNativeHandling) {
nativeBehavior = setNativeBehavior;
nativePlayerHandling = setNativeHandling;
}
void onBehave(jjOBJ@ obj) {
if (obj.state == STATE::KILL) {
obj.delete();
}
else {
controlObjectCollision(obj);
obj.behave(nativeBehavior);
}
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ play, int force) {
if (@play != null && acUtils::gameIsRunning()) {
jjPLAYER@ creator = jjPlayers[obj.creatorID];
if (obj.creatorType == CREATOR::PLAYER && creator.isEnemy(play) &&
play.blink == 0 && creator.blink == 0) {
int8 damage = obj.var[6] & 8 != 0 ? 2 : 1;
if (jjPlayers[creator.playerID].isZombie) damage++;
if (debugModeOn) jjAlert("damage now: " + damage);
damage += acUtils::getDamageModifier(players[creator.playerID], players[play.playerID]);
if (damage < 0) damage = 0;
if (debugModeOn) jjAlert("damage then: " + damage);
play.hurt(damage, false, creator);
obj.state = STATE::KILL;
}
return true;
}
return false;
}
}
class ChainLightningTarget {
int8 id;
int8 parentID;
int8 playerID;
int8 damage;
uint elapsed;
uint duration;
ChainLightningTarget(int8 setID, int8 setPlayerID, int8 setDamage, uint setDuration, int8 setParentID = -1) {
id = setID;
playerID = setPlayerID;
damage = setDamage;
duration = setDuration;
elapsed = setDuration;
parentID = setParentID;
}
}
class Chunk {
array<jjOBJ@> objects;
void addObject(jjOBJ@ obj) {
objects.insertLast(obj);
}
void clearObjects() {
objects.removeRange(0, objects.length);
}
}
class DeathRipple : AreaOfEffect {
int frame;
float range;
DeathRipple(float setXPos, float setYPos, float setRadius, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
super(setXPos, setYPos, setRadius, setDamage, setDuration, setCaster);
frame = 0;
}
void animate() override {
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
if (playerInRange(play, false)) {
jjDrawRotatedSprite(play.xPos, play.yPos, ANIM::AMMO, 66, frame, 0, 2, 2, SPRITE::SINGLECOLOR, 24);
}
}
if (jjGameTicks % 5 == 0) {
if (frame < 8) {
frame++;
} else {
frame = 0;
}
}
}
void control(jjPLAYER@ play) override {
if (playerInRange(play, true)) {
play.hurt(damage - players[play.playerID].magicResist, false, caster);
}
}
bool playerInRange(jjPLAYER@ play, bool vulnerable) {
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::FLARE, 5);
float xDistance = play.xPos - xPos;
float yDistance = play.yPos - yPos;
if (vulnerable) {
return xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius && acUtils::gameIsRunning()
&& acUtils::checkIfPlayerIsVulnerable(caster, play, cast<Spell@>(spells["H"]));
}
return xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius;
}
}
class DisruptingRay : Effect {
DisruptingRay(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration, bool setIsLocal, bool setIsCurse) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration, setIsLocal, setIsCurse);
}
void affect() override {}
}
abstract class Effect {
bool isLocal;
bool isCurse;
jjPLAYER@ play;
string name;
SPELL enumValue;
SPELL counterEffect;
uint elapsed;
uint duration;
Effect() {}
Effect(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect, uint setDuration,
bool setIsLocal = false, bool setIsCurse = false) {
@play = setPlay;
name = setName;
enumValue = setEnumValue;
counterEffect = setCounterEffect;
duration = setDuration;
isLocal = setIsLocal;
isCurse = setIsCurse;
elapsed = setDuration;
}
void affect() {}
}
class Fireball : jjBEHAVIORINTERFACE {
uint8 frame;
jjPLAYER@ currentCaster;
jjPLAYER@ originalCaster;
Fireball() {
frame = 0;
}
void onBehave(jjOBJ@ obj) {
switch(obj.state) {
case STATE::START:
jjSample(obj.xPos, obj.yPos, SOUND::AMMO_FIREGUN1A, 0, 7500);
obj.direction = jjPlayers[obj.creatorID].direction;
obj.xPos += obj.direction >= 0 ? TILE : -TILE;
obj.state = STATE::FLY;
obj.light = 125;
@currentCaster = jjPlayers[obj.creatorID];
@originalCaster = jjPlayers[obj.creatorID];
break;
case STATE::FLY:
{
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
if (obj.doesCollide(play, true) && play !is currentCaster) {
if (players[play.playerID].hasEffect(SPELL_MAGIC_MIRROR)) {
acUtils::addMagicMirrorAnimation(play.playerID, -obj.direction);
obj.direction = -obj.direction;
@currentCaster = play;
} else {
explode(obj);
}
}
}
obj.xPos += obj.direction >= 0 ? 10 : -10;
if (obj.xPos < 0 || obj.xPos > jjLayerWidth[4] * TILE) {
obj.delete();
} else if ((jjLayers[4].maskedVLine(int(obj.xPos+TILE), int(obj.yPos), 1))
|| (jjLayers[4].maskedVLine(int(obj.xPos-TILE), int(obj.yPos), 1))) {
explode(obj);
}
}
break;
}
}
void onDraw(jjOBJ@ obj) {
int angle = obj.direction >= 0 ? 0 : 540;
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 14, frame, angle, 2, 2);
if (frame < 7) frame++;
else frame = 0;
}
void explode(jjOBJ@ obj) {
acSpells::doAOE(currentCaster, originalCaster, SPELL_FIREBALL, obj.xPos, obj.yPos);
obj.delete();
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
return false;
}
}
class FireballExplosion : AreaOfEffect {
int frame;
FireballExplosion(float setXPos, float setYPos, float setRadius, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
super(setXPos, setYPos, setRadius, setDamage, setDuration, setCaster);
frame = 0;
}
void animate() override {
jjDrawResizedSprite(xPos, yPos, ANIM::AMMO, 81, frame, radius, radius, SPRITE::NORMAL, 0, 1);
if (jjGameTicks % 7 == 0) {
if (frame < 11) {
frame++;
}
}
}
void control(jjPLAYER@ play) override {
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::AMMO, frame, 81);
float xDistance = play.xPos - xPos;
float yDistance = play.yPos - yPos;
if (xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius && acUtils::gameIsRunning()) {
play.hurt(damage - players[play.playerID].magicResist, false, caster);
}
}
}
class Forgetfulness : Effect {
Forgetfulness(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration, bool setIsLocal, bool setIsCurse) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration, setIsLocal, setIsCurse);
}
void affect() override {
play.noFire = true;
}
}
class Frenzy : Effect {
Frenzy(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration);
}
void affect() override {}
}
class FrostRing : AreaOfEffect {
int frame;
FrostRing(float setXPos, float setYPos, float setRadius, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
super(setXPos, setYPos, setRadius, setDamage, setDuration, setCaster);
frame = 0;
}
void animate() override {
jjDrawResizedSprite(xPos, yPos, ANIM::AMMO, 82, frame, radius, radius, SPRITE::TINTED, 32, 1);
if (jjGameTicks % 3 == 0) {
if (frame < 11) {
frame++;
}
}
}
void control(jjPLAYER@ play) override {
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::AMMO, frame, 82);
float xDistance = play.xPos - xPos;
float yDistance = play.yPos - yPos;
if (xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius && acUtils::gameIsRunning()
&& play !is caster) {
play.hurt(damage - players[play.playerID].magicResist, false, caster);
play.freeze();
}
}
}
class GemMine {
int8 id;
int8 ownerID;
int captureElapsed, lockElapsed, yieldElapsed;
int captureBegin = 350;
int lockBegin = 2100;
int top, bottom, left, right;
int yieldBegin = 350;
array<int8> playersInRange;
string name;
GemMine(int8 id, string name, int top, int bottom, int left, int right) {
this.id = id;
this.name = name;
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
ownerID = -1;
captureElapsed = captureBegin;
yieldElapsed = yieldBegin;
lockElapsed = lockBegin;
}
void capture(int8 setOwnerID) {
captureElapsed = captureBegin;
lockElapsed = lockBegin;
ownerID = setOwnerID;
}
void control(jjPLAYER@ localPlayer, Player@ asPlayer) {
if (acUtils::gameIsRunning()) {
if (lockElapsed > 0) {
lockElapsed--;
} else {
for (int8 i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
int index = playersInRange.find(play.playerID);
if (index < 0 && playerInRange(play)) {
playersInRange.insertLast(play.playerID);
} else if (index >= 0 && !playerInRange(play)) {
playersInRange.removeAt(index);
}
}
if (playerInRange(localPlayer) && !asPlayer.isDead
&& localPlayer.playerID != ownerID && playersInRange.length == 1) {
if (captureElapsed > 0) {
if (captureElapsed == captureBegin) {
jjAlert("Capturing gem mine in..." + captureElapsed / SECOND, false, STRING::MEDIUM);
} else if (captureElapsed % SECOND == 0) {
jjAlert("" + captureElapsed / SECOND, false, STRING::MEDIUM);
}
captureElapsed--;
} else {
capture(localPlayer.playerID);
acNetworking::sendCaptureGemMinePacket(localPlayer.playerID, id);
}
} else {
captureElapsed = captureBegin;
}
}
if (ownerID >= 0 && jjPlayers[ownerID].isLocal) {
yieldGem(jjPlayers[ownerID]);
}
}
}
void yieldGem(jjPLAYER@ play) {
if (yieldElapsed > 0) {
yieldElapsed--;
} else {
yieldElapsed = yieldBegin;
jjAddObject(OBJECT::PURPLEGEM, play.xPos, play.yPos);
}
}
void draw(jjCANVAS@ canvas) {
uint8 color = 0;
uint8 _ = 0;
string ownerName = "";
if (ownerID >= 0) {
jjPLAYER@ owner = jjPlayers[ownerID];
owner.furGet(_, color, _, _);
ownerName = owner.name;
}
jjTEXTAPPEARANCE centeredText();
centeredText.align = STRING::CENTER;
canvas.drawSprite(right * TILE, bottom * TILE, ANIM::FLAG, 3, 0, 0, SPRITE::SINGLECOLOR, color);
canvas.drawString(right * TILE, (bottom + 1) * TILE, "Owned by\n" + ownerName, STRING::SMALL, centeredText);
if (acUtils::gameIsRunning() && lockElapsed > 0) {
canvas.drawString(right * TILE, (bottom + 1) * TILE, "\n\nUnlocking in " + int(lockElapsed / SECOND), STRING::SMALL, centeredText);
}
}
bool playerInRange(jjPLAYER@ play) {
return play.xPos >= left * TILE && play.xPos <= right * TILE
&& play.yPos >= top * TILE && play.yPos <= bottom * TILE;
}
}
class Key {
int keyCode;
string key;
bool keyPressed;
Key() {}
Key(int setKeyCode, string setKey) {
keyCode = setKeyCode;
key = setKey;
keyPressed = false;
}
}
class IceBolt : jjBEHAVIORINTERFACE {
int frame;
jjPLAYER@ currentCaster;
jjPLAYER@ originalCaster;
IceBolt() {
frame = 0;
}
void onBehave(jjOBJ@ obj) {
switch(obj.state) {
case STATE::START:
jjSample(obj.xPos, obj.yPos, SOUND::AMMO_ICEPU4);
obj.direction = jjPlayers[obj.creatorID].direction;
obj.xPos += obj.direction >= 0 ? 16 : -16;
obj.state = STATE::FLY;
obj.var[6] = 16;
obj.light = 100;
@currentCaster = jjPlayers[obj.creatorID];
@originalCaster = jjPlayers[obj.creatorID];
break;
case STATE::FLY:
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
if (abs(obj.xPos - play.xPos) <= 32 && abs(obj.yPos - play.yPos) <= 32) {
if (obj.doesCollide(play, true) && currentCaster.isEnemy(play)
&& acUtils::gameIsRunning()) {
if (players[play.playerID].hasEffect(SPELL_MAGIC_MIRROR)) {
acUtils::addMagicMirrorAnimation(play.playerID, -obj.direction);
obj.direction = -obj.direction;
@currentCaster = play;
} else {
Spell@ spell = cast<Spell@>(spells["E"]);
play.hurt(spell.baseDamage
+ players[originalCaster.playerID].spellDamageBonus
- players[play.playerID].magicResist,
false, currentCaster);
play.freeze();
}
}
}
}
obj.xPos += obj.direction >= 0 ? 10 : -10;
if (obj.xPos < 0 || obj.xPos > jjLayerWidth[4] * TILE) {
obj.delete();
}
controlObjectCollision(obj);
break;
case STATE::KILL:
obj.state = STATE::FLY;
break;
case STATE::EXPLODE:
default:
obj.state = STATE::FLY;
break;
}
}
void onDraw(jjOBJ@ obj) {
int angle = obj.direction >= 0 ? 0 : 540;
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::AMMO, 11, frame, angle, 2, 2, SPRITE::TINTED, 35);
if (frame < 7) frame++;
else frame = 0;
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
return false;
}
}
class Implosion : AreaOfEffect {
float scale;
int8[] targets;
bool finished;
Implosion(float setXPos, float setYPos, float setRadius, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
super(setXPos, setYPos, setRadius, setDamage, setDuration, setCaster);
scale = 5;
finished = false;
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::FLARE, 5);
Spell@ spell = cast<Spell@>(spells["Q"]);
if (acUtils::checkIfPlayerIsInRange(setCaster, play, scaledRadius) && acUtils::checkIfPlayerIsVulnerable(caster, play, spell)
&& acUtils::gameIsRunning() && targets.find(play.playerID) < 0) {
if (debugModeOn) jjAlert("" + play.playerID);
targets.insertLast(play.playerID);
}
}
}
void animate() override {
for (uint i = 0; i < targets.length; i++) {
jjPLAYER@ play = jjPlayers[targets[i]];
jjDrawRotatedSprite(play.xPos, play.yPos, ANIM::BOLLPLAT, 0, 0, 0, scale, scale, SPRITE::SINGLECOLOR, 1);
}
if (scale > 0) {
scale -= 0.1;
} else if (!finished) {
finished = true;
for (uint i = 0; i < targets.length; i++) {
jjPLAYER@ play = jjPlayers[targets[i]];
if (play.isLocal) {
play.hurt(damage - players[play.playerID].magicResist, true, caster);
jjSamplePriority(SOUND::SMALTREE_GROUND);
}
}
}
}
void control(jjPLAYER@ play) override {}
bool playerInRange(jjPLAYER@ play, bool vulnerable) {
float scaledRadius = acUtils::getScaledRadius(radius, ANIM::FLARE, 5);
float xDistance = play.xPos - xPos;
float yDistance = play.yPos - yPos;
if (vulnerable) {
return xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius && acUtils::gameIsRunning()
&& acUtils::checkIfPlayerIsVulnerable(caster, play, cast<Spell@>(spells["Q"]));
}
return xDistance*xDistance + yDistance*yDistance < scaledRadius*scaledRadius;
}
}
class MagicArrow : jjBEHAVIORINTERFACE {
jjPLAYER@ currentCaster;
jjPLAYER@ originalCaster;
void onBehave(jjOBJ@ obj) {
switch(obj.state) {
case STATE::START:
jjSample(obj.xPos, obj.yPos, SOUND::AMMO_BULFL1);
obj.direction = jjPlayers[obj.creatorID].direction;
obj.xPos += obj.direction >= 0 ? 16 : -16;
obj.state = STATE::FLY;
obj.var[6] = 16;
obj.light = 100;
@currentCaster = jjPlayers[obj.creatorID];
@originalCaster = jjPlayers[obj.creatorID];
break;
case STATE::FLY:
{
for (int i = 0; i < 32; i++) {
jjPLAYER@ play = jjPlayers[i];
if (abs(obj.xPos - play.xPos) <= 32 && abs(obj.yPos - play.yPos) <= 32) {
if (obj.doesCollide(play, true) && currentCaster.isEnemy(play)
&& acUtils::gameIsRunning()) {
if (players[play.playerID].hasEffect(SPELL_MAGIC_MIRROR)) {
acUtils::addMagicMirrorAnimation(play.playerID, -obj.direction);
obj.direction = -obj.direction;
@currentCaster = play;
} else {
Spell@ spell = cast<Spell@>(spells["M"]);
play.hurt(spell.baseDamage
+ players[originalCaster.playerID].spellDamageBonus
- players[play.playerID].magicResist,
false, currentCaster);
}
}
}
}
obj.xPos += obj.direction >= 0 ? 10 : -10;
obj.yPos += jjSin(8 * uint(obj.xPos % float(1024))) * 8;
if (obj.xPos < 0 || obj.xPos > jjLayerWidth[4] * TILE) {
obj.delete();
}
controlObjectCollision(obj);
}
break;
case STATE::KILL:
obj.state = STATE::FLY;
break;
case STATE::EXPLODE:
default:
obj.state = STATE::FLY;
break;
}
}
void onDraw(jjOBJ@ obj) {
int angle = obj.direction >= 0 ? 950 : 425;
jjDrawRotatedSprite(obj.xPos, obj.yPos, ANIM::FLAG, 0, 0, angle, 1.5, 1.5, SPRITE::MENUPLAYER);
obj.particlePixelExplosion(1);
}
bool onObjectHit(jjOBJ@ obj, jjOBJ@ bullet, jjPLAYER@ player, int force) {
return true;
}
}
class MagicMirror : Effect {
MagicMirror(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration);
}
void affect() override {}
}
class MagicMirrorAnimation {
int direction;
int frameCounter;
int elapsed;
jjPLAYER@ play;
MagicMirrorAnimation(jjPLAYER@ play, int direction) {
@this.play = play;
this.direction = direction;
elapsed = 37;
frameCounter = 0;
}
bool draw() {
int angle = direction >= 0 ? 256 : 768;
int xOffset = direction >= 0 ? 24 : -24;
jjDrawRotatedSprite(play.xPos + xOffset, play.yPos, ANIM::AMMO, 76, frameCounter, 256, 1.5, 1.5,
SPRITE::SINGLEHUE, 128);
if (elapsed > 0) {
elapsed--;
frameCounter++;
return false;
} else {
return true;
}
}
}
class Player {
int mana;
int maxMana;
int manaRegenCounter;
int manaRegenCounterEnd = 140;
int manaRegenRate;
int cooldown;
int8 playerID;
int8 magicResist;
int8 spellDamageBonus;
uint32 originalFur;
uint8 currentHealth;
uint spellDurationBonus;
bool isDead;
bool isChanneling;
string selectedSpellKey;
array<SKILL> activeSkills;
array<Effect@> activeEffects;
Player() {
isDead = false;
isChanneling = false;
selectedSpellKey = "";
mana = STARTING_MANA;
maxMana = DEFAULT_MAX_MANA;
manaRegenCounter = 0;
manaRegenRate = DEFAULT_MANA_REGEN_RATE;
playerID = 0;
cooldown = 0;
magicResist = 0;
spellDamageBonus = 0;
spellDurationBonus = 0;
}
~Player() {
jjPLAYER@ play = jjPlayers[playerID];
if (originalFur != 0 && !play.isZombie) {
play.fur = originalFur;
}
}
void addNewRandomSkill(string playerName) {
if (activeSkills.length < skills.length) {
int index = 0;
SKILL randomSkill = SKILL_MAX_MANA;
while (index >= 0) {
uint random = jjRandom() % skills.length;
randomSkill = SKILL(random);
index = activeSkills.find(randomSkill);
}
if (jjIsServer) {
acUtils::alertOfLearnedSkill(playerName, randomSkill);
} else {
acNetworking::sendSkillLearnedPacket(playerID, randomSkill);
}
acUtils::setSkillBonus(this, randomSkill, playerID);
activeSkills.insertLast(randomSkill);
}
}
bool isExistingEffectOrCounterEffect(Effect@ activeEffect, Effect@ newEffect) {
return activeEffect.enumValue == newEffect.enumValue
|| activeEffect.enumValue == newEffect.counterEffect;
}
void setNewActiveEffect(Effect@ newEffect) {
int j = 0;
int activeEffectsLength = activeEffects.length();
for (int i = 0; i < activeEffectsLength; i++) {
if (!isExistingEffectOrCounterEffect(activeEffects[i], newEffect)) {
@activeEffects[j] = activeEffects[i];
j++;
}
}
activeEffects.removeRange(j, activeEffectsLength - j);
activeEffects.insertLast(newEffect);
}
void setSelectedSpellKey(string newSelectedSpellKey) {
selectedSpellKey = newSelectedSpellKey;
}
void setChanneledSpellKey(string newSelectedSpellKey) {
selectedSpellKey = newSelectedSpellKey;
isChanneling = true;
}
void unSetChanneledSpellKey() {
selectedSpellKey = "";
isChanneling = false;
}
void removeActiveEffect(uint index) {
activeEffects.removeAt(index);
}
void removeAllActiveEffects() {
activeEffects.removeRange(0, activeEffects.length);
}
void removeNegativeEffects() {
int j = 0;
int activeEffectsLength = activeEffects.length();
for (int i = 0; i < activeEffectsLength; i++) {
if (!activeEffects[i].isCurse) {
@activeEffects[j] = activeEffects[i];
j++;
}
}
activeEffects.removeRange(j, activeEffectsLength - j);
}
void regenerateMana(jjPLAYER@ play) {
if (manaRegenCounter < manaRegenCounterEnd) {
manaRegenCounter += isInMagicWell(play) ? manaRegenRate * 4 : manaRegenRate;
} else {
manaRegenCounter = 0;
if (mana < maxMana) {
mana++;
}
}
}
bool hasEffect(SPELL effectEnum) {
for (uint i = 0; i < activeEffects.length; i++) {
if (activeEffects[i].enumValue == effectEnum) {
return true;
}
}
return false;
}
bool isInMagicWell(jjPLAYER@ play) {
return play.xPos > MAGIC_WELL_LEFT * TILE && play.xPos < MAGIC_WELL_RIGHT * TILE
&& play.yPos > MAGIC_WELL_TOP * TILE;
}
}
class Precision : Effect {
Precision(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration);
}
void affect() override {}
}
class Skill {
SKILL enumValue;
string name;
string description;
Skill(SKILL setEnumValue) {
enumValue = setEnumValue;
}
Skill(SKILL setEnumValue, string setName, string setDescription) {
enumValue = setEnumValue;
name = setName;
description = setDescription;
}
bool opEquals(Skill@ other) {
return enumValue == other.enumValue;
}
}
class Slow : Effect {
Slow(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration, bool setIsLocal, bool setIsCurse) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration, setIsLocal, setIsCurse);
}
void affect() override {
if (play.xSpeed > SLOW_SPEED) {
play.xSpeed = SLOW_SPEED;
} else if (play.xSpeed < -SLOW_SPEED) {
play.xSpeed = -SLOW_SPEED;
}
}
}
class Spell {
string key;
string name;
SPELL enumValue;
SPELL counterSpell;
uint tier;
uint numpad;
int localCount;
int baseDamage;
uint baseDuration;
int baseManaCost;
float channelingTime;
float radius;
bool damagesAll;
string description;
Spell() {}
Spell(string setKey, string setName, SPELL setEnumValue, SPELL setCounterSpell, uint setTier,
uint setNumpad, int setBaseDamage, uint setBaseDuration, int setBaseManaCost,
float setChannelingTime, float setRadius, bool setDamagesSelf, string setDescription) {
key = setKey;
name = setName;
enumValue = setEnumValue;
counterSpell = setCounterSpell;
tier = setTier;
numpad = setNumpad;
baseDamage = setBaseDamage;
baseDuration = setBaseDuration;
baseManaCost = setBaseManaCost;
channelingTime = setChannelingTime;
radius = setRadius;
damagesAll = setDamagesSelf;
description = setDescription;
localCount = 0;
}
int opCmp(const Spell@ otherSpell) {
return numpad - otherSpell.numpad;
}
}
class StoneSkin : Effect {
StoneSkin(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration);
}
void affect() override {}
}
class VisualGem {
float x, y, scale;
int angle, color, frame;
VisualGem(float setX, float setY) {
x = setX;
y = setY;
angle = jjRandom() % 1024;
color = jjRandom() % 12;
//scale = jjRandom() % 40 * 0.01 + 0.1;
scale = 0.3;
frame = jjRandom() % 8;
}
void draw(jjCANVAS@ canvas) {
canvas.drawRotatedSprite(int(x*TILE), int(y*TILE), ANIM::PICKUPS, 34, frame, angle, scale, scale, SPRITE::GEM, color);
}
}
class WallOfFire {
int damage;
int frame;
int channel;
int8 height;
float xOrigin;
float yOrigin;
uint elapsed;
uint duration;
jjPLAYER@ caster;
WallOfFire(float setXOrigin, float setYOrigin, int8 setHeight, int setDamage, uint setDuration, jjPLAYER@ setCaster) {
xOrigin = setXOrigin;
yOrigin = setYOrigin;
height = setHeight;
damage = setDamage;
elapsed = duration = setDuration;
@caster = setCaster;
frame = 1;
channel = 0;
if (height > WALL_OF_FIRE_MAX_HEIGHT) {
height = WALL_OF_FIRE_MAX_HEIGHT;
}
}
}
class Weakness : Effect {
Weakness(jjPLAYER@ setPlay, string setName, SPELL setEnumValue, SPELL setCounterEffect,
uint setDuration, bool setIsLocal, bool setIsCurse) {
super(setPlay, setName, setEnumValue, setCounterEffect, setDuration, setIsLocal, setIsCurse);
}
void affect() override {}
}
void controlObjectCollision(jjOBJ@ obj) {
if (obj.state != STATE::EXPLODE) {
uint yChunk = (uint(obj.yPos) + 64) >> 7;
uint xChunk = (uint(obj.xPos) + 64) >> 7;
for (uint y = 0; y < 2; y++) {
for (uint x = 0; x < 2; x++) {
if (yChunk - y < chunks.length && xChunk - x < chunks[yChunk - y].length) {
array<jjOBJ@>@ objects = chunks[yChunk - y][xChunk - x].objects;
for (uint i = 0; i < objects.length; i++) {
jjOBJ@ other = objects[i];
if (other.playerHandling == HANDLING::PICKUP && obj.doesCollide(other, true)) {
obj.objectHit(other, HANDLING::PICKUP);
} else if (other.playerHandling == HANDLING::SPECIAL && obj.doesCollide(other, true)) {
obj.objectHit(other, HANDLING::ENEMY);
} else if (other.eventID == OBJECT::DESTRUCTSCENERY && obj.doesCollide(other, true)) {
obj.objectHit(other, HANDLING::ENEMY);
obj.delete();
}
}
}
}
}
}
}
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.