Esempio n. 1
0
// cutscene igor
void ai_npc_igor(Object *o)
{
	switch(o->state)
	{
		case 0:		// init, standing/panting
			o->xinertia = 0;
			o->frame = 0;
			o->animtimer = 0;
			o->state = 1;
		case 1:
			ANIMATE(5, 0, 1);
		break;
		
		case 2:		// walking
			o->state = 3;
			o->frame = 2;
			o->animtimer = 0;
		case 3:
			ANIMATE(3, 2, 5);
			XMOVE(0x200);
		break;
		
		case 4:		// punch
			o->xinertia = 0;
			o->state = 5;
			o->timer = 0;
		case 5:
			o->frame = 6;
			if (++o->timer > 10)
			{
				o->timer = 0;
				o->state = 6;
				sound(SND_EXPL_SMALL);
			}
		break;
		case 6:
			o->frame = 7;
			if (++o->timer > 8)
			{
				o->state = 0;
				o->frame = 0;
			}
		break;
		
		case 7:
			o->state = 1;
		break;
	}
	
	o->yinertia += 0x40;
	LIMITY(0x5FF);
}
Esempio n. 2
0
static bool run_bute_defeated(Object *o, int hp)
{
        if (o->hp <= (1000 - hp)) {
                if (o->type == OBJ_MESA) {
                        o->ChangeType(OBJ_MESA_DYING);
                } else {
                        o->x -= (4 << CSF);
                        o->y -= (4 << CSF);
                        o->ChangeType(OBJ_BUTE_DYING);

                        sound(SND_ENEMY_SQUEAK);
                        XMOVE(-0x100);
                }

                ai_bute_dying(o);
                return 1;
        }

        return 0;
}
// white sparky thing that moves along floor throwing out bones,
// spawned he hits the ground.
// similar to the red smoke-spawning ones from Undead Core.
void ai_ballos_bone_spawner(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			sound(SND_MISSILE_HIT);
			o->state = 1;
			
			XMOVE(0x400);
		}
		case 1:
		{
			ANIMATE(1, 0, 2);
			o->timer++;
			
			if ((o->timer % 6) == 1)
			{
				int xi = (random(4, 16) << CSF) / 8;
				
				if (o->dir == LEFT)
					xi = -xi;
				
				CreateObject(o->x, o->y, OBJ_BALLOS_BONE, xi, -0x400);
				sound(SND_BLOCK_DESTROY);
			}
			
			if ((o->blockl && o->xinertia < 0) || \
				(o->blockr && o->xinertia > 0))
			{
				o->Delete();
			}
		}
		break;
	}
	
}
Esempio n. 4
0
void ai_red_bat(Object *o)
{
	ANIMATE(1, 0, 2);
	
	switch(o->state)
	{
		case 0:
		{
			o->state = 1;
			o->ymark = o->y;
			o->timer = random(0, 50);
		}
		case 1:
		{
			if (--o->timer < 0)
			{
				o->state = 2;
				o->yinertia = 0x400;
			}
			else break;
		}
		case 2:
		{
			o->yinertia += (o->y < o->ymark) ? 0x10 : -0x10;
			LIMITY(0x300);
			XMOVE(0x100);
		}
		break;
	}
	
	if (o->x < 0 || o->x > (map.xsize * TILE_W) << CSF)
	{
		effect(o->CenterX(), o->CenterY(), EFFECT_BOOMFLASH);
		o->Delete();
	}
}
Esempio n. 5
0
// this is her phasy teleport out/teleport in effect
// it's a 2-dir interlaced picture of her with each dir
// containing only half the lines. We spawn two objects
// in opposite dirs and then separate them.
void ai_misery_phase(Object *o)
{
  XMOVE(0x400);
  if (++o->timer >= 8)
    o->Delete();
}
Esempio n. 6
0
void ai_ma_pignon(Object *o)
{
	/*debug("state: %d", o->state);
	debug("timer: %d", o->timer);
	debug("timer2: %d", o->timer2);
	debug("timer3: %d", o->timer3);
	debug("xinertia: %d", o->xinertia);
	debug("yinertia: %d", o->yinertia);
	debug("frame: %d", o->frame);
	*/
	
	switch(o->state)
	{
		case 0:
		{
			o->SnapToGround();
			o->state = 1;
		}
		case 1:
		{
			FACEPLAYER;
			o->frame = 0;
			randblink(o);
		}
		break;
		
		case MP_Fight_Start:		// set by script
		{
			o->state = MP_BaseState;
			o->timer = 0;
			o->timer2 = 0;
			o->flags |= FLAG_SHOOTABLE;
		}
		case MP_BaseState:
		{
			FACEPLAYER;
			o->damage = 1;
			o->frame = 0;
			
			if (++o->timer > 4)
			{
				o->timer = 0;
				o->state = MP_Jump;
				
				if (++o->timer3 > 12)
				{
					o->timer3 = 0;
					o->state = MP_CloneAttack;
				}
			}
		}
		break;
		
		case MP_Jump:		// pause a moment and jump
		{
			o->frame = 2;
			if (++o->timer > 4)
			{
				o->state = MP_In_Air;
				o->frame = 3;
				
				o->xinertia = random(-0x400, 0x400);
				o->yinertia = -0x800;
				
				sound(SND_ENEMY_JUMP);
				o->timer2++;
			}
		}
		break;
		
		case MP_In_Air:		// jumping or falling after clone attack
		{
			o->yinertia += 0x80;
			
			// for when falling back onscreen after clone attack
			if (o->y > (8 * TILE_H) << CSF)
				o->flags &= ~FLAG_IGNORE_SOLID;
			else
				o->blockd = false;
			
			// bounce off walls
			if ((o->blockl && o->xinertia < 0) || \
				(o->blockr && o->xinertia > 0))
			{
				o->xinertia = -o->xinertia;
			}
			
			FACEPLAYER;
			
			// select frame
			if (o->yinertia < -0x200)
			{
				o->frame = 3;
			}
			else if (o->yinertia > 0x200)
			{
				o->frame = 4;
			}
			else
			{
				o->frame = 0;
			}
			
			if (o->blockd && o->yinertia > 0)
			{
				o->state = MP_Landed;
				o->timer = 0;
				o->frame = 2;
				o->xinertia = 0;
			}
			
			if (o->timer2 > 4)
			{
				if (player->y < (o->y + 0x800))
				{
					o->state = MP_ChargeAttack;
					o->timer = 0;
					o->xinertia = 0;
					o->yinertia = 0;
				}
			}
		}
		break;
		
		case MP_Landed:
		{
			o->frame = 2;
			if (++o->timer > 4)
			{
				o->state = MP_BaseState;
			}
		}
		break;
		
		
		case MP_ChargeAttack:		// charge attack
		{
			o->frame = 5;
			if (++o->timer > 10)
			{
				o->state = MP_ChargeAttack+1;
				o->frame = 6;
				
				XMOVE(0x5ff);
				sound(SND_FUNNY_EXPLODE);
				
				o->flags &= ~FLAG_SHOOTABLE;
				o->flags |= FLAG_INVULNERABLE;
				o->damage = 10;
			}
		}
		break;
		case MP_ChargeAttack+1:		// in-air during charge attack
		{
			ANIMATE(0, 6, 7);
			
			if ((o->xinertia < 0 && o->blockl) || \
				(o->xinertia > 0 && o->blockr))
			{
				o->state = MP_Hit_Wall;
			}
		}
		break;
		
		case MP_Hit_Wall:		// hit wall
		{
			o->state++;
			o->timer = 0;
			quake(16);
		}
		case MP_Hit_Wall+1:
		{
			o->damage = 4;
			ANIMATE(0, 6, 7);
			
			if ((++o->timer % 6) == 0)
			{
				int x = (random(4, 16) * TILE_W) << CSF;
				CreateObject(x, (16 << CSF), OBJ_MA_PIGNON_ROCK);
			}
			
			if (o->timer > 30)
			{
				o->timer2 = 0;
				o->state = MP_In_Air;
				
				o->flags |= FLAG_SHOOTABLE;
				o->flags &= ~FLAG_INVULNERABLE;
				
				o->damage = 3;
			}
		}
		break;
		
		
		case MP_CloneAttack:	// begin clone-attack sequence
		{
			o->state++;
			o->frame = 9;
			FACEPLAYER;
		}
		case MP_CloneAttack+1:	// walk at player before attack
		{
			ANIMATE(0, 9, 11);
			
			XMOVE(0x400);
			if (pdistlx(3 << CSF))
			{
				o->state = MP_Fly_Up;
				o->timer = 0;
				o->frame = 2;
				o->xinertia = 0;
			}
		}
		break;
		
		case MP_Fly_Up:		// jump and fly up for clone attack
		{
			o->frame = 2;
			if (++o->timer > 4)
			{
				o->state++;
				o->frame = 12;
				o->yinertia = -0x800;
				sound(SND_FUNNY_EXPLODE);
				
				o->flags |= FLAG_IGNORE_SOLID;
				o->flags &= ~FLAG_SHOOTABLE;
				o->flags |= FLAG_INVULNERABLE;
				
				o->damage = 10;
			}
		}
		break;
		case MP_Fly_Up+1:		// flying up
		{
			ANIMATE(0, 12, 13);
			
			if (o->y < (16<<CSF))
				o->state = MP_Spawn_Clones;
		}
		break;
		
		case MP_Spawn_Clones:	// offscreen, spawning clones
		{
			o->yinertia = 0;
			o->state++;
			o->timer = 0;
			
			quake(10);
		}
		case MP_Spawn_Clones+1:
		{
			ANIMATE(0, 12, 13);
			
			if ((++o->timer % 6) == 0)
			{
				int x = (random(4, 16) * TILE_W) << CSF;
				CreateObject(x, (16 << CSF), OBJ_MA_PIGNON_CLONE);
			}
			
			if (o->timer > 30)
			{
				o->timer2 = 0;
				o->state = MP_In_Air;	// fall back down to ground
				
				o->flags |= FLAG_SHOOTABLE;
				o->flags &= ~FLAG_INVULNERABLE;
			}
		}
		break;
		
		case MP_Defeated:			// defeated -- set by script
		{
			KillObjectsOfType(OBJ_MA_PIGNON_CLONE);
			o->flags &= ~FLAG_SHOOTABLE;
			o->state++;
			o->timer = 0;
			o->frame = 8;
			o->damage = 0;
		}
		case MP_Defeated+1:
		{
			o->yinertia += 0x20;
			if (o->blockd)
			{
				o->xinertia *= 7;
				o->xinertia /= 8;
			}
			
			o->display_xoff = (++o->timer & 1);
		}
		break;
	}
	
	// ma pignon is invulnerable to missiles and Blade.
	if (o->state >= MP_Fight_Start && o->state < MP_Defeated)
	{
		// ....he's invulnerable anyway during these two states so don't mess with that.
		if (o->state != MP_ChargeAttack+1 && o->state != MP_Fly_Up+1)
		{
			bool found_weapons = false;
			if (o->type != OBJ_MA_PIGNON_CLONE)
			{
				Object *c;
				FOREACH_OBJECT(c)
				{
					if (c->type == OBJ_MISSILE_SHOT || \
						c->type == OBJ_SUPERMISSILE_SHOT || \
						c->type == OBJ_MISSILE_BOOM_SPAWNER || \
						c->type == OBJ_BLADE12_SHOT || \
						c->type == OBJ_BLADE3_SHOT || \
						c->type == OBJ_BLADE_SLASH)
					{
						found_weapons = true;
						break;
					}
				}
			}
			
			if (found_weapons)
			{
				o->flags &= ~FLAG_SHOOTABLE;
				o->flags |= FLAG_INVULNERABLE;
			}
			else
			{
				o->flags |= FLAG_SHOOTABLE;
				o->flags &= ~FLAG_INVULNERABLE;
			}
		}
Esempio n. 7
0
void ai_npc_sue(Object *o)
{
	switch(o->state)
	{
		case 0:		// stand and blink
			o->timer = 0;
			o->frame = 0;
			o->xinertia = 0;
			o->sue.carried_by = NULL;
			randblink(o, 1, 4);
		break;
		
		case 3:		// walking
		case 4:		// walking
		case 5:		// face away
			ai_generic_npc(o);
		break;
		
		// got punched by Igor
		case 6:
			o->state = 7;
			o->frame = 7;
			o->timer = 0;
			sound(SND_ENEMY_SQUEAK);
		case 7:
			if (++o->timer > 10)
				o->state = 0;
		break;
		
		// got punched extra hard by Igor
		// flys through air backwards and crashes
		case 8:
			o->state = 9;
			o->frame = 7;
			o->timer = 0;
			sound(SND_ENEMY_SQUEAK);
			
			o->yinertia = -0x200;
			XMOVE(-0x400);
		case 9:
			if (++o->timer > 3 && o->blockd)
			{
				o->state = 10;
				o->dir ^= 1;
			}
		break;
		case 10:
			o->xinertia = 0;
			o->frame = 8;
		break;
		
		// punching the air (when she tells Igor "I'm not afraid of you!")
		case 11:
			o->state = 12;
			o->timer = 0;
			o->animframe = 0;
			o->animtimer = 0;
		case 12:
		{
			const static int punchframes[] = { 10, 0 };
			o->animate_seq(8, punchframes, 2);
		}
		break;
		
		// picked up & carried away by Igor
		case 13:
			o->frame = 11;
			o->xinertia = 0;
			o->yinertia = 0;
			o->state = 14;
			
			// find Igor
			o->sue.carried_by = FindObjectByID2(501);
			if (!o->sue.carried_by)
				NX_ERR("-- Could not find entity carrying Sue (ID 501)\n");
		case 14:	// being carried--see aftermove routine
			o->frame = 9;
		break;
		
		// spawn red crystal and call it to us (Undead Core intro)
		case 15:
		{
			o->PushBehind(dr_create_red_crystal(o->x+(128<<CSF), o->y));
			
			o->state = 16;
			o->xinertia = 0;
			o->frame = 0;
		}
		case 16:
		{
			crystal_xmark = o->x - (18<<CSF);
			crystal_ymark = o->y - (8<<CSF);
		}
		break;
		case 17:	// look up (still followed by red crystal)
		{
			o->xinertia = 0;
			o->frame = 12;
			
			crystal_xmark = o->x;
			crystal_ymark = o->y - (8<<CSF);
		}
		break;
		
		// run away from DOCTOR_GHOST and hide behind player
		case 20:
		{
			o->state = 21;
			o->frame = 2;
			o->animtimer = 0;
		}
		case 21:
		{
			ANIMATE(2, 2, 5);
			XMOVE(0x400);
			
			if (o->x < player->x - (8<<CSF))
			{
				o->dir = RIGHT;
				o->state = 0;
			}
		}
		break;
		
		// run, during "we've got to get out of here" post-undead core cutscene.
		case 30:
		{
			o->state = 31;
			o->frame = 2;
			o->animtimer = 0;
		}
		case 31:
		{
			ANIMATE(2, 2, 5);
			XMOVE(0x400);
		}
		break;
		
		case 40:	// she jumps off the island
		{
			o->state = 41;
			o->frame = 9;
			o->yinertia = -0x400;
		}
		break;
		
		/*default:
			NX_ERR("-- Sue entered unhandled state %d (0x%02x)\n", o->state, o->state);
			exit(1);*/
	}
	
	o->yinertia += 0x40;
	LIMITX(0x400);
	LIMITY(0x5ff);
}
Esempio n. 8
0
void ai_toroko(Object *o)
{
	switch(o->state)
	{
		case 0:		// stand and blink
			o->frame = 0;
			o->xinertia = 0;
			randblink(o, 1, 4);
		break;
		
		case 3:		// run away!!
			o->state = 4;
			o->frame = 1;
			o->animtimer = 0;
		case 4:
			ANIMATE(2, 1, 4);
			
			if (o->blockl) { o->dir = RIGHT; o->xinertia = 0x200; }
			if (o->blockr) { o->dir = LEFT; o->xinertia = -0x200; }
			
			XMOVE(0x400);
		break;
		
		case 6:		// hop and run away!!
			o->state = 7;
			o->frame = 1;
			o->animtimer = 0;
			o->yinertia = -0x400;
			o->toro.left_ground = false;
		case 7:
			ANIMATE(2, 1, 4);
			XMOVE(0x100);
			
			if (!o->toro.left_ground)
			{
				if (!o->blockd)
					o->toro.left_ground = true;
			}
			else
			{
				if (o->blockd)
				{
					o->toro.left_ground = false;
					o->state = 3;
				}
			}
		break;
		
		// small hop straight up/down from Balrog
		// shaking the ground, used in Shack
		case 8:
			o->frame = 1;
			o->timer = 0;
			o->state = 9;
			o->yinertia = -0x200;
			o->toro.left_ground = false;
		case 9:
		{
			if (!o->toro.left_ground)
			{
				if (!o->blockd)
					o->toro.left_ground = true;
			}
			else
			{
				if (o->blockd)
				{
					o->toro.left_ground = false;
					o->state = 0;
				}
			}
		}
		break;
		
		case 10:	// eeks and falls down
			o->state = 11;
			o->frame = 5;
			o->yinertia = -(2 << CSF);
			sound(SND_ENEMY_SQUEAK);
			XMOVE(0x100);
		break;
		case 11:	// falling down
			if (o->blockd)
			{
				o->state = 12;
				o->frame = 6;
				o->flags |= FLAG_SCRIPTONACTIVATE;
				o->xinertia = 0;
			}
		break;
	}
	
	o->yinertia += 0x40;
	LIMITX(0x400);
	LIMITY(0x5ff);
}
Esempio n. 9
0
// regular NPC curly
void ai_curly(Object *o)
{
	switch(o->state)
	{
		case 0:							// state 0: stand and do nothing
			o->frame = 0;
			o->flags |= FLAG_SCRIPTONACTIVATE;	// needed for after Almond battle
		case 1:
			// important that state 1 does not change look-away frame for Drain cutscene
			if (o->frame != 12) o->frame = 0;
			o->xinertia = 0;
		break;
		
		case 3:							// state 3: walk forward
		case 10:						// state 10: walk to player and stop
		{
			if (o->state == 10) FACEPLAYER;
			o->state++;
			o->animtimer = 0;
			o->frame = 0;
		}
		case 4:
		case 11:
		{
			if (o->state == 11 && pdistlx(20<<CSF))
			{
				o->state = 0;
				break;
			}
			
			ANIMATE(5, 0, 3);
			if (!o->blockd) o->frame = 3;
			
			XMOVE(0x200);
		}
		break;
		
		// state 5: curly makes a "kaboom", then looks sad.
		case 5:
			o->state = 6;
			SmokeClouds(o, 8, 0, 0);
		case 6:
			o->frame = 16;
		break;
		
		case 20:			// face away
			o->xinertia = 0;
			o->frame = 12;
		break;
		
		case 21:			// look up
			o->xinertia = 0;
			o->frame = 4;
		break;
		
		case 30:			// state 30: curly goes flying through the air and is knocked out
		{
			o->state = 31;
			o->frame = 14;
			o->timer2 = 0;
			o->yinertia = -0x400;
			XMOVE(-0x200);
		}
		case 31:
		{
			if (o->blockd && o->yinertia >= 0)
				o->state = 32;
			else
				break;
		}
		case 32:			// state 32: curly is laying knocked out
		{
			o->frame = 15;
			o->xinertia = 0;
		}
		break;
		
		// walk backwards from collapsing wall during final cutscene
		case 70:
		{
			o->state = 71;
			o->timer = 0;
			o->frame = 1;
			o->animtimer = 0;
		}
		case 71:
		{
			XMOVE(-0x100);
			ANIMATE(8, 0, 3);
		}
		break;
	}
	
	o->yinertia += 0x40;
	LIMITY(0x5ff);
}
Esempio n. 10
0
void ai_balrog(Object *o)
{
bool fall = true;

	// he is greenish when he first appears in Gum Room
	if (DoesCurrentStageUseSpriteset(NPCSET_FROG))
		o->sprite = SPR_BALROG_GREEN;
	
	switch(o->state)
	{
		case 0:
		{
			o->flags &= ~FLAG_IGNORE_SOLID;
			o->xinertia = 0;
			o->balrog.smoking = false;
			
			o->frame = 0;
			randblink(o, 4, 8);
		}
		break;
		
		case 10:		// he jumps and flys away
			o->xinertia = 0;
			o->frame = 2;
			o->timer = 0;
			o->state++;
		case 11:
		{
			if (++o->timer <= 20) break;
			
			o->state++;
			o->yinertia = -0x800;
			o->flags |= FLAG_IGNORE_SOLID;
		}
		case 12:
		{
			fall = false;
			o->frame = 3;
			o->yinertia -= 0x10;
			if (o->y < 0)
			{
				o->Delete();
				sound(SND_QUAKE);
				game.quaketime = 30;
			}
		}
		break;
		
		// he looks shocked and shakes, then flys away
		// used when he is "hit by something"
		case 20:
		{
			o->state = 21;
			o->frame = 5;
			o->xinertia = 0;
			o->timer = o->timer2 = 0;
			SmokeClouds(o, 4, 8, 8);
			sound(SND_BIG_CRASH);
			o->balrog.smoking = 1;
		}
		case 21:
		{
			o->timer2++;
			o->x += ((o->timer2 >> 1) & 1) ? (1<<CSF) : -(1<<CSF);
			
			if (++o->timer > 100)
				o->state = 10;
			
			o->yinertia += 0x20;
			LIMITY(0x5ff);
		}
		break;
		
		case 30:	// he smiles for a moment
			o->frame = 6;
			o->timer = 0;
			o->state = 31;
		case 31: if (++o->timer > 100) o->state = o->frame = 0;
		break;
		
		// flashing white (spell casted on him)
		// this only works in Gum Room before balfrog fight, as the normal
		// non-greenish spritesheet doesn't include the required frame.
		case 40:
			o->state = 41;
			o->animtimer = 0;
			o->animframe = 0;
		case 41:
		{
			static const int flash_seq[] = { 5, 7 };
			o->animate_seq(1, flash_seq, 2);
		}
		break;
		case 42:
			o->timer = 0;
			o->state = 43;
		case 43:
			// flashing visibility
			// (transforming into Balfrog stage boss;
			//	our flashing is interlaced with his)
			o->timer++;
			o->invisible = (o->timer & 2) ? false : true;
		break;
		
		case 50:	// he faces away
			o->frame = 8;
			o->xinertia = 0;
		break;
		
		case 60:	// he walks
			o->state = 61;
			balrog_walk_init(o);
		case 61:
		{
			balrog_walk_animation(o);
			XMOVE(0x200);
		}
		break;
		
		// he is teleported away (looking distressed)
		// this is when he is sent to Labyrinth at end of Sand Zone
		case 70:
			o->xinertia = 0;
			o->timer = 0;
			o->frame = 7;
			o->state++;
		case 71:
			if (DoTeleportOut(o, 2))
				o->Delete();
		break;
		
		case 80:	// hands up and shakes
			o->frame = 5;
			o->state = 81;
		case 81:
		{
			if (++o->timer & 2)
				o->x += (1 << CSF);
			else
				o->x -= (1 << CSF);
		}
		break;
		
		// fly up and lift Curly & PNPC
		// (post-Ballos ending scene)
		case 100:
		{
			o->state = 101;
			o->timer = 0;
			o->frame = 2;	// prepare for jump
		}
		case 101:
		{
			if (++o->timer > 20)
			{
				o->state = 102;
				o->timer = 0;
				o->frame = 3;	// fly up
				
				DeleteObjectsOfType(OBJ_NPC_PLAYER);
				DeleteObjectsOfType(OBJ_CURLY);
				
				CreateObject(0, 0, OBJ_BALROG_PASSENGER, 0, 0, LEFT)->linkedobject = o;
				CreateObject(0, 0, OBJ_BALROG_PASSENGER, 0, 0, RIGHT)->linkedobject = o;
				
				o->yinertia = -0x800;
				o->flags |= FLAG_IGNORE_SOLID;	// so can fly through ceiling
				fall = false;
			}
		}
		break;
		case 102:	// flying up during escape seq
		{
			fall = false;
			
			// bust through ceiling
			int y = ((o->y + (4<<CSF)) >> CSF) / TILE_H;
			if (y < 35 && y >= 0)
			{
				int x = (o->CenterX() >> CSF) / TILE_W;
				
				if (map.tiles[x][y] != 0)
				{
					// smoke needs to go at the bottom of z-order or you can't
					// see any of the characters through all the smoke.
					map_ChangeTileWithSmoke(x, y, 0, 4, false, lowestobject);
					map_ChangeTileWithSmoke(x-1, y, 0, 4, false, lowestobject);
					map_ChangeTileWithSmoke(x+1, y, 0, 4, false, lowestobject);
					
					megaquake(10, 0);
					sound(SND_MISSILE_HIT);
				}
			}
			
			if (o->Bottom() < -(20<<CSF))
			{
				quake(30, 0);
				o->Delete();
			}
		}
		break;
		
		case 500:	// used during Balfrog death scene
		{
			fall = false;
		}
		break;
	}
Esempio n. 11
0
// boss-fight igor
void ai_boss_igor(Object *o)
{
	enum
	{
		STATE_INIT = 0,
		STATE_STAND,
		
		STATE_BEGIN_ATTACK,
		STATE_WALK,
		
		STATE_JUMPING,
		STATE_LANDED,
		
		STATE_PUNCH,
		STATE_PUNCH_2,
		STATE_PUNCH_3,
		
		STATE_MOUTH_BLAST,
		STATE_MOUTH_BLAST_2
	};
	
	switch(o->state)
	{
		case STATE_INIT:
		{
			o->damage = 0;
			o->xinertia = 0;
			
			o->state = STATE_STAND;
			o->frame = 0;
			o->animtimer = 0;
		}
		case STATE_STAND:
		{
			ANIMATE(5, 0, 1);
			if (++o->timer > 50)
			{
				o->state = STATE_BEGIN_ATTACK;
			}
		}
		break;
		
		case STATE_BEGIN_ATTACK:
		{
			o->state = STATE_WALK;
			o->frame = 2;
			o->animtimer = 0;
			o->timer = 0;
			
			FACEPLAYER;
			o->igor.fireattack = false;
			
			// when health is less than halfway, then use
			// the mouth blast attack every third time.
			if (++o->timer2 >= 3 && \
				o->hp <= (objprop[o->type].initial_hp / 2))
			{
				o->timer2 = 0;
				o->igor.fireattack = true;
				o->dir ^= 1;	// walk away from player
			}
			
		}	// fall thru
		case STATE_WALK:
		{
			ANIMATE(3, 2, 5);
			XMOVE(0x200);
			
			if (o->igor.fireattack)
			{	// begin mouth-blast attack
				if (++o->timer > 16)
				{
					o->state = STATE_MOUTH_BLAST;
					o->xinertia = 0;
					o->frame = 10;
				}
			}
			else
			{
				if (o->dir == LEFT)
				{
					if (o->x <= player->x + player->Width())
						o->state = STATE_PUNCH;
				}
				else
				{
					if (o->x + o->Width() >= player->x)
						o->state = STATE_PUNCH;
				}
				
				// if we don't reach him after a while, do a jump
				if (++o->timer > 50)
				{
					o->frame = 10;
					o->yinertia = -0x400;
					o->state = STATE_JUMPING;
					o->timer = 0;
					
					o->xinertia *= 2;
					o->xinertia /= 3;
					
					o->damage = 2;
				}
			}
		}
		break;
		
		case STATE_PUNCH:
		{
			o->xinertia = 0;
			
			o->state = STATE_PUNCH_2;
			o->frame = 6;
			o->timer = 0;
		}
		case STATE_PUNCH_2:
		{
			if (++o->timer > 12)
			{
				sound(SND_EXPL_SMALL);
				
				// sprite appears identical, but has a wider bounding box.
				o->sprite = SPR_IGOR_PUNCHING;
				o->damage = 5;
				
				o->state = STATE_PUNCH_3;
				o->frame = 7;
				o->timer = 0;
			}
		}
		break;
		case STATE_PUNCH_3:
		{
			if (++o->timer > 10)
			{
				o->state = STATE_INIT;
				o->frame = 0;
				o->damage = 0;
				
				// return to normal-size bounding box
				o->sprite = SPR_IGOR;
			}
		}
		break;
		
		case STATE_JUMPING:
		{
			if (o->blockd)
			{
				sound(SND_QUAKE);
				SmokeSide(o, 4, DOWN);
				
				o->state = STATE_LANDED;
				o->frame = 11;
				o->timer = 0;
			}
		}
		break;
		
		case STATE_LANDED:
		{
			o->xinertia = 0;
			if (++o->timer > 10)
			{
				o->state = STATE_INIT;
				o->frame = 0;
				o->damage = 0;
			}
		}
		break;
		
		case STATE_MOUTH_BLAST:
		{
			FACEPLAYER;
			o->timer = 0;
			o->state++;
		}
		case STATE_MOUTH_BLAST_2:
		{
			o->timer++;
			
			// flash mouth
			o->frame = 8;
			if (o->timer > 50 && (o->timer & 2))
				o->frame = 9;
			
			// fire shots
			if (o->timer > 100)
			{
				if ((o->timer % 6) == 1)
				{
					sound(SND_BLOCK_DESTROY);
					Object *shot = SpawnObjectAtActionPoint(o, OBJ_IGOR_SHOT);
					
					int angle = (o->dir == LEFT) ? 136 : 248;
					angle += random(-16, 16);
					ThrowObjectAtAngle(shot, angle, 0x580);
				}
				
				if (o->timer > 132)		// fires 6 shots
				{
					o->state = STATE_INIT;
					o->timer = 0;
				}
			}
		}
		break;
	}
	
	o->yinertia += 0x40;
	LIMITY(0x5ff);
}
Esempio n. 12
0
void ai_bute_sword(Object *o)
{
	if (run_bute_defeated(o, BUTE_HP))
		return;
	
	switch(o->state)
	{
		case 0:
		{
			o->flags |= (FLAG_SHOOTABLE | FLAG_INVULNERABLE);
			o->nxflags |= NXFLAG_FOLLOW_SLOPE;
			o->damage = 0;
			o->state = 1;
		}
		case 1:		// lying in wait
		{
			FACEPLAYER;
			
			if (pdistlx(128<<CSF) && \
				pdistly2(128<<CSF, 16<<CSF))
			{
				o->state = 10;
			}
		}
		break;
		
		// wait a moment, then start running at player
		case 10:
		{
			o->flags |= FLAG_INVULNERABLE;
			o->damage = 0;
			o->frame = 0;
			
			o->state = 11;
			o->timer = 0;
		}
		case 11:
		{
			if (++o->timer > 30)
			{
				o->state = 20;
				o->timer = 0;
			}
		}
		break;
		
		// run at player and jump
		case 20:
		{
			o->flags &= ~FLAG_INVULNERABLE;
			o->state = 21;
			FACEPLAYER;
		}
		case 21:
		{
			ANIMATE(3, 0, 1);
			XMOVE(0x400);
			
			if (pdistlx(40<<CSF))
			{
				o->xinertia /= 2;
				o->yinertia = -0x300;
				
				o->state = 30;
				o->frame = 2;	// sword back, jumping
				sound(SND_ENEMY_JUMP);
			}
			else if (++o->timer > 50)
			{	// timeout, p got away
				o->state = 10;
				o->xinertia = 0;
			}
		}
		break;
		
		// jumping up
		case 30:
		{
			if (o->yinertia > -0x80)
			{
				o->frame = 3;	// sword swipe fwd
				o->damage = 9;
				
				o->state = 31;
				o->timer = 0;
			}
		}
		break;
		
		// swiping sword, in air
		case 31:
		{
			if (++o->timer > 2)
			{
				o->timer = 0;
				o->frame = 4;	// sword down, in front
			}
			
			if (o->blockd && o->yinertia > 0)
			{
				o->xinertia = 0;
				o->damage = 3;
				
				o->state = 32;
				o->timer = 0;
			}
		}
		break;
		
		case 32:
		{
			if (++o->timer > 30)
			{
				o->state = 10;
				o->timer = 0;
			}
		}
		break;
	}
	
	o->yinertia += 0x20;
	LIMITY(0x5ff);
}
Esempio n. 13
0
// handles his "looping" flight/rush attacks
static void run_flight(Object *o)
{
	switch(o->state)
	{
		// flying left or right
		case BP_FLY_LR:
		{
			o->state++;
			o->animtimer = 0;
			o->frame = 6;		// flying horizontally
			
			o->yinertia = 0;
			o->damage = DMG_RUSH;
			
			FACEPLAYER;
			XMOVE(RUSH_SPEED);
		}
		case BP_FLY_LR+1:
		{
			ANIMATE(1, 6, 7);
			
			// smacked into wall?
			if ((o->blockl && o->dir == LEFT) || \
				(o->blockr && o->dir == RIGHT))
			{
				o->xinertia = 0;
				o->state = BP_HIT_WALL;
				o->damage = DMG_NORMAL;
				o->timer = 0;
				megaquake(10);
			}
			
			// reached player?
			// this has to be AFTER smacked-into-wall check for proper behavior
			// if player stands in spikes at far left/right of arena.
			if (pdistlx(RUSH_DIST))
				o->state = BP_PREPARE_FLY_UD;
		}
		break;
		
		// smacked into wall while flying L/R
		case BP_HIT_WALL:
		{
			o->frame = 6;
			
			if (++o->timer > 30)
			{
				if (o->timer2 <= 3)
					o->state = BP_PREPARE_FLY_LR;
				else
					o->state = BP_RETURN_TO_GROUND;
			}
		}
		break;
		
		
		// flying up
		case BP_FLY_UP:
		{
			o->state++;
			o->timer = 0;
			o->animtimer = 0;
			
			o->frame = 8;		// vertical flight
			o->dir = LEFT;		// up-facing frame
			
			o->yinertia = -RUSH_SPEED;
			o->xinertia = 0;
			o->damage = DMG_RUSH;
		}
		case BP_FLY_UP+1:
		{
			ANIMATE(1, 8, 9);
			
			// hit ceiling? (to make this happen, break his loop and jump ABOVE him
			// while he is in the air, at the part where he would normally be
			// coming back down at you).
			if (o->blocku)
			{
				o->state = BP_HIT_CEILING;
				o->damage = DMG_NORMAL;
				o->timer = 0;
				
				SmokeXY(o->CenterX(), o->Top(), 8);
				megaquake(10);
				
				spawn_bones(o, UP);
			}
			
			// reached player? (this check here isn't exactly the same as pdistly;
			// it's important that it checks the player's top and not his center).
			if ((abs(player->y - o->y) < RUSH_DIST) && o->timer2 < 4)
				o->state = BP_PREPARE_FLY_LR;
		}
		break;
		
		case BP_HIT_CEILING:	// hit ceiling
		{
			o->frame = 8;
			
			if (++o->timer > 30)
			{
				if (o->timer2 <= 3)
					o->state = BP_PREPARE_FLY_LR;
				else
					o->state = BP_RETURN_TO_GROUND;
			}
		}
		break;
		
		
		// flying down
		case BP_FLY_DOWN:
		{
			o->state++;
			o->timer = 0;
			o->animtimer = 0;
			
			o->frame = 8;		// vertical flight
			o->dir = RIGHT;		// down-facing frame
			
			o->yinertia = RUSH_SPEED;
			o->xinertia = 0;
			o->damage = DMG_RUSH;
		}
		case BP_FLY_DOWN+1:
		{
			ANIMATE(1, 8, 9);
			
			if (o->blockd)
			{
				o->state = BP_HIT_FLOOR;
				o->damage = DMG_NORMAL;
				o->timer = 0;
				
				SmokeXY(o->CenterX(), o->Bottom(), 8);
				megaquake(10);
				
				spawn_bones(o, DOWN);
				FACEPLAYER;
			}
			
			if (pdistly(RUSH_DIST) && o->timer2 < 4)
				o->state = BP_PREPARE_FLY_LR;
		}
		break;
		
		case BP_HIT_FLOOR:	// hit floor
		{
			o->frame = 3;
			
			if (++o->timer > 30)
			{
				o->state = BP_FIGHTING_STANCE;
				o->timer = 120;
			}
		}
		break;
		
		
		// come back to ground while facing head on
		case BP_RETURN_TO_GROUND:
		{
			o->frame = 4;		// face screen frame
			o->dir = LEFT;		// non-flashing version
			
			o->state++;
		}
		case BP_RETURN_TO_GROUND+1:
		{
			ANIMATE(1, 4, 5);
			
			o->yinertia += 0x40;
			LIMITY(0x5ff);
			
			if (o->blockd && o->yinertia >= 0)
			{
				o->state++;
				o->timer = 0;
				o->frame = 3; 	// landed
				
				FACEPLAYER;
			}
		}
		break;
		
		case BP_RETURN_TO_GROUND+2:
		{
			o->xinertia *= 3;
			o->xinertia /= 4;
			
			if (++o->timer > 10)
			{
				o->state = BP_FIGHTING_STANCE;
				o->timer = 140;
			}
		}
		break;
	}
}
Esempio n. 14
0
// there is an apparent bug on the sprite sheet for this monster:
//	right-facing frame 1 is a duplicate of frame 0,
//	so the mouth-twitch animation does not work when
//	the frog is facing right.
void ai_frog(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			o->timer = 0;
			o->xinertia = 0;
			o->yinertia = 0;
			
			// non-normal dirs are used to indicate that this frog was
			// spawned by balfrog: we are falling out of ceiling during fight
			if (o->dir != LEFT && o->dir != RIGHT)
			{
				o->dir = random(0, 1) ? LEFT : RIGHT;
				o->flags |= FLAG_IGNORE_SOLID;
				
				o->state = 3;
				o->frame = 2;
			}
			else
			{
				o->flags &= ~FLAG_IGNORE_SOLID;
				o->state = 1;
			}
		}
		case 1:		// standing
		{
			o->timer++;
			
			if (!random(0, 50))
			{	// mouth-flitter animation
				o->state = 2;
				o->frame = 0;
				o->timer = 0;
				o->animtimer = 0;
			}
		}
		break;
		
		case 2:		// mouth flitter
		{
			ANIMATE(2, 0, 1);
			
			if (++o->timer > 18)
				o->state = 1;
		}
		break;
		
		case 3:		// falling out of ceiling during balfrog fight
		{
			if (++o->timer > 40)
			{
				o->flags &= ~FLAG_IGNORE_SOLID;
				
				if (o->blockd)
				{
					o->state = 0;
					o->frame = 0;
					o->timer = 0;
				}
			}
		}
		break;
		
		case 10:	// jumping
		case 11:
		{
			if (o->blockl && o->xinertia < 0)
			{
				o->dir = RIGHT;
				o->xinertia = -o->xinertia;
			}
			
			if (o->blockr && o->xinertia > 0)
			{
				o->dir = LEFT;
				o->xinertia = -o->xinertia;
			}
			
			if (o->blockd)
			{
				o->state = 0;
				o->frame = 0;
				o->timer = 0;
			}
		}
		break;
	}
	
	// random jumping, and jump when shot
	if (o->state < 3 && o->timer > 10)
	{
		bool dojump = false;
		
		if (o->shaketime)
		{
			dojump = true;
		}
		else if (pdistlx(0x14000) && pdistly(0x8000))
		{
			if (!random(0, 50))
			{
				dojump = true;
			}
		}
		
		if (dojump)
		{
			FACEPLAYER;
			o->state = 10;
			o->frame = 2;
			o->yinertia = -0x5ff;
			
			// no jumping sound in cutscenes at ending
			if (!player->inputs_locked && !player->disabled)
				sound(SND_ENEMY_JUMP);
			
			XMOVE(0x200);
		}
	}
	
	o->yinertia += 0x80;
	LIMITY(0x5ff);
}
Esempio n. 15
0
void ai_critter(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			if (o->type == OBJ_POWER_CRITTER)
			{	// altered physics for Power Critter
				o->critter.jumpheight = 0x2800;
				o->critter.jumpgrav = 0x1C;
				o->critter.falldmg = 12;
			}
			else
			{
				o->critter.jumpheight = 0;
				o->critter.jumpgrav = 0x40;
				o->critter.falldmg = 3;
				
				if (o->type == OBJ_CRITTER_HOPPING_BLUE || 			// first cave
					o->type == OBJ_CRITTER_HOPPING_GREEN || 		// egg 1
					o->type == OBJ_CRITTER_HOPPING_AQUA ||			// egg 2
					o->type == OBJ_CRITTER_HOPPING_RED)				// last cave
				{
					o->critter.canfly = false;
					
					// critters in egg1 only 2 dmg
					if (o->type == OBJ_CRITTER_HOPPING_GREEN)
						o->critter.falldmg = 2;
					
					// critters in First Cave don't jump as high
					if (o->type != OBJ_CRITTER_HOPPING_BLUE)
					{
						o->critter.jumpgrav = 0x2C;
					}
				}
				else
				{
					// critters are purple in Maze
					o->sprite = SPR_CRITTER_FLYING_CYAN;
					
					o->critter.canfly = true;
				}
			}
			
			o->state = 1;
		} //fall thru
		case 1:
		{
			o->frame = 0;
			
			if (o->timer >= 8)
			{
				int attack_dist = (o->critter.canfly) ? (96 << CSF) : (64 << CSF);
				
				// close enough to attack?
				if (pdistlx(attack_dist) && pdistly2(96<<CSF, 48<<CSF))
				{
					o->state = 2;
					o->frame = 0;
					o->timer = 0;
				}
				else if (pdistlx(attack_dist + (32<<CSF)) && pdistly2(128<<CSF, 48<<CSF))
				{	// no, but close enough to look up at "attention" and watch player
					FACEPLAYER;
					o->frame = 1;
					o->timer = 8;	// reset timer to stop watching
				}
				else
				{
					// once a little time has passed stop watching him if he turns his back
					if ((o->x > player->x && player->dir==LEFT) || \
						(o->x < player->x && player->dir==RIGHT))
					{
						if (++o->timer >= 150)
						{
							o->frame = 0;
							o->timer = 8;
						}
					}
					else o->timer = 8;
				}
			}
			else
			{
				o->timer++;
			}
			
			if (o->shaketime)
			{	// attack if shot
				o->state = 2;
				o->frame = 0;
				o->timer = 0;
			}
		}
		break;
		
		case 2:		// start jump
		{
			if (++o->timer > 8)
			{
				o->state = 3;
				o->frame = 2;
				o->yinertia = -1228;
				sound(SND_ENEMY_JUMP);
				
				FACEPLAYER;
				XMOVE(0x100);
			}
		}
		break;
		
		case 3:		// jumping
		{
			// enter flying phase as we start to come down or
			// if we hit the ceiling.
			if (o->yinertia > 0x100 || o->blocku)
			{
				// during flight we will sine-wave oscilliate around this position
				o->ymark = (o->y - o->critter.jumpheight);
				
				o->state = 4;
				o->frame = 3;
				o->timer = 0;
			}
			else
			{
				if (o->blockd && o->yinertia >= 0)
				{	// jumped onto a platform before we got to fly--land immediately
					goto landed;
				}
				break;
			}
		}	// fall-thru
		case 4:		// flying
		{
			FACEPLAYER;
			
			// time to come down yet?
			// (come down immediately if we are not one of the flying critters)
			if (!o->critter.canfly || \
				o->blockl || o->blockr || o->blocku || \
				++o->timer > 100)
			{
				o->damage = o->critter.falldmg;			// increased damage if falls on player
				o->state = 5;
				o->frame = 2;
				o->yinertia /= 2;
			}
			else
			{
				// run the propeller
				ANIMATE(0, 3, 5);
				if ((o->timer & 3)==1) sound(SND_CRITTER_FLY);
				
				if (o->blockd) o->yinertia = -0x200;
			}
		}
		break;
		
		case 5:		// coming down from flight
		{
			if (o->blockd)
			{	// landed
landed: ;
				o->damage = 2;			// reset to normal damage
				o->state = 1;
				
				o->frame = 0;
				o->timer = 0;
				o->xinertia = 0;
				
				sound(SND_THUD);
			}
		}
		break;
	}
	
	if (o->state == 4)		// flying
	{
		// fly towards player
		o->xinertia += (o->x > player->x) ? -0x20 : 0x20;
		// sine-wave oscillate
		o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
		
		LIMITX(0x200);
		LIMITY(0x200);
	}
	else if (o->state == 3 && o->yinertia < 0)	// jumping up
	{
		o->yinertia += o->critter.jumpgrav;
	}
	else
	{
		o->yinertia += 0x40;
	}
	
	LIMITY(0x5ff);
}