Пример #1
0
// convenience function.
//  * spawn an object at o's action point.
//  * launch it at the player at speed.
//  * introduce "rand_variance" random error/variation into the launch angle.
void EmFireAngledShot(Object *o, int objtype, int rand_variance, int speed)
{
Object *shot;

	shot = SpawnObjectAtActionPoint(o, objtype);
	ThrowObjectAtPlayer(shot, rand_variance, speed);
}
Пример #2
0
void ai_firewhirr(Object *o)
{
    Object *shot;

    FACEPLAYER;

    switch(o->state)
    {
    case 0:
        o->state = 1;
        o->timer = random(0, 50);
        o->ymark = o->y;
    //o->yinertia = -0x200;
    case 1:

        if (!o->timer)
        {
            o->state = 10;
            o->yinertia = -0x200;
        }
        else o->timer--;

    case 10:
        o->frame ^= 1;

        o->yinertia += (o->y < o->ymark) ? 0x10 : -0x10;
        LIMITY(0x200);

        // inc time-to-fire while player near
        if (pdistly(80 << CSF))
        {
            if (o->dir==LEFT && player->x < o->x && pdistlx(160 << CSF)) o->timer2++;
            if (o->dir==RIGHT && player->x > o->x && pdistlx(160 << CSF)) o->timer2++;
        }

        // if time to fire, spawn a shot
        if (o->timer2 > 20)
        {
            shot = SpawnObjectAtActionPoint(o, OBJ_FIREWHIRR_SHOT);
            o->timer2 = -100 + random(0, 20);
            // tell Curly to acquire us as a target
            if (o->onscreen)
            {
                o->CurlyTargetHere();
            }
        }
        break;
    }
}
Пример #3
0
void ai_mannan(Object *o)
{
	// check if we were "killed"
	if (o->state < 3 && o->hp < 90)
	{
		sound(SND_LITTLE_CRASH);
		SmokeClouds(o, 8, 12, 12);
		o->SpawnXP(objprop[o->type].xponkill);
		o->flags &= ~FLAG_SHOOTABLE;
		o->state = 3;
		o->timer = 0;
		o->frame = 2;
		o->damage = 0;
	}
	
	switch(o->state)
	{
		case 0:
			if (o->shaketime)
			{
				SpawnObjectAtActionPoint(o, OBJ_MANNAN_SHOT);
				o->frame = 1;
				o->state = 2;
				o->timer = 0;
			}
		break;
		
		case 2:		// firing
			if (++o->timer > 20)
			{
				o->timer = o->state = o->frame = 0;
			}
		break;
		
		case 3:		// dead/blinking
			switch(++o->timer)
			{
				case 50: case 60: o->frame = 3; break;
				case 53: case 63: o->frame = 2; break;
				case 100: o->state = 4; break;
			}
		break;
	}
}
Пример #4
0
void OmegaBoss::Run(void)
{
	Object *&o = game.stageboss.object;
	
	if (omg.defeated)
		return;
	
	switch(o->state)
	{
		case 0:	break;	// waiting for trigger by script
		
		case OMG_WAIT:	// waits for a moment then go to omg.nextstate
		{
			o->state++;
			omg.timer = 0;
		}
		case OMG_WAIT+1:
		{
			if (++omg.timer >= OMEGA_WAIT_TIME)
			{
				omg.timer = 0;
				o->state = omg.nextstate;
			}
		}
		break;
		
		case OMG_APPEAR:
		{
			omg.timer = 0;
			o->frame = 0;
			o->state = OMG_MOVE;
			omg.movedir = -OMEGA_SPEED;
			o->flags |= FLAG_SOLID_MUSHY;
		}
		case OMG_MOVE:	// rising up/going back into ground
		{
			o->frame = 0;
			o->y += omg.movedir;
			
			game.quaketime = 2;
			
			omg.timer++;
			if ((omg.timer & 3) == 0) sound(SND_QUAKE);
			
			if (omg.timer >= omg.movetime)
			{
				if (omg.movedir < 0)
				{	// was rising out of ground
					omg.nextstate = OMG_JAWS_OPEN;
					o->state = OMG_WAIT;
				}
				else
				{	// was going back into ground
					omg.timer = 0;
					o->state = OMG_UNDERGROUND;
					o->flags &= ~(FLAG_SOLID_MUSHY | FLAG_SOLID_BRICK);
				}
			}
		}
		break;
		
		case OMG_JAWS_OPEN:			// jaws opening
		{
			o->state++;
			omg.animtimer = 0;
			sound(SND_JAWS);
			o->sprite = SPR_OMG_OPENED;			// select "open" bounding box
		}
		case OMG_JAWS_OPEN+1:
		{
			omg.animtimer++;
			if (omg.animtimer > 2)
			{
				omg.animtimer = 0;
				o->frame++;
				if (o->frame==3)
				{
					o->state = OMG_FIRE;
					omg.firecounter = 0;
					o->flags |= FLAG_SHOOTABLE;
				}
			}
		}
		break;
		
		case OMG_FIRE:	// throwing out red stuff
		{
			omg.firecounter++;
			
			if (omg.firecounter > omg.startfiring && omg.firecounter < omg.stopfiring)
			{
				if ((omg.firecounter % omg.firefreq)==0)
				{
					Object *shot;
					
					sound(SND_EM_FIRE);
					
					shot = SpawnObjectAtActionPoint(o, OBJ_OMEGA_SHOT);
					shot->xinertia = random(-omg.shotxspd, omg.shotxspd);
					shot->yinertia = -0x333;
					if (omg.form==2 || random(0, 9) < 8)
					{
						shot->sprite = SPR_OMG_BULLET_NORMAL;
						shot->flags = FLAG_SHOOTABLE;
					}
					else
					{
						shot->sprite = SPR_OMG_BULLET_HARD;
						shot->flags = (FLAG_SHOOTABLE | FLAG_INVULNERABLE);
					}
					
					shot->timer = (random(0, 7) >= 4) ? random(300, 400):0;
					shot->damage = 4;
				}
			}
			else if (omg.firecounter >= omg.endfirestate || sound_is_playing(SND_MISSILE_HIT))
			{	// snap jaws shut
				omg.animtimer = 0;
				o->state = OMG_JAWS_CLOSE;
				sound(SND_JAWS);
			}
		}
		break;
		
		case OMG_JAWS_CLOSE:	// jaws closing
		{
			omg.animtimer++;
			if (omg.animtimer > 2)
			{
				omg.animtimer = 0;
				
				o->frame--;
				if (o->frame == 0)
				{
					sound_stop(SND_JAWS);
					sound(SND_BLOCK_DESTROY);
					
					o->sprite = SPR_OMG_CLOSED;		// select "closed" bounding box
					
					o->flags &= ~FLAG_SHOOTABLE;
					o->damage = 0;
					
					if (omg.form == 1)
					{	// form 1: return to sand
						o->state = OMG_WAIT;
						omg.nextstate = OMG_MOVE;
						omg.movedir = OMEGA_SPEED;
						omg.movetime = OMEGA_SINK_DEPTH;
					}
					else
					{	// form 2: jump
						sound(SND_FUNNY_EXPLODE);
						if (o->x < player->x) o->xinertia = 0xC0;
										 else o->xinertia = -0xC0;
						o->state = OMG_JUMP;
						o->yinertia = -0x5FF;
						omg.orgy = o->y;
					}
				}
			}
			
			// hurt player if he was standing in the middle when the jaws shut
			if (player->riding == o)
			{
				hurtplayer(OMEGA_DAMAGE);
			}
		}
		break;
		
		case OMG_UNDERGROUND:		// underground waiting to reappear
		{
			if (++omg.timer >= 120)
			{
				omg.timer = 0;
				o->state = OMG_APPEAR;
				
				o->x = omg.orgx + (random(-64, 64) << CSF);
				o->y = omg.orgy;
				omg.movetime = OMEGA_RISE_HEIGHT;
				
				// switch to jumping out of ground when we get low on life
				if (omg.form==1 && o->hp <= HP_TRIGGER_POINT)
				{
					o->flags |= FLAG_SOLID_MUSHY;
					
					omg.form = 2;
					omg.firefreq = 5;
					omg.shotxspd = 0x155;
					omg.startfiring = 0;
					omg.stopfiring = 30;
					omg.endfirestate = 50;
					omg.movetime = OMEGA_RISE_HEIGHT+3;
				}
			}
		}
		break;
		
		case OMG_JUMP:	// init for jump
		{
			omg.orgy = o->y;
			o->state++;
			omg.timer = 0;
		}
		case OMG_JUMP+1:	// jumping
		{
			o->yinertia += 0x24;
			if (o->yinertia > 0x5ff) o->yinertia = 0x5ff;
			
			if (o->yinertia > 0)
			{	// coming down
				
				pieces[LEFTLEG]->sprite = pieces[RIGHTLEG]->sprite = SPR_OMG_LEG_ONGROUND;
				
				// retract legs a little when we hit the ground
				if (pieces[LEFTLEG]->blockd || pieces[RIGHTLEG]->blockd)
				{
					o->xinertia = 0;
					omg.leg_descend -= o->yinertia;
					if (++omg.timer >= 3)
					{
						o->yinertia = 0;
						o->state = OMG_JAWS_OPEN;
					}
				}
				
				// --- squash player if we land on him -------------
				// if top of player is higher than bottom of our bounding box
				// but bottom of player's bounding box is not...
				if (player->blockd)
				{
					int omg_bottom = o->y + (sprites[o->sprite].solidbox.y2 << CSF);
					if (player->y <= omg_bottom)
					{
						if (player->y + (sprites[player->sprite].solidbox.y2 << CSF) >= omg_bottom)
						{
							if (hitdetect(o, player))	// easy way to verify the X's are lined up
							{	// SQUISH!
								hurtplayer(OMEGA_DAMAGE);
							}
						}
					}
				}
			}
			else
			{	// jumping up; extend legs
				omg.leg_descend = (omg.orgy - o->y) + LEGD_MIN;
				if (omg.leg_descend > LEGD_MAX) omg.leg_descend = LEGD_MAX;
				pieces[LEFTLEG]->sprite = pieces[RIGHTLEG]->sprite = SPR_OMG_LEG_INAIR;
			}
		}
		break;
		
		/// victory
		case OMG_EXPLODING:
		{
			omg.timer = 0;
			o->state++;
		}
		case OMG_EXPLODING+1:
		{
			int x, y;
			
			o->xinertia = o->yinertia = 0;
			
			x = o->CenterX() + (random(-48, 48)<<CSF);
			y = o->CenterY() + (random(-48, 24)<<CSF);
			SmokePuff(x, y);
			effect(x, y, EFFECT_BOOMFLASH);
			
			game.quaketime = 2;
			
			if ((omg.timer % 12)==0) sound(SND_ENEMY_HURT_BIG);
			
			if (++omg.timer > 100)
			{
				omg.timer = 0;
				starflash.Start(o->CenterX(), o->CenterY());
				o->state = OMG_EXPLODED;
			}
			else if (omg.timer==24)
			{
				StartScript(210);
			}
		}
		break;
		
		case OMG_EXPLODED:
		{
			game.quaketime = 40;
			
			if (++omg.timer > 50)
			{
				o->Delete();
				for(int i=0;i<NUM_PIECES;i++)
					pieces[i]->Delete();
				
				omg.defeated = true;
				return;
			}
		}
		break;
	}
	
	// implement shaking when shot
	// we do it manually instead of used the usual shared code
	// because we want all the pieces to shake at once
	if (o->hp != omg.lasthp && !omg.shaketimer)
	{
		omg.shaketimer = 3;
		// why did I write this? anyway, I'm sure it's important
		if (o->x > player->x) o->display_xoff = -1;
						 else o->display_xoff = 1;
		
		omg.lasthp = o->hp;
	}
	if (omg.shaketimer)
	{
		int xoff = -o->display_xoff;
		
		if (!--omg.shaketimer) xoff = 0;
		
		o->display_xoff = xoff;
		pieces[LEFTLEG]->display_xoff = xoff;
		pieces[RIGHTLEG]->display_xoff = xoff;
		pieces[LEFTSTRUT]->display_xoff = xoff;
		pieces[RIGHTSTRUT]->display_xoff = xoff;
	}
	
	if (o->state)
	{
		o->blockl |= pieces[LEFTLEG]->blockl;
		o->blockr |= pieces[RIGHTLEG]->blockr;
		
		pieces[LEFTLEG]->x = o->x - (4 << CSF); pieces[LEFTLEG]->y = o->y + omg.leg_descend;
		pieces[RIGHTLEG]->x = o->x + (38 << CSF); pieces[RIGHTLEG]->y = o->y + omg.leg_descend;
		pieces[LEFTSTRUT]->x = o->x + (9 << CSF); pieces[LEFTSTRUT]->y = o->y + (27 << CSF);
		pieces[RIGHTSTRUT]->x = o->x + (43 << CSF); pieces[RIGHTSTRUT]->y = o->y + (27 << CSF);
	}
}
Пример #5
0
void ai_dragon_zombie(Object *o)
{
	if (o->hp < 950 && o->state < 50)
	{
		sound(SND_BIG_CRASH);
		SmokeClouds(o, 8, 4, 4);
		o->SpawnPowerups();
		
		o->flags &= ~FLAG_SHOOTABLE;
		o->damage = 0;
		
		o->frame = 5;	// dead
		o->state = 50;	// dead
	}
	
	switch(o->state)
	{
		case 0:
		case 1:		// ready
		{
			ANIMATE(30, 0, 1);
			
			if (--o->timer < 0)		// can fire again yet?
			{
				if (pdistlx(112 << CSF))	// player in range?
				{
					o->state = 2;
					o->timer = 0;
				}
			}
		}
		break;
		
		case 2:		// flashing, prepare to fire
		{
			FACEPLAYER;
			
			o->timer++;
			o->frame = (o->timer & 2) ? 2 : 3;
			
			if (o->timer > 30)
				o->state = 3;
		}
		break;
		
		case 3:
		{
			o->state = 4;
			o->timer = 0;
			o->frame = 4;
			
			// save point we'll fire at--these enemies don't update
			// the position of their target for each shot
			o->xmark = player->x;
			o->ymark = player->y;
		}
		case 4:
		{
			o->timer++;
			
			if (o->timer < 40 && (o->timer % 8) == 1)
			{
				Object *fire = SpawnObjectAtActionPoint(o, OBJ_DRAGON_ZOMBIE_SHOT);
				ThrowObject(fire, o->xmark, o->ymark, 6, 0x600);
				
				sound(SND_SNAKE_FIRE);
			}
			
			if (o->timer > 60)
			{
				o->state = 1;
				o->frame = 0;
				o->timer = random(100, 200);	// random time till can fire again
			}
		}
		break;
	}
}
Пример #6
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);
}
Пример #7
0
void ai_boss_doctor(Object *o)
{
	//AIDEBUG;
	
	/*if (o->state > 2 && o->state < 500)
	{
		o->state = 937;
		StartScript(410);
		return;
	}*/
	
	switch(o->state)
	{
		case 0:
		{
			o->y += (8 << CSF);
			o->frame = 3;
			o->state = 1;
			o->BringToFront();		// make sure in front of doctor_crowned
			crystal_tofront = true;	// make sure front crystal is in front of us
		}
		break;
		
		case 2:		// transforming (script)
		{
			o->timer++;
			o->frame = (o->timer & 2) ? 0 : 3;
			
			if (o->timer > 50)
				o->state = 10;
		}
		break;
		
		case 10:	// base state/falling (script)
		{
			o->yinertia += 0x80;
			o->flags |= FLAG_SHOOTABLE;
			o->damage = 3;
			
			if (o->blockd)
			{
				o->state = 20;
				o->timer = 0;
				o->frame = 0;
				
				o->savedhp = o->hp;
				FACEPLAYER;
			}
		}
		break;
		
		// fire wave shot
		case 20:
		{
			o->timer++;
			
			if (o->timer < 50)
			{
				if ((o->hp - o->savedhp) > 20)
					o->timer = 50;
			}
			
			if (o->timer == 50)
			{	// arm across chest
				FACEPLAYER;
				o->frame = 4;
			}
			
			if (o->timer == 80)
			{
				Object *shot;
				o->frame = 5;	// arm cast out
				
				shot = SpawnObjectAtActionPoint(o, OBJ_DOCTOR_SHOT);
				shot->dir = o->dir;
				shot->angle = 0;
				
				shot = SpawnObjectAtActionPoint(o, OBJ_DOCTOR_SHOT);
				shot->dir = o->dir;
				shot->angle = 0x80;
				
				sound(SND_FUNNY_EXPLODE);
			}
			
			if (o->timer == 120)
				o->frame = 0;	// arm down
			
			if (o->timer > 130)
			{
				if ((o->hp - o->savedhp) > 50)
				{
					o->state = 100;
					o->timer = 0;
				}
				
				if (o->timer > 160)
				{
					o->state = 100;
					o->timer = 0;
				}
			}
		}
		break;
		
		// big "explosion" blast
		case 30:
		{
			o->state = 31;
			o->timer = 0;
			o->frame = 6;
			o->xmark = o->x;
			o->flags |= FLAG_SHOOTABLE;
		}
		case 31:
		{
			o->x = o->xmark;
			if (++o->timer & 2) o->x += (1 << CSF);
			
			if (o->timer > 50)
			{
				o->state = 32;
				o->timer = 0;
				o->frame = 7;
				
				sound(SND_LIGHTNING_STRIKE);
				
				for(int angle=8;angle<256;angle+=16)
				{
					Object *shot = SpawnObjectAtActionPoint(o, OBJ_DOCTOR_BLAST);
					ThrowObjectAtAngle(shot, angle, 0x400);
				}
			}
		}
		break;
		case 32:	// after blast
		{
			if (++o->timer > 50)
				o->state = 100;
		}
		break;
		
		// teleport away
		case 100:
		{
			o->state = 101;
			o->flags &= ~FLAG_SHOOTABLE;
			o->damage = 0;
			
			dr_tp_out_init(o);
		}
		case 101:
		{
			if (dr_tp_out(o))
			{
				o->state = 102;
				o->timer = 0;
				o->invisible = true;
				
				// decide where we're going to go now, so the red crystal
				// can start moving towards it. But, it's important not to
				// actually move until the last possible second, or we could
				// drag our floattext along with us (and give away our position).
				o->xmark = (random(5, 35) * TILE_W) << CSF;
				o->ymark = (random(5, 7) * TILE_H) << CSF;
			}
		}
		break;
		
		case 102:	// invisible: waiting to reappear
		{
			if (++o->timer > 40)
			{
				o->state = 103;
				o->timer = 16;
				o->frame = 2;
				o->yinertia = 0;
				
				o->x = o->xmark;
				o->y = o->ymark;
				
				FACEPLAYER;
			}
		}
		break;
		
		// tp back in
		case 103:
		{
			o->state++;
			dr_tp_in_init(o);
		}
		case 104:
		{
			if (dr_tp_in(o))
			{
				o->flags |= FLAG_SHOOTABLE;
				o->damage = 3;
				
				if (++o->timer2 >= 4)
				{	// big explode
					o->timer2 = 0;
					o->state = 30;
				}
				else
				{	// another wave shot
					o->state = 10;
				}
			}
		}
		break;
		
		// defeated!
		case 500:
		{
			o->flags &= ~FLAG_SHOOTABLE;
			o->frame = 6;
			
			// fall to earth
			o->yinertia += 0x10;
			if (o->blockd && o->yinertia >= 0)
			{
				o->state = 501;
				o->timer = 0;
				
				o->xmark = o->x;
				FACEPLAYER;
			}
		}
		break;
		
		case 501:	// flashing (transforming into Doctor 2)
		{
			FACEPLAYER;
			o->frame = 8;
			
			o->x = o->xmark;
			if (!(++o->timer & 2))
				o->x += (1 << CSF);
		}
		break;
	}
	
	// enable per-frame bbox
	COPY_PFBOX;
	
	// set crystal follow position
	if (o->state >= 10)
	{
		if (o->invisible)	// teleporting
		{
			crystal_xmark = o->xmark;
			crystal_ymark = o->ymark;
		}
		else
		{
			crystal_xmark = o->x;
			crystal_ymark = o->y;
		}
	}
	
	LIMITY(0x5ff);
}
Пример #8
0
void ai_buyobuyo_base(Object *o)
{
    /*if (o->onscreen) {
    	debug("state: %d", o->state);
    	debug("timer: %d", o->timer);
    	debug("timer2: %d", o->timer2);
    }*/

    if (o->state < 3 && o->hp < (1000 - BUYOBUYO_BASE_HP))
    {
        SmokeClouds(o, objprop[o->type].death_smoke_amt, 8, 8);
        effect(o->CenterX(), o->CenterY(), EFFECT_BOOMFLASH);
        o->SpawnPowerups();

        o->flags &= ~FLAG_SHOOTABLE;
        o->damage = 0;

        o->state = 10;
        o->frame = 2;
    }

    switch(o->state)
    {
    case 0:
    {
        // ceiling has different bounding box and action point
        if (o->dir == RIGHT)
            o->sprite = SPR_BUYOBUYO_BASE_CEILING;

        o->state = 1;
        o->timer = 10;
    }
    case 1:
    {
        if (pdistlx(0x14000))
        {
            if ((o->dir == LEFT && pdistly2(0x14000, 0x2000)) || \
                    (o->dir == RIGHT && pdistly2(0x2000, 0x14000)))
            {
                if (--o->timer < 0)
                {
                    o->state = 2;
                    o->timer = 0;
                    o->animtimer = 0;
                }
            }
        }
    }
    break;

    case 2:
    {
        ANIMATE(3, 0, 1);

        if (++o->timer > 10)
        {
            Object *buyo = SpawnObjectAtActionPoint(o, OBJ_BUYOBUYO);
            buyo->dir = o->dir;

            sound(SND_EM_FIRE);
            o->frame = 0;
            o->CurlyTargetHere();

            // cyclic: three firings then pause
            o->state = 1;
            if (++o->timer2 > 2)
            {
                o->timer = 100;
                o->timer2 = 0;
            }
            else
            {
                o->timer = 20;
            }
        }
    }
    break;
    }
}
Пример #9
0
void IronheadBoss::Run(void)
{
	if (!o) return;
	
	switch(o->state)
	{
		case IRONH_SPAWN_FISHIES:
		{
			o->timer = 0;
			o->state++;
		}
		case IRONH_SPAWN_FISHIES+1:		// wave of fishies comes in
		{
			if (++o->timer > 50)
			{
				o->timer = 0;
				o->state = IRONH_SWIM;
			}
			
			if ((o->timer & 3)==0)
			{
				CreateObject((random(15, 18) * TILE_W) << CSF, \
						  	(random(ARENA_TOP, ARENA_BOTTOM) * TILE_H) << CSF, \
						  	OBJ_IRONH_FISHY);
			}
		}
		break;
		
		case IRONH_SWIM:		// swimming attack
		{
			o->state++;
			
			if (o->dir==RIGHT)
			{	// coming up on player from left
				o->x = 0x1e000;
				o->y = player->y;
			}
			else
			{	// returning from right side of screen
				o->x = 0x5a000;
				o->y = (random(ARENA_TOP, ARENA_BOTTOM) * TILE_H) << CSF;
			}
			
			o->xmark = o->x;
			o->ymark = o->y;
			
			o->yinertia = random(-0x200, 0x200);
			o->xinertia = random(-0x200, 0x200);
			
			o->flags |= FLAG_SHOOTABLE;
		}
		case IRONH_SWIM+1:
		{
			ANIMATE(2, 0, 7);
			
			if (o->dir==RIGHT)
			{
				o->xmark += 0x400;
			}
			else
			{
				o->xmark -= 0x200;
				o->ymark += (o->ymark < player->y) ? 0x200: -0x200;
			}
			
			//debugXline(o->xmark, 255,0,0);
			//debugYline(o->ymark, 0,255,0);
			o->xinertia += (o->x > o->xmark) ? -8 : 8;
			o->yinertia += (o->y > o->ymark) ? -8 : 8;
			
			LIMITY(0x200);
			
			if (o->dir==RIGHT)
			{
				if (o->x > 0x5a000)
				{
					o->dir = LEFT;
					o->state = IRONH_SPAWN_FISHIES;
				}
			}
			else
			{
				if (o->x < 0x22000)
				{
					o->dir = RIGHT;
					o->state = IRONH_SPAWN_FISHIES;
				}
			}
			
			if (o->dir==LEFT)
			{
				// fire bullets at player when retreating
				switch(++o->timer)
				{
					case 300:
					case 310:
					case 320:
					{
						Object *shot = SpawnObjectAtActionPoint(o, OBJ_IRONH_SHOT);
						shot->xinertia = (random(-3, 0) << CSF);
						shot->yinertia = (random(-3, 3) << CSF);
						sound(SND_EM_FIRE);
					}
					break;
				}
			}
		}
		break;
		
		case IRONH_DEFEATED:
		{
			sound(SND_EXPL_SMALL);
			o->state = IRONH_DEFEATED+1;
			o->flags &= ~FLAG_SHOOTABLE;
			o->frame = 8;
			o->damage = 0;
			o->xmark = o->x;
			o->ymark = o->y;
			o->xinertia = o->yinertia = 0;
			o->timer = 0;
			KillObjectsOfType(OBJ_IRONH_FISHY);
			KillObjectsOfType(OBJ_IRONH_BRICK);
			KillObjectsOfType(OBJ_BRICK_SPAWNER);
			game.quaketime = 20;
			
			for(int i=0;i<32;i++)
				ironh_smokecloud(o);
		}
		case IRONH_DEFEATED+1:			// retreat back to left...
		{
			o->xmark -= (1<<CSF);
			
			o->x = o->xmark + (random(-1, 1) << CSF);
			o->y = o->ymark + (random(-1, 1) << CSF);
			
			o->timer++;
			if ((o->timer & 3)==0) ironh_smokecloud(o);
		}
		break;
	}
	
	// show pink "hit" frame when he's taking damage
	o->sprite = SPR_IRONH;
	if (o->shaketime)
	{
		this->hittimer++;
		if (this->hittimer & 2)
		{
			o->sprite = SPR_IRONH_HURT;
		}
	}
	else
	{
		this->hittimer = 0;
	}
}