So, I'm trying to code a custom boss that summons a bunch of enemies, including summoning low HP bosses as enemies, but I've run into an issue: I'm having a hard time making things immune to (or at least not 1HKO'd by) Spaz's kick and Jazz's uppercut. Setting things to use playerHandling mode HANDLING::SPECIAL "works"... but also removes non-bullet collision detection for most enemies and the main boss (the latter would actually be a good thing if it was consistent, since I don't want it to be hurt by anything other than time passing anyways, but it's too inconsistent to be useful). It also has an issue where setting the bosses to have that collision mode means they beat the level when killed, when you're only supposed to win the level by letting the main boss run out of HP. Basically, it's supposed to be a survival challenge.
Here's the full script for the level as of now, including an attempt at a work-around for the issue where killing bosses clears the level (the work-around works, but only about half the time for some reason):
Code:
#include "MLLE-Include-1.4.asc"
const bool MLLESetupSuccessful = MLLE::Setup();
#pragma require "Tube.j2t"
#pragma require "Medivo.j2t"
#pragma require "hgfCow-MLLE-Data-1.j2l"
#pragma require "Carrot1.j2t"
#pragma require "hgfCow.j2l"
//a special thanks to Sir Ementaler and Violet CLM for their assistance with writing the script!
void onLevelLoad() {
jjObjectPresets[OBJECT::DEVILDEVAN].behavior = cowBoss;
jjObjectPresets[OBJECT::DEVILDEVAN].isFreezable = false;
jjObjectPresets[OBJECT::DEVILDEVAN].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::DEVILDEVAN].scriptedCollisions = true;
jjObjectPresets[OBJECT::DEVILDEVAN].energy = 50;
jjObjectPresets[OBJECT::DEVILDEVAN].bulletHandling = HANDLING::DESTROYBULLET;
jjObjectPresets[OBJECT::BILSY].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::BILSY].playerHandling = HANDLING::ENEMY;
jjObjectPresets[OBJECT::BILSY].energy = 14;
jjObjectPresets[OBJECT::BUBBA].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::BUBBA].playerHandling = HANDLING::ENEMY;
jjObjectPresets[OBJECT::BUBBA].energy = 5+(jjDifficulty*4);
jjObjectPresets[OBJECT::TUFBOSS].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::TUFBOSS].playerHandling = HANDLING::ENEMY;
jjObjectPresets[OBJECT::TUFBOSS].energy = 7+(jjDifficulty*4);
jjObjectPresets[OBJECT::BOLLY].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::BOLLY].playerHandling = HANDLING::SPECIAL;
jjObjectPresets[OBJECT::BOLLY].energy = 10;
jjObjectPresets[OBJECT::UTERUS].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::UTERUS].playerHandling = HANDLING::ENEMY;
jjObjectPresets[OBJECT::UTERUS].energy = 10;
jjObjectPresets[OBJECT::ROBOT].bulletHandling = HANDLING::HURTBYBULLET;
jjObjectPresets[OBJECT::ROBOT].playerHandling = HANDLING::ENEMY;
jjObjectPresets[OBJECT::ROBOT].energy = 30;
//just a thing I borrowed from plusPixelMapEx
jjANIMATION@ anim = jjAnimations[jjObjectPresets[OBJECT::DEVILDEVAN].curAnim];
anim.frameCount = 1;
jjANIMFRAME@ frame = jjAnimFrames[anim.firstFrame];
jjPIXELMAP kingCow(459*32, 3*32, 6*32, 7*32, 4);
kingCow.save(frame);
frame.hotSpotX = -frame.width / 2;
frame.hotSpotY = -frame.height / 2;
}
void onLevelBegin(){
//make sure the main song reloads after encountering the boss
jjMusicLoad("Meatball Parade.ogg");
}
//int rPart(float x,float y) { // render a part of Devan Force
// jjDrawSprite(x, y, ANIM::BIGROCK, 0, 0, 0);
//void jjDrawSprite(x, y, uint8 (ANIM::BIGROCK), uint8 (0), uint8 (0), int direction = 0, SPRITE::Mode mode = SPRITE::NORMAL, int param = 0, int8 layerZ = 4, uint8 layerXY = 4, int8 playerID = -1)
// return 0;
//}
void cowBoss(jjOBJ@ obj) {
switch (obj.state) {
case STATE::START:
//don't start boss until player has reached boss activation point
obj.state = STATE::DELAYEDSTART;
case STATE::DELAYEDSTART:
//loop players
for (int i = 0; i < jjLocalPlayerCount; ++i) {
jjPLAYER@ localPlayer = jjLocalPlayers[i];
if (localPlayer.bossActivated) {
localPlayer.boss = obj.objectID;
obj.state = STATE::START;
}
}
if (obj.state == STATE::START) {
//set object to be handled in a more normal way, since we're using Devil Devan as the "base"
obj.playerHandling = HANDLING::SPECIAL;
//load song
jjMusicLoad("dang.j2b");
//start boss
obj.state = STATE::ATTACK;
//initialize some important variables
obj.age = 60; //boss attack cooldown
obj.special = 0; //next attack the boss is going to use
obj.var[0] = 0; //move direction
obj.var[1] = 0; //reticle height
obj.var[2] = 10; //carrot delay
break;
}
return;
case STATE::KILL:
//start next stage
jjNxt(true, false);
case STATE::DEACTIVATE:
//reset boss
jjMusicLoad("Meatball Parade.ogg");
obj.deactivate();
break;
case STATE::ATTACK:
//draw boss
jjDrawSpriteFromCurFrame(obj.xPos, obj.yPos, obj.curFrame, obj.direction, SPRITE::NORMAL, 24);
//set cow as boss
for (int i = 0; i < jjLocalPlayerCount; ++i) {
jjPLAYER@ localPlayer = jjLocalPlayers[i];
if (localPlayer.bossActivated) {
localPlayer.boss = obj.objectID;
}
}
//just some old code I didn't completely remove
//for (int i = 1; i < jjObjectCount; i++){
// jjOBJ@ o = jjObjects[i];
// if (o.eventID == OBJECT::BOLLY){obj.var[0] == 1;}
// if (o.eventID == OBJECT::BUBBA){obj.var[0] == 1;}
// if (o.eventID == OBJECT::BILSY){obj.var[0] == 1;}
// if (o.eventID == OBJECT::TUFBOSS){obj.var[0] == 1;}
//}
//if (obj.var[0] == 0){}
//constantly cool down attack
obj.age -= 1;
//prepare summon
if (obj.age <= 0) {
//just some more old code I didn't completely remove
//if (obj.special == 1){jjAddObject(OBJECT::TUFBOSS, obj.xPos, obj.yPos+96);}
//if (obj.special == 2){jjAddObject(OBJECT::BUBBA, obj.xPos, obj.yPos);}
//if (obj.special == 2){jjAddObject(OBJECT::BOLLY, obj.xPos, obj.yPos);}
//if (obj.special == 2){jjAddObject(OBJECT::UTERUS, obj.xPos, obj.yPos);}
//if (obj.special == 3){jjAddObject(OBJECT::BILSY, obj.xPos, obj.yPos);}
//summon an enemy based on next attack chosen
if (obj.special == 0){jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 1){jjObjects[jjAddObject(OBJECT::BAT, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 2){jjObjects[jjAddObject(OBJECT::RAVEN, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 3){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 4){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 5){jjObjects[jjAddObject(OBJECT::TUFBOSS, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}
//if (obj.special == 6){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;
// if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos+10, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;
// jjObjects[jjAddObject(OBJECT::BEE, obj.xPos-10, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}}
if (obj.special == 6){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;
if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::BEE, obj.xPos+10, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}}
if (obj.special == 7){jjObjects[jjAddObject(OBJECT::BUBBA, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 8){jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;
if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos+10, obj.yPos)].playerHandling = HANDLING::SPECIAL;
jjObjects[jjAddObject(OBJECT::LIZARD, obj.xPos-10, obj.yPos)].playerHandling = HANDLING::SPECIAL;}}
if (obj.special == 9 && jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::BILSY, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 9 && jjDifficulty == 1){jjObjects[jjAddObject(OBJECT::BAT, obj.xPos, obj.yPos+120)].playerHandling = HANDLING::SPECIAL;}
if (obj.special == 9 && jjDifficulty == 0){jjAddObject(OBJECT::CARROT, obj.xPos, obj.yPos+140);}
//if (obj.special == 10){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos, obj.yPos)]; if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos+10, obj.yPos)]; jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos-10, obj.yPos)];}}
if (obj.special == 10){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos, obj.yPos)].playerHandling = HANDLING::SPECIAL;
if(jjDifficulty >= 2){jjObjects[jjAddObject(OBJECT::FENCER, obj.xPos+10, obj.yPos)].playerHandling = HANDLING::SPECIAL;}}
//reset cooldown
obj.age = 180;
if (jjDifficulty == 2){obj.age = 150;}
if (jjDifficulty >= 3){obj.age = 120;}
//select next move
obj.special += 1;
//progress towards next carrot
obj.var[2] = obj.var[2]-1;
//hurt boss
obj.energy -= 1;
}
//loop attack pattern
if (obj.special >= 11){
obj.special = 5;
}
if (obj.var[2] <= 0){
if (jjDifficulty <= 2){jjAddObject(OBJECT::CARROT, obj.xPos, obj.yPos+140);}
if (jjDifficulty >= 3){jjAddObject(OBJECT::SEEKERAMMO3, obj.xPos, obj.yPos+140);}
obj.var[2] = 10;
}
//end boss
if (obj.energy <= 0){obj.bulletHandling = HANDLING::DESTROYBULLET; obj.state = STATE::KILL;}
//turn around
if (obj.xPos <= 495*32){obj.var[0]=1;}
if (obj.xPos >= 506*32){obj.var[0]=0;}
//move
if (obj.var[0] == 0){obj.xPos -=1;}
if (obj.var[0] == 1){obj.xPos +=1;}
//set reticle height
if (obj.special == 0 || obj.special == 3 || obj.special == 5 || obj.special == 7 || obj.special == 8 && obj.special != 9){obj.var[1]=230;}
if (obj.special == 1 || obj.special == 2 || obj.special == 4 || obj.special == 6){obj.var[1]=120;}
if (obj.special == 9 && jjDifficulty >= 2){obj.var[1]=230;}
if (obj.special == 9 && jjDifficulty == 1){obj.var[1]=120;}
if (obj.special == 9 && jjDifficulty == 0){obj.var[1]=9001;}
//display reticle
if (obj.age < 45 && obj.age % 6 <= 2){jjDrawSprite(obj.xPos, obj.yPos+obj.var[1], ANIM::PLUS_RETICLES, 2, 0, 0);}
//attempted work-around for killing bosses, this works about half the time
for (int i = 1; i < jjObjectCount; i++){
jjOBJ@ o = jjObjects[i];
if (o.state == STATE::DONE){jjDeleteObject(o.objectID);}
}
default:
//empty
}
}
Anybody have any ideas on how to fix the problems I've run into?
EDIT: Upon thinking about it further, I'm starting to think the easiest solution would be to disable Jazz's uppercut and Spaz's kick during the boss battle. Any easy way to go about doing that?
EDIT 2: I managed to figure it out on my own, never mind.
__________________
Words. More words. Line. Insert text here. Placeholder. Lorem ipsum dolor sit amet. Uh... I guess I should put something proper here one day.
¯\_(?)_/¯
Last edited by happygreenfrog; Jan 22, 2018 at 12:57 PM.
|