View Single Post
happygreenfrog happygreenfrog's Avatar

JCF Member

Joined: Jan 1970

Posts: 23

happygreenfrog has disabled reputation

Jan 22, 2018, 08:11 AM
happygreenfrog is offline
Reply With Quote
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 01:57 PM.