Пример #1
0
void XBoss::run_target(int index)
{
	Object *o = targets[index];
	
	// has this target been destroyed?
	// (we don't really kill the object until the battle is over,
	// to avoid having to deal with dangling pointers).
	if (o->invisible)
		return;
	
	switch(o->state)
	{
		case 0:
			o->flags &= ~FLAG_SHOOTABLE;
			o->frame &= 3;
			o->state = 1;
		break;
		
		case STATE_TARGET_FIRE:
		{
			o->timer = 40 + (index * 10);
			o->flags |= FLAG_SHOOTABLE;
			o->state++;
		}
		case STATE_TARGET_FIRE+1:
		{
			if (--o->timer <= 16)
			{
				// flash shortly before firing
				if (o->timer & 2) o->frame |= 4;
							 else o->frame &= 3;
				
				if (o->timer <= 0)
				{
					o->timer = 40;
					EmFireAngledShot(o, OBJ_GAUDI_FLYING_SHOT, 2, 0x500);
					sound(SND_EM_FIRE);
				}
			}
		}
		break;
	}
	
	// keep appropriate position on internals
	//                               UL          UR         LL         LR
	static const int xoffs[] = { -22 <<CSF,  28 <<CSF, -15 <<CSF,  17 <<CSF };
	static const int yoffs[] = { -16 <<CSF, -16 <<CSF,  14 <<CSF,  14 <<CSF };
	
	o->x = internals->x + xoffs[index];
	o->y = internals->y + yoffs[index];
}
Пример #2
0
// her 3 attacks: black shots, black balls, and summon falling block.
static void run_spells(Object *o)
{
  switch (o->state)
  {
    // flashes for spell...
    // then either fires shots or casts the falling-block spell
    case STATE_FLASH_FOR_SPELL:
    {
      o->flags &= ~FLAG_SHOOTABLE;
      o->xinertia = 0;
      o->yinertia = 0;

      o->timer = 0;
      o->state++;
    }
    case STATE_FLASH_FOR_SPELL + 1:
    {
      o->timer++;
      o->frame = 5 + (o->timer & 1);

      if (o->timer > 30)
      {
        o->timer = 0;
        o->frame = 4;

        if (++o->timer2 >= 3)
        {
          o->state  = STATE_SUMMON_BLOCK;
          o->timer2 = 0;
        }
        else
        {
          o->state = STATE_FIRE_SHOTS;
        }
      }
    }
    break;

    // fire black shots at player
    case STATE_FIRE_SHOTS:
    {
      if ((++o->timer % 6) == 0)
      {
        EmFireAngledShot(o, OBJ_MISERY_SHOT, 4, 0x800);
        NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_FIREBALL);
      }

      if (o->timer > 30)
      {
        o->timer = 0;
        o->state = STATE_TP_AWAY;
      }
    }
    break;

    // summon falling block
    case STATE_SUMMON_BLOCK:
    {
      if (++o->timer == 10)
      {
        int x         = player->x - (8 * CSFI);
        int y         = player->y - (64 * CSFI);
        Object *block = CreateObject(x, y, OBJ_FALLING_BLOCK);
        block->sprite = SPR_BALCONY_BLOCK_LARGE;
        block->dir    = DOWN; // tell block it was spawned by Misery
      }

      if (o->timer > 30)
      {
        o->state = STATE_TP_AWAY;
        o->timer = 0;
      }
    }
    break;

    // summon black balls
    case STATE_SUMMON_BALLS:
    {
      FACEPLAYER;
      o->frame = 4;

      o->timer = 0;
      o->state++;
    }
    case STATE_SUMMON_BALLS + 1:
    {
      o->yinertia += (o->y < o->ymark) ? 0x20 : -0x20;
      LIMITY(0x200);

      if ((++o->timer % 24) == 0)
      {
        CreateObject(o->x, o->y + (4 * CSFI), OBJ_MISERY_BALL);
        NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_FIREBALL);
      }

      if (o->timer > 72)
      {
        o->state = 100;
        o->timer = 0;
      }
    }
    break;
  }
}
Пример #3
0
// used only for purple ones in maze
void ai_critter_shooting_purple(Object *o)
{

	switch(o->state)
	{
		case 0:
			o->state = STATE_IDLE;
			o->damage = CRITTER_DAMAGE;
		case STATE_IDLE:
		{
			o->frame = 0;		// assume not at attention
			if (o->timer >= 8)
			{
				if (pdistlx(96<<CSF) && pdistly2(96<<CSF, 32<<CSF))
				{
					FACEPLAYER;
					
					// close enough to attack?
					if (pdistlx(48<<CSF))
					{
						o->state = STATE_PREPARE_JUMP;
						o->frame = 0;
						o->timer = 0;
					}
					else
					{	// no, but stand at "attention"
						o->frame = 1;
					}
				}
			}
			else
			{
				o->timer++;
			}
			
			// also attack if shot
			if (o->shaketime)
			{
				o->state = STATE_PREPARE_JUMP;
				o->frame = 0;
				o->timer = 0;
			}
		}
		break;
		
		case STATE_PREPARE_JUMP:
		{
			o->frame = 1;
			if (++o->timer > 8)
			{
				FACEPLAYER;
				
				o->state = STATE_JUMP;
				o->timer = 0;
				o->frame = 2;
				
				sound(SND_ENEMY_JUMP);
				o->yinertia = -0x5ff;
			}
		}
		break;
		
		case STATE_JUMP:
		{
			if (o->yinertia > 0x100 || \
				(o->blockd && ++o->timer > 16))		// failsafe
			{
				o->ymark = o->y;
				
				o->state = STATE_HOVER;
				o->frame = 3;
				o->timer = 0;
				
				o->CurlyTargetHere(60, 100);
			}
		}
		break;
		
		case STATE_HOVER:
		{	// sinusoidal hover
			o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
			LIMITY(0x200);
			
			FACEPLAYER;
			ANIMATE(0, 3, 5);
			
			// time to end flight?
			if (++o->timer > 60 || o->blocku)
			{
				o->damage = CRITTER_FALL_DAMAGE;
				o->state = STATE_END_JUMP;
				o->frame = 2;
				break;
			}
			
			if ((o->timer % 4) == 1)
				sound(SND_CRITTER_FLY);
			
			if ((o->timer % 30) == 6)
			{
				EmFireAngledShot(o, OBJ_CRITTER_SHOT, 6, 0x600);
				sound(SND_EM_FIRE);
			}
			
			if (o->blockd)
				o->yinertia = -0x200;
		}
		break;
		
		case STATE_END_JUMP:
		{
			if (o->blockd)
			{
				o->damage = 2;
				o->xinertia = 0;
				o->timer = 0;
				o->frame = 0;
				o->state = 0;
				sound(SND_THUD);
			}
		}
		break;
	}
	
	if (o->state != STATE_HOVER)
	{
		o->yinertia += 0x20;
		LIMITY(0x5ff);
	}
}
Пример #4
0
void ai_minicore(Object *o)
{
	Object *core = o->linkedobject;
	if (!core) { o->Delete(); return; }
	
	switch(o->state)
	{
		case MC_SLEEP:		// idle & mouth closed
			o->frame = 2;
			o->xmark = o->x;
			o->ymark = o->y;
		break;
		
		case MC_THRUST:			// thrust (move to random new pos)
			o->state = MC_THRUST+1;
			o->frame = 2;
			o->timer = 0;
			o->xmark = core->x + (random(-128, 32) << CSF);
			o->ymark = core->y + (random(-64, 64) << CSF);
		case MC_THRUST+1:
			if (++o->timer > 50)
			{
				o->frame = 0;
			}
		break;
		
		case MC_CHARGE_FIRE:			// charging for fire
			o->state = MC_CHARGE_FIRE+1;
			o->timer = 0;
		case MC_CHARGE_FIRE+1:			// flash blue
			o->timer++;
			o->frame = ((o->timer >> 1) & 1);
			if (o->timer > 20)
			{
				o->state = MC_FIRE;
			}
		break;
		
		case MC_FIRE:			// firing
			o->state = MC_FIRE+1;
			o->frame = 2;	// close mouth again
			o->timer = 0;
			o->xmark = o->x + (random(24, 48) << CSF);
			o->ymark = o->y + (random(-4, 4) << CSF);
		case MC_FIRE+1:
			if (++o->timer > 50)
			{
				o->state = MC_FIRED;
				o->frame = 0;
			}
			else if (o->timer==1 || o->timer==3)
			{
				// fire at player at speed (2<<CSF) with 2 degrees of variance
				EmFireAngledShot(o, OBJ_MINICORE_SHOT, 2, 2<<CSF);
				sound(SND_EM_FIRE);
			}
		break;
		
		
		case MC_RETREAT:		// defeated!
			o->state = MC_RETREAT+1;
			o->frame = 2;
			o->xinertia = o->yinertia = 0;
		case MC_RETREAT+1:		// retreat back into the abyss
			o->xinertia += 0x20;
			if (o->x > ((map.xsize*TILE_W)<<CSF) + 0x4000)
			{
				o->Delete();
			}
		break;
	}
	
	if (o->state < MC_RETREAT)
	{
		// jump back when shot
		if (o->shaketime)
		{
			o->xmark += 0x400;
		}
		
		o->x += (o->xmark - o->x) / 16;
		o->y += (o->ymark - o->y) / 16;
	}
	
	// don't let them kill us
	o->hp = 1000;
	
	// invincible when mouth is closed
	if (o->frame != 2)
		o->flags &= ~FLAG_INVULNERABLE;
	else
		o->flags |= FLAG_INVULNERABLE;
}
Пример #5
0
void CoreBoss::Run()
{
bool do_thrust = false;
int i;

	if (!o) return;
	//stat("state = %d", o->state);
	
	switch(o->state)
	{
		case CORE_SLEEP:	break;			// core is asleep
		
		// Core's mouth is closed.
		// Core targets player point but does not update it during the state.
		// This is also the state set via BOA to awaken the core.
		case CORE_CLOSED:
		{
			o->state = CORE_CLOSED+1;
			o->timer = 0;
			
			StopWaterStream();
			o->xmark = player->x;
			o->ymark = player->y;
		}
		case CORE_CLOSED+1:
		{
			// open mouth after 400 ticks
			if (o->timer > 400)
			{
				if (++o->timer2 > 3)
				{	// every 3rd time do gusting left and big core blasts
					o->timer2 = 0;
					o->state = CORE_GUST;
				}
				else
				{
					o->state = CORE_OPEN;
				}
				
				do_thrust = true;
			}
		}
		break;
		
		// Core's mouth is open.
		// Core moves towards player, and updates the position throughout
		// the state (is "aggressive" about seeking him).
		// Core fires ghosties, and curly targets it.
		case CORE_OPEN:
		{
			o->state = CORE_OPEN+1;
			o->timer = 0;
			// gonna open mouth, so save the current HP so we'll
			// know how much damage we've taken this time.
			o->savedhp = o->hp;
		}
		case CORE_OPEN+1:
		{
			o->xmark = player->x;
			o->ymark = player->y;
			
			// must call constantly for red-flashing when hit
			OPEN_MOUTH;
			
			// hint curly to target us
			if ((o->timer % 64) == 1)
			{
				o->CurlyTargetHere();
			}
			
			// spawn ghosties
			if (o->timer < 200)
			{
				if ((o->timer % 20)==0)
				{
					CreateObject(o->x + (random(-48, -16) << CSF), \
						     	 o->y + (random(-64, 64) << CSF), \
							 	 OBJ_CORE_GHOSTIE);
				}
			}
			
			// close mouth when 400 ticks have passed or we've taken more than 200 damage
			if (o->timer > 400 || (o->savedhp - o->hp) >= 200)
			{
				o->state = CORE_CLOSED;
				CLOSE_MOUTH;
				do_thrust = true;
			}
		}
		break;
		
		
		case CORE_GUST:
		{
			o->state = CORE_GUST+1;
			o->timer = 0;
			
			StartWaterStream();
		}
		case CORE_GUST+1:
		{
			// spawn water droplet effects and push player
			Object *droplet = CreateObject(player->x + ((random(-50, 150)<<CSF)*2), \
								   		   player->y + (random(-160, 160)<<CSF),
								   		   OBJ_FAN_DROPLET);
			droplet->dir = LEFT;
			player->xinertia -= 0x20;
			
			OPEN_MOUTH;
			
			// spawn the big white blasts
			if (o->timer==300 || o->timer==350 || o->timer==400)
			{
				EmFireAngledShot(pieces[CFRONT], OBJ_CORE_BLAST, 0, 3<<CSF);
				sound(SND_LIGHTNING_STRIKE);
			}
			
			if (o->timer > 400)
			{
				o->state = CORE_CLOSED;
				CLOSE_MOUTH;
				do_thrust = true;
			}
		}
		break;
		
		
		case 500:		// defeated!!
		{
			StopWaterStream();
			map.wlforcestate = WL_CALM;
			
			o->state = 501;
			o->timer = 0;
			o->xinertia = o->yinertia = 0;
			game.curlytarget.timeleft = 0;
			
			CLOSE_MOUTH;
			
			game.quaketime = 20;
			SmokeXY(pieces[CBACK]->x, pieces[CBACK]->CenterY(), 20, 128, 64);
			
			// tell all the MC's to retreat
			for(i=0;i<5;i++)
			{
				pieces[i]->flags &= ~(FLAG_SHOOTABLE & FLAG_INVULNERABLE);
				pieces[i]->state = MC_RETREAT;
			}
		}
		case 501:
		{
			o->timer++;
			if ((o->timer & 0x0f) != 0)
			{
				SmokeXY(pieces[CBACK]->x, pieces[CBACK]->CenterY(), 1, 64, 32);
			}
			
			if (o->timer & 2)
				o->x -= (1 << CSF);
			else
				o->x += (1 << CSF);
			
			#define CORE_DEATH_TARGET_X		0x7a000
			#define CORE_DEATH_TARGET_Y		0x16000
			o->xinertia += (o->x > CORE_DEATH_TARGET_X) ? -0x80 : 0x80;
			o->yinertia += (o->y > CORE_DEATH_TARGET_Y) ? -0x80 : 0x80;
		}
		break;
		
		case 600:			// teleported away by Misery
		{
			o->xinertia = 0;
			o->yinertia = 0;
			o->state++;
			//sound(SND_TELEPORT);
			
			pieces[CFRONT]->clip_enable = pieces[CBACK]->clip_enable = 1;
			o->timer = sprites[pieces[CFRONT]->sprite].h;
		}
		case 601:
		{
			pieces[CFRONT]->display_xoff = pieces[CBACK]->display_xoff = random(-8, 8);
			
			pieces[CFRONT]->clipy2 = o->timer;
			pieces[CBACK]->clipy2 = o->timer;
			
			if (--o->timer < 0)
			{
				pieces[CFRONT]->invisible = true;
				pieces[CBACK]->invisible = true;
				
				// restore status bars
				game.stageboss.object = NULL;
				game.bossbar.object = NULL;
				o->Delete(); o = NULL;
				return;
			}
		}
		break;
	}
	
	
	if (do_thrust)
	{
		// tell all the minicores to jump to a new position
		for(i=0;i<5;i++)
		{
			pieces[i]->state = MC_THRUST;
		}
		
		quake(20);
		sound(SND_CORE_THRUST);
	}
	
	
	// fire the minicores in any awake non-dead state
	if (o->state >= CORE_CLOSED && o->state < 500)
	{
		o->timer++;
		
		// fire off each minicore sequentially...
		switch(o->timer)
		{
			case 80+0:   pieces[0]->state = MC_CHARGE_FIRE; break;
			case 80+30:  pieces[1]->state = MC_CHARGE_FIRE; break;
			case 80+60:  pieces[2]->state = MC_CHARGE_FIRE; break;
			case 80+90:  pieces[3]->state = MC_CHARGE_FIRE; break;
			case 80+120: pieces[4]->state = MC_CHARGE_FIRE; break;
		}
		
		// move main core towards a spot in front of target
		o->xinertia += (o->x > (o->xmark + (160<<CSF))) ? -4 : 4;
		o->yinertia += (o->y > o->ymark - (o->Height() / 2)) ? -4 : 4;
	}
	
	// set up our shootable status--you never actually hit the core (CFRONT),
	// but if it's mouth is open, make us, the invisible controller object, shootable.
	if (pieces[CFRONT]->frame==2)
	{
		o->flags &= ~FLAG_SHOOTABLE;
		pieces[CFRONT]->flags |= FLAG_INVULNERABLE;
	}
	else
	{
		o->flags |= FLAG_SHOOTABLE;
		pieces[CFRONT]->flags &= ~FLAG_INVULNERABLE;
	}
	
	LIMITX(0x80);
	LIMITY(0x80);
}
Пример #6
0
void ai_red_demon(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			o->xmark = o->x;
			o->xinertia = 0;
			o->frame = 0;
			o->state = 1;
		}
		case 1:
		{
			ANIMATE(20, 0, 1);
			FACEPLAYER;
		}
		break;
		
		case 10:	// prepare to jump
		{
			o->flags |= FLAG_SHOOTABLE;
			o->state = 11;
			o->frame = 3;
			o->timer = 0;
		}
		case 11:
		{
			switch(++o->timer)
			{
				case 30:
				case 40:
				case 50:
				{
					o->frame = 4;
					EmFireAngledShot(o, OBJ_RED_DEMON_SHOT, 0, 0x800);
					sound(SND_EM_FIRE);
				}
				break;
				
				case 34:
				case 44:
				case 54:
				{
					o->frame = 3;
				}
				break;
				
				case 61:
				{
					o->state = 20;
					o->timer = 0;
					o->frame = 2;
				}
				break;
			}
		}
		break;
		
		case 20:	// pause before jump
		{
			if (++o->timer > 20)
			{
				o->state = 21;
				o->timer = 0;
				o->frame = 5;
				
				o->yinertia = -0x5ff;
				o->xinertia = (o->CenterX() < player->CenterX()) ? 0x100 : -0x100;
			}
		}
		break;
		
		case 21:	// in air
		{
			switch(++o->timer)
			{
				case 30:
				case 40:
				case 50:
				{
					o->frame = 6;
					EmFireAngledShot(o, OBJ_RED_DEMON_SHOT, 0, 0x800);
					sound(SND_EM_FIRE);
				}
				break;
				
				case 34:
				case 44:
				{
					o->frame = 5;
				}
				break;
				
				case 54:
				{
					o->frame = 7;
				}
				break;
			}
			
			if (o->blockd && o->yinertia >= 0)
			{
				quake(10);
				o->state = 22;
				o->timer = 0;
				o->frame = 2;
			}
		}
		break;
		
		case 22:	// landed
		{
			o->xinertia /= 2;
			
			if (++o->timer > 22)
			{
				o->state = 10;
			}
		}
		break;
		
		// defeated/turned to stone (set by script)
		case 50:
		{
			o->flags &= ~FLAG_SHOOTABLE;
			o->damage = 0;
			
			if (o->blockd)
			{
				o->state = 51;
				o->frame = 2;
				
				game.quaketime = 10;
				SmokeClouds(o, 12, 4, 4);
				o->SpawnXP(19);
				
				sound(SND_BIG_CRASH);
				
				// needed to prevent status bars from not disappearing
				game.bossbar.object = NULL;
			}
		}
		break;
		
		case 51:
		{
			o->xinertia *= 7;
			o->xinertia /= 8;
			
			o->frame = 8;
		}
		break;
	}
	
	if (o->state < 50)
	{
		FACEPLAYER;
	}
	
	o->yinertia += 0x20;
	LIMITY(0x5ff);
}