Name | Author | Game Mode | Rating | |||||
---|---|---|---|---|---|---|---|---|
Miscellaneous stuff | Violet CLM | Multiple | N/A |
#pragma require "ScaryMonsters.asc"
#pragma require "ScaryMonsters.j2a"
namespace ScaryMonsters {
void BeAClown(uint8 eventID) {
jjOBJ@ preset = jjObjectPresets[eventID];
preset.behavior = Clown;
preset.playerHandling = HANDLING::ENEMY;
preset.scriptedCollisions = false;
preset.bulletHandling = HANDLING::HURTBYBULLET;
preset.energy = 100;
preset.isTarget = true;
preset.isBlastable = true;
preset.isFreezable = true;
preset.triggersTNT = true;
preset.points = 500;
preset.counter = 0;
preset.state = STATE::START;
preset.killAnim = jjAnimSets[ANIM::AMMO] + 81;
preset.curAnim = jjAnimSets[ANIM::CUSTOM[0]].load(0, "ScaryMonsters.j2a");
preset.curFrame = jjAnimations[preset.curAnim];
preset.frameID = 0;
}
const int ClownFrequency = 6000;
void Clown(jjOBJ@ obj) {
++obj.counter;
if (obj.energy < 100 && obj.bulletHandling == HANDLING::HURTBYBULLET) { //hurt!
jjOBJ@ ball = jjObjects[jjAddObject(obj.eventID, obj.xPos, obj.yPos - 4, obj.objectID, CREATOR::OBJECT, ClownBall)];
ball.xSpeed = obj.xSpeed * 3 * obj.direction;
if (ball.xSpeed == 0)
ball.behavior = BEHAVIOR::BOUNCEONCE;
ball.curAnim = obj.curAnim;
ball.determineCurFrame();
ball.ySpeed = -3;
ball.energy = 1;
ball.points = 100;
obj.bulletHandling = HANDLING::IGNOREBULLET;
obj.counter = 0;
if (obj.state == STATE::FREEZE)
obj.unfreeze(0);
obj.state = STATE::FALL;
obj.xSpeed = obj.direction * -3;
obj.xAcc = obj.direction / 24.f;
obj.ySpeed = -2;
obj.yPos -= 30;
obj.curFrame = jjAnimations[obj.curAnim += 3];
obj.creatorType = CREATOR::OBJECT; //don't come back to life anymore if deactivated
} else switch (obj.state) {
case STATE::START:
obj.putOnGround(false);
obj.var[0] = jjMaskedTopVLine(int(obj.xPos), int(obj.yPos) - 40, 50);
obj.state = STATE::ROTATE;
obj.direction = 1;
break;
case STATE::DEACTIVATE:
obj.deactivate();
break;
case STATE::FREEZE:
--obj.counter;
if (--obj.freeze == 0)
obj.state = obj.oldState;
if (obj.oldState != STATE::WAIT && obj.oldState != STATE::FALL)
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, jjAnimations[obj.curAnim], obj.direction);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::FROZEN);
break;
case STATE::ROTATE: {
const auto sine = jjSin(obj.counter << 1);
obj.xSpeed = sine * (3 + jjDifficulty / 2.f);
const float targetX = obj.xPos + obj.xSpeed * obj.direction;
if (jjMaskedTopVLine(int(targetX), int(obj.yPos) - 40, 50) == obj.var[0] && jjEventAtLastMaskedPixel != AREA::STOPENEMY)
obj.xPos = targetX;
else {
obj.direction = -obj.direction;
jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::SPAZSOUNDS_HAHAHA + (jjRandom() & 1)), 0, ClownFrequency);
}
obj.xAcc += sine;
obj.frameID = int(obj.xAcc) / 4;
obj.curAnim += 1;
obj.determineCurFrame(true);
obj.curAnim -= 1;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.determineCurFrame(false), obj.direction);
const int angle = int(sine * obj.direction * 96);
const float asin = jjSin(angle), acos = jjCos(angle);
const int xdiff = 6 * obj.direction;
jjDrawRotatedSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, angle, obj.direction,1, obj.justHit == 0 ? SPRITE::NORMAL : SPRITE::SINGLECOLOR, 15);
jjDrawSpriteFromCurFrame(obj.xPos - (asin * 33 + acos * xdiff), obj.yPos - (acos * 33 - asin * xdiff), jjAnimations[obj.curAnim + 5] + ((jjGameTicks >> 2) % 12), obj.direction);
if (obj.counter == 256) {
obj.counter = 0;
obj.state = STATE::ATTACK;
}
break; }
case STATE::ATTACK:
obj.curFrame = jjAnimations[obj.curAnim + 2] + obj.counter / 10;
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, jjAnimations[obj.curAnim], obj.direction);
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction);
if (obj.counter == 20) {
jjSample(obj.xPos, obj.yPos, SOUND::SPAZSOUNDS_HIHI, 0, ClownFrequency * 3 / 5);
jjOBJ@ bomb = jjObjects[obj.fireBullet(OBJECT::BOMB)];
bomb.curAnim = obj.curAnim + 6;
bomb.xSpeed = obj.direction * 2.5;
bomb.ySpeed = -3;
bomb.state = STATE::FLY;
if (jjDifficulty > 2) {
bomb.playerHandling = HANDLING::ENEMYBULLET;
bomb.animSpeed = 1;
}
} else if (obj.counter == 49) {
obj.counter = 0;
obj.state = STATE::ROTATE;
}
break;
case STATE::FALL: {
if ((obj.xSpeed > 0) == (obj.direction == -1)) {
const float targetX = obj.xPos + (obj.xSpeed += obj.xAcc);
if (!jjMaskedVLine(int(targetX), int(obj.yPos) - 12, 24))
obj.xPos = targetX;
else
obj.xSpeed = obj.xAcc = 0;
}
const float targetY = obj.yPos + (obj.ySpeed += 0.09);
if (!jjMaskedHLine(int(obj.xPos) - 24, 24, int(targetY) + 18)) {
obj.yPos = targetY;
if (obj.counter == 20)
++obj.curFrame;
} else {
obj.curFrame = jjAnimations[obj.curAnim] + 2;
obj.state = STATE::WAIT;
obj.counter = 0;
}
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, obj.justHit == 0 ? SPRITE::NORMAL : SPRITE::SINGLECOLOR, 15);
break; }
case STATE::WAIT:
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction);
if (obj.counter == 35)
obj.curFrame += 1;
else if (obj.counter == 50) {
jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::SPAZSOUNDS_HAHAHA + (jjRandom() & 1)), 0, ClownFrequency);
obj.bulletHandling = HANDLING::HURTBYBULLET;
obj.curAnim += 1;
obj.frameID = 0;
obj.determineCurFrame();
obj.state = STATE::WALK;
obj.behavior = BEHAVIOR::WALKINGENEMY;
obj.xSpeed = 4;
obj.xAcc = 0;
obj.energy = (jjDifficulty > 2) ? 4 : 3;
}
break;
}
}
void ClownBall(jjOBJ@ obj) { //minimally edited from BEHAVIOR::TURTLESHELL to avoid killing enemies
if (obj.state==STATE::START)
obj.state=STATE::FLY;
else if (obj.state==STATE::KILL || obj.state==STATE::DEACTIVATE)
obj.delete();
else if (obj.state == STATE::FREEZE) {
if (--obj.freeze == 0)
obj.state = STATE::FLY;
} else {
if (abs(obj.xSpeed) > 2) {
if (obj.yPos>jjWaterLevel)
{
obj.xSpeed=(obj.xSpeed*7)/8;
obj.ySpeed=(obj.ySpeed*7)/8;
}
else
obj.xSpeed=(obj.xSpeed*63)/64;
}
obj.xPos+=obj.xSpeed;
obj.yPos+=obj.ySpeed;
const bool nogoup=jjMaskedPixel(int(obj.xPos),int(obj.yPos)-4);
const bool nogodown=jjMaskedPixel(int(obj.xPos),int(obj.yPos)+10);
const bool nogoleft=jjMaskedPixel(int(obj.xPos)-8,int(obj.yPos));
const bool nogoright=jjMaskedPixel(int(obj.xPos)+8,int(obj.yPos));
int calc, calc2;
if ((obj.xSpeed>0) && nogoright)
{
calc=1+int(obj.xSpeed);
calc2=jjMaskedTopVLine(int(obj.xPos+8),int(obj.yPos)+10-calc,calc);
if ((calc2<=1) || (calc2>=calc))
{
obj.xPos-=obj.xSpeed;
obj.xSpeed=-obj.xSpeed;
} else
{
obj.yPos-=calc;
obj.xSpeed=(obj.xSpeed*15)/16;
};
} else
if ((obj.xSpeed<0) && nogoleft)
{
calc=1-int(obj.xSpeed);
calc2=jjMaskedTopVLine(int(obj.xPos-8),int(obj.yPos)+10-calc,calc);
if ((calc2<=1) || (calc2>=calc))
{
obj.xPos-=obj.xSpeed;
obj.xSpeed=-obj.xSpeed;
} else
{
obj.yPos-=calc;
obj.xSpeed=(obj.xSpeed*15)/16;
};
};
if (nogoup && (obj.ySpeed<0))
{
obj.yPos-=obj.ySpeed; //reset to last location!
obj.ySpeed=-obj.ySpeed/2;
} else
if (nogodown)
{
calc=jjMaskedTopVLine(int(obj.xPos),int(obj.yPos),10);
if (calc != 0)
obj.yPos-=(10-calc);
else
obj.yPos-=obj.ySpeed;
if (obj.ySpeed>1)
jjSample(obj.xPos, obj.yPos, SOUND::Sample(SOUND::COMMON_IMPACT1 + (jjRandom() & 7)));
obj.ySpeed=-(obj.ySpeed/2);
} else
{
if (obj.yPos>jjWaterLevel)
{
obj.ySpeed+=0.125/4;
if (obj.ySpeed>4) obj.ySpeed=4;
else
if (obj.ySpeed<-4) obj.ySpeed=-4;
}
else
{
obj.ySpeed+=0.125;
if (obj.ySpeed>8) obj.ySpeed=8;
};
};
}
obj.direction = (obj.xSpeed >= 0) ? 1 : -1;
if (jjGameTicks & 3 == 0) {
++obj.frameID;
obj.determineCurFrame();
}
obj.draw();
}
}
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.