Exemplo n.º 1
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;
    }
}
Exemplo n.º 2
0
void ai_proximity_press_vert(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			if (pdistlx(8<<CSF) && pdistly2(8<<CSF, 128<<CSF) && \
				!o->blockd)
			{
				o->state = 10;
				o->animtimer = 0;
				o->frame = 1;
			}
		}
		break;
		
		case 10:
		{
			if (o->frame < 2)
				ANIMATE_FWD(2);
			
			if (o->blockd)
			{
				if (o->frame >= 2)	// make sure eye fully open
				{
					SmokeSide(o, 4, DOWN);
					quake(10);
				}
				
				o->flags |= FLAG_SOLID_BRICK;
				o->damage = 0;
				
				o->state = 11;
				o->frame = 0;
			}
			else
			{
				if (player->Top() > o->CenterY())
				{
					o->flags &= ~FLAG_SOLID_BRICK;
					o->damage = 127;
				}
				else
				{
					o->flags |= FLAG_SOLID_BRICK;
					o->damage = 0;
				}
			}
		}
		break;
	}
	
	if (o->state >= 5)
	{
		o->yinertia += 0x80;
		LIMITY(0x5ff);
	}
}
Exemplo n.º 3
0
void ai_bat_circle(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			uint8_t angle;
			o->state = 1;
			
			// set up initial direction and target x,y
			angle = random(0, 255);
			o->xinertia = sin_table[angle];
			
			angle += 64;
			o->xmark = (o->x + (sin_table[angle] * 8));
			
			angle = random(0, 255);
			o->yinertia = sin_table[angle];
			
			angle += 64;
			o->ymark = (o->y + (sin_table[angle] * 8));
		}
		case 1:
			// circle around our target point
			ANIMATE(1, 2, 4);
			FACEPLAYER;
			o->xinertia += (o->x > o->xmark) ? -0x10 : 0x10;
			o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
			LIMITX(0x200);
			LIMITY(0x200);
			
			if (!o->timer2)
			{
				if (pdistlx(0x1000) && (player->y > o->y) && pdistly(0xC000))
				{	// dive attack
					o->xinertia /= 2;
					o->yinertia = 0;
					o->state = 2;
					o->frame = 5;		// mouth showing teeth
				}
			}
			else o->timer2--;
		break;
		
		case 2:	// dive attack
			o->yinertia += 0x40;
			LIMITY(0x5ff);
			
			if (o->blockd)
			{
				o->yinertia = 0;
				o->xinertia *= 2;
				o->timer2 = 120;		// delay before can dive again
				o->state = 1;
			}
		break;
	}
}
Exemplo n.º 4
0
void ai_falling_spike_small(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			o->xmark = o->x;
			
			if (pdistlx(12 << CSF))
				o->state = 1;
		}
		break;
		
		case 1:		// shaking
		{
			if (++o->animtimer >= 12)
				o->animtimer = 0;
			
			o->x = o->xmark;
			if (o->animtimer >= 6) o->x += (1 << CSF);
			
			if (++o->timer > 30)
			{
				o->state = 2;	// fall
				o->frame = 1;	// slightly brighter frame at top
			}
		}
		break;
		
		case 2:		// falling
		{
			o->yinertia += 0x20;
			LIMITY(0xC00);
			
			if (o->blockd)
			{
				if (!player->inputs_locked)	// no sound in ending cutscene
					sound(SND_BLOCK_DESTROY);
				
				SmokeClouds(o, 4, 2, 2);
				effect(o->CenterX(), o->CenterY(), EFFECT_BOOMFLASH);
				o->Delete();
			}
		}
		break;
	}
}
Exemplo n.º 5
0
void ai_misery_ball(Object *o)
{
  switch (o->state)
  {
    case 0:
    {
      o->state    = 1;
      o->ymark    = o->y;
      o->xinertia = 0;
      o->yinertia = -0x200;
    }
    case 1:
    {
      ANIMATE(2, 0, 1);

      o->xinertia += (o->x < player->x) ? 0x10 : -0x10;
      o->yinertia += (o->y < o->ymark) ? 0x20 : -0x20;
      LIMITX(0x200);
      LIMITY(0x200);

      if (pdistlx(8 * CSFI) && player->y > o->y)
      {
        o->state = 10;
        o->timer = 0;
      }
    }
    break;

    case 10: // black lightning
    {
      if (++o->timer > 10)
      {
        NXE::Sound::SoundManager::getInstance()->playSfx(NXE::Sound::SFX::SND_LIGHTNING_STRIKE);
        CreateObject(o->x, o->y, OBJ_BLACK_LIGHTNING);
        o->Delete();
      }

      o->frame = (o->timer & 2) ? 2 : 1;
    }
    break;
  }
}
Exemplo n.º 6
0
void ai_press_vert(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			o->state = 1;
			o->y -= (4 << CSF);
			
			if (pdistlx((8<<CSF)) && pdistly2((8<<CSF), (128<<CSF)))
			{
				o->state = 5;
			}
		}
		break;
		
		case 5:
		{
			if (o->blockd)
			{
				o->state = 10;
				o->animtimer = 0;
				o->frame = 1;
			}
		}
		break;
		
		case 10:
		{
			ANIMATE_FWD(2);
			if (o->frame > 2)
				o->frame = 2;
			
			if (player->y > o->y)
				o->flags |= FLAG_SOLID_BRICK;
		}
		break;
	}
}
Exemplo n.º 7
0
void ai_falling_spike_large(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			o->xmark = o->x;
			
			if (pdistlx(12 << CSF))
				o->state = 1;
		}
		break;
		
		case 1:		// shaking
		{
			if (++o->animtimer >= 12)
				o->animtimer = 0;
			
			o->x = o->xmark;
			if (o->animtimer >= 6)	// scuttle:: big spikes shake in the other direction
				o->x -= (1 << CSF);
			
			if (++o->timer > 30)
			{
				o->state = 2;	// fall
				o->frame = 1;	// slightly brighter frame at top
			}
		}
		break;
		
		case 2:		// falling
		{
			o->yinertia += 0x20;
			LIMITY(0xC00);
			
			if (o->Bottom() < player->Bottom())
			{	// could fall on player
				o->flags &= ~FLAG_SOLID_BRICK;
				o->damage = 127;	// ouch!
			}
			else
			{	// player could only touch side from this position
				o->flags |= FLAG_SOLID_BRICK;
				o->damage = 0;
			}
			
			// damage NPC's as well (it kills that one Dragon Zombie)
			Object *enemy;
			FOREACH_OBJECT(enemy)
			{
				if ((enemy->flags & FLAG_SHOOTABLE) && \
					o->Bottom() >= enemy->CenterY() && hitdetect(o, enemy))
				{
					if (!(enemy->flags & FLAG_INVULNERABLE))
						enemy->DealDamage(127);
				}
			}
			
			if (++o->timer > 8 && o->blockd)
			{
				o->flags |= FLAG_SOLID_BRICK;
				o->damage = 0;
				o->yinertia = 0;
				
				o->state = 3;	// fall complete
				o->timer = 0;
				
				sound(SND_BLOCK_DESTROY);
				SmokeClouds(o, 4, 2, 2);
				
				effect(o->CenterX(), o->y + (sprites[o->sprite].block_d[0].y << CSF),
					EFFECT_STARSOLID);
			}
		}
		break;
		
		case 3:		// hit ground
		{
			if (++o->timer > 4)
			{	// make it destroyable
				o->flags |= FLAG_SHOOTABLE;
				o->flags &= ~FLAG_INVULNERABLE;
				o->state = 4;
			}
		}
		break;
	}
}
Exemplo n.º 8
0
void ai_mesa(Object *o)
{
	if (run_bute_defeated(o, MESA_HP))
		return;
	
	switch(o->state)
	{
		case 0:
		{
			o->y += (4<<CSF);
			o->state = 1;
		}
		case 1:
		{
			ANIMATE(40, 0, 1);
			FACEPLAYER;
			
			if (pdistlx(320<<CSF) && pdistly(160<<CSF))
			{
				if (++o->timer > 50)
					o->state = 10;
			}
		}
		break;
		
		case 10:
		{
			o->state = 11;
			o->timer = 0;
			o->frame = 2;	// hand down
			
			int x = o->x + ((o->dir == LEFT) ? (7<<CSF) : -(7<<CSF));
			int y = o->y + (10<<CSF);
			
			o->linkedobject = CreateObject(x, y, OBJ_MESA_BLOCK);
			o->linkedobject->linkedobject = o;
		}
		case 11:
		{
			if (++o->timer > 50)
			{
				o->state = 20;
				o->timer = 0;
				o->frame = 3;	// hand up, throwing
				
				if (o->linkedobject)
				{
					Object *&block = o->linkedobject;
					
					block->y = (o->y - (4<<CSF));
					block->xinertia = (o->dir == RIGHT) ? 0x400 : -0x400;
					block->yinertia = -0x400;
					block->state = 1;
					
					sound(SND_EM_FIRE);
					block->linkedobject = NULL;
					o->linkedobject = NULL;
				}
			}
		}
		break;
		
		case 20:
		{
			if (++o->timer > 20)
			{	// throw again, if player still near
				o->state = 1;
				o->timer = 0;
			}
		}
		break;
	}
	
	o->yinertia += 0x55;
	LIMITY(0x5ff);
}
Exemplo n.º 9
0
void ai_bat_hang(Object *o)
{
	switch(o->state)
	{
		case 0:
			o->state = 1;
		case 1:		// hanging and waiting
			if (!random(0, 100))
			{
				o->state = 2;
				o->timer = 0;
				o->frame = 1;
			}
			
			if (pdistlx(0x1000) && pdistly2(0x1000, 0x9000))
			{
				o->frame = 0;
				o->state = 3;
			}
		break;
		
		case 2:		// blinking
			if (++o->timer > 8)
			{
				o->state = 1;
				o->frame = 0;
			}
		break;
		
		case 3:		// at attention
			o->frame = 0;
			if (o->shaketime || pdistlx(0x2800))
			{
				o->frame = 1;
				o->animtimer = 0;
				o->state = 4;
				o->timer = 0;
			}
		break;
		
		case 4:		// falling
			o->yinertia += 0x20;
			LIMITY(0x5ff);
			
			o->timer++;
			if (o->timer > 20 || o->blockd)
			{
				if (o->blockd || ((player->y - 0x2000) < o->y))
				{	// start flying
					o->animtimer = 0;
					o->frame = 2;
					o->state = 5;
					o->ymark = o->y;
					if (o->blockd) o->yinertia = -0x200;
				}
			}
		break;
		
		case 5:		// flying
			ANIMATE(1, 2, 4);
			FACEPLAYER;
			
			o->xinertia += (o->x > player->x) ? -0x20 : 0x20;
			o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
			
			LIMITX(0x200);
			LIMITY(0x200);
			
			if (o->blockd) o->yinertia = -0x200;
			if (o->blockr) o->yinertia = 0x200;
		break;
	}
}
Exemplo n.º 10
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);
	}
}
Exemplo n.º 11
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);
}
Exemplo n.º 12
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;
    }
}
Exemplo 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;
	}
}
Exemplo 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);
}
Exemplo 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);
}
Exemplo n.º 16
0
void ai_counter_bomb(Object *o)
{
	/*debug("state: %d", o->state);
	debug("timer: %d", o->timer);
	debug("timer2: %d", o->timer2);*/
	
	switch(o->state)
	{
		case 0:
		{
			o->state = 1;
			o->ymark = o->y;
			
			o->timer = random(0, 50);
			o->timer2 = 0;
		}
		case 1:
		{	// desync if multiple enemies
			if (--o->timer < 0)
			{
				o->timer = 0;
				o->state = 2;
				o->yinertia = 0x300;
			}
		}
		break;
		
		case 2:		// ready
		{
			if (pdistlx(80 << CSF) || o->shaketime)
			{
				o->state = 3;
				o->timer = 0;
			}
		}
		break;
		
		case 3:		// counting down...
		{
			if (--o->timer < 0)
			{
				if (o->timer2 < 5)
				{
					Object *number = CreateObject(o->CenterX() + (8 << CSF), \
												  o->y + (16 << CSF), \
												  OBJ_COUNTER_BOMB_NUMBER);
					
					number->frame = o->timer2++;
					o->timer = 60;
				}
				else
				{
					// expand bounding box to cover explosion area
					o->x = o->CenterX();
					o->y = o->CenterY();
					o->invisible = true;
					o->sprite = SPR_BBOX_PUPPET_1;
					sprites[o->sprite].bbox.x1 = -128;
					sprites[o->sprite].bbox.y1 = -100;
					sprites[o->sprite].bbox.x2 = 128;
					sprites[o->sprite].bbox.y2 = 100;
					o->damage = 30;
					
					o->yinertia = 0;
					o->state = 4;
					
					// make kaboom
					sound(SND_EXPLOSION1);
					quake(20);
					SmokeXY(o->CenterX(), o->CenterY(), 100, 128, 100);
					
					return;
				}
			}
		}
		break;
		
		case 4:		// exploding (one frame only to give time for bbox to damage player)
			o->Delete();
			return;
	}
	
	ANIMATE(4, 0, 2);
	
	if (o->state == 2 || o->state == 3)
	{
		o->yinertia += (o->y > o->ymark) ? -0x10 : 0x10;
		LIMITY(0x100);
	}
}
Exemplo n.º 17
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;
	}
}
Exemplo n.º 18
0
void ai_critter_hopping_red(Object *o)
{
	switch(o->state)
	{
		case 0:
		{
			FACEPLAYER;
			o->frame = 0;
			
			if (o->shaketime)
			{
				o->state = 2;
				o->timer = 0;
			}
			else if (++o->timer >= 8)
			{
				if (pdistly((5 * TILE_H) << CSF))
				{
					if (pdistlx((6 * TILE_W) << CSF))
					{
						o->state = 1;
						o->timer = 0;
					}
					else if (pdistlx((9 * TILE_W) << CSF))
					{
						o->frame = 1;
					}
				}
			}
		}
		break;
		
		case 1:		// prepare to jump
		{
			if (++o->timer > 8)
			{
				o->state = 2;
				o->frame = 2;
				sound(SND_ENEMY_JUMP);
				
				o->yinertia = -0x5ff;
				o->xinertia = (o->dir == RIGHT) ? 0x200 : -0x200;
			}
		}
		break;
		
		case 2:		// in air
		{
			if (o->blockd && o->yinertia > 0)
			{
				sound(SND_THUD);
				o->xinertia = 0;
				
				o->state = 0;
				o->timer = 0;
				o->frame = 1;
			}
		}
		break;
	}
	
	o->yinertia += 0x55;
	LIMITY(0x5ff);
}
Exemplo n.º 19
0
void ai_bute_archer_red(Object *o)
{
	//DebugCrosshair(o->x, o->y, 0, 255, 255);
	
	switch(o->state)
	{
		case 0:
		{
			o->state = 1;
			
			o->xmark = o->x;
			o->ymark = o->y;
			
			if (o->dir == LEFT)
				o->xmark -= (128<<CSF);
			else
				o->xmark += (128<<CSF);
			
			o->xinertia = random(-0x400, 0x400);
			o->yinertia = random(-0x400, 0x400);
		}
		case 1:		// come on screen
		{
			ANIMATE(1, 0, 1);
			
			if ((o->dir == LEFT && o->x < o->xmark) || \
				(o->dir == RIGHT && o->x > o->xmark))
			{
				o->state = 20;
			}
		}
		break;
		
		case 20:	// aiming
		{
			o->state = 21;
			o->timer = random(0, 150);
			
			o->frame = 2;
			o->animtimer = 0;
		}
		case 21:
		{
			ANIMATE(2, 2, 3);
			
			if (++o->timer > 300 || \
				(pdistlx(112<<CSF) && pdistly(16<<CSF)))
			{
				o->state = 30;
			}
		}
		break;
		
		case 30:	// flashing to fire
		{
			o->state = 31;
			o->timer = 0;
			o->animtimer = 0;
			o->frame = 3;
		}
		case 31:
		{
			ANIMATE(1, 3, 4);
			
			if (++o->timer > 30)
			{
				o->state = 40;
				o->frame = 5;
				
				Object *arrow = CreateObject(o->x, o->y, OBJ_BUTE_ARROW);
				arrow->dir = o->dir;
				arrow->xinertia = (o->dir == RIGHT) ? 0x800 : -0x800;
			}
		}
		break;
		
		case 40:	// fired
		{
			o->state = 41;
			o->timer = 0;
			o->animtimer = 0;
		}
		case 41:
		{
			ANIMATE(2, 5, 6);
			
			if (++o->timer > 40)
			{
				o->state = 50;
				o->timer = 0;
				o->xinertia = 0;
				o->yinertia = 0;
			}
		}
		break;
		
		case 50:	// retreat offscreen
		{
			ANIMATE(1, 0, 1);
			XACCEL(-0x20);
			
			if (o->Right() < 0 || o->Left() > ((map.xsize * TILE_W) << CSF))
				o->Delete();
		}
		break;
	}
	
	// sinusoidal hover around set point
	if (o->state != 50)
	{
		o->xinertia += (o->x < o->xmark) ? 0x2A : -0x2A;
		o->yinertia += (o->y < o->ymark) ? 0x2A : -0x2A;
		LIMITX(0x400);
		LIMITY(0x400);
	}
	
}
Exemplo n.º 20
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);
}
Exemplo n.º 21
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;
			}
		}
Exemplo n.º 22
0
void ai_bute_archer(Object *o)
{
	if (run_bute_defeated(o, BUTE_HP))
		return;
	
	switch(o->state)
	{
		case 0:		// waiting for player (when haven't seen him yet)
		{
			if ((o->dir == LEFT  && player->CenterX() < o->CenterX()) || \
				(o->dir == RIGHT && player->CenterX() > o->CenterX()))
			{
				if (pdistlx(320<<CSF) && pdistly(160<<CSF))
				{
					o->state = 10;
				}
			}
		}
		break;
		
		// aiming--can track player here for a brief period
		case 10:
		{
			FACEPLAYER;
			
			if (!pdistlx(224<<CSF) || player->y <= (o->y - (8<<CSF)))
			{
				o->frame = 4;	// shooting up
				o->timer2 = 1;
			}
			else
			{
				o->frame = 1;	// shooting straight
				o->timer2 = 0;
			}
			
			if (++o->timer > 10)
			{
				o->state = 20;
				o->timer = 0;
			}
		}
		break;
		
		// flashing to fire
		case 20:
		{
			if (o->timer2 == 0)
				ANIMATE(0, 1, 2)
			else
				ANIMATE(0, 4, 5)
			
			if (++o->timer > 30)
				o->state = 30;
		}
		break;
		
		// fire
		case 30:
		{
			o->state = 31;
			o->timer = 0;
			
			Object *arrow = CreateObject(o->CenterX(), o->CenterY(), OBJ_BUTE_ARROW);
			arrow->xinertia = (o->dir == RIGHT) ? 0x600 : -0x600;
			
			if (o->timer2 == 1)		// shooting up
				arrow->yinertia = -0x600;
			
			// frame: arrow away
			o->frame = (o->timer2 == 1) ? 6 : 3;
		}
		case 31:
		{
			if (++o->timer > 30)
			{
				o->state = 40;
				o->frame = 0;
				o->timer = random(50, 150);
			}
		}
		break;
		
		// after fire, and the "woken up" waiting-for-player state
		case 40:
		{
			if (pdistlx(352<<CSF) && pdistly(240<<CSF))
			{
				if (--o->timer < 0)
					o->state = 10;	// fire again
			}
			else
			{	// player got away, do nothing until he returns
				o->timer = 150;
			}
		}
		break;
	}
}
Exemplo n.º 23
0
void ai_block_movev(Object *o)
{
	int py = player->CenterY();
	int objy = o->CenterY();
	
	switch(o->state)
	{
		case 0:
         NX_LOG("ai_block_movev - state 0.\n");
			o->flags |= FLAG_SOLID_BRICK;
			o->smushdamage = 100;
			o->dir = (o->dir == LEFT) ? UP : DOWN;
			o->state = (o->dir == DOWN) ? 10 : 20;
		break;
		
		case 10:	// at top edge, ready to travel down
         NX_LOG("ai_block_movev - state 10.\n");
			if (((py > objy) && (py - objy) < 0x32000) || \
				((py < objy) && (objy - py) < 0x3200))
			{
				if (pdistlx(0x3200))
				{
					o->state = 30;
					o->timer = 0;
				}
			}
		break;
		
		case 20:	// at bottom edge, ready to travel up
         NX_LOG("ai_block_movev - state 20.\n");
			if (((py > objy) && (py - objy) < 0x3200) || \
				((py < objy) && (objy - py) < 0x32000))
			{
				if (pdistlx(0x3200))
				{
					o->state = 30;
					o->timer = 0;
				}
			}
		break;
		
		case 30:	// traveling
         NX_LOG("ai_block_movev - state 30.\n");
		{
			YACCEL(0x20);
			LIMITY(0x200);
			
			// hit edge
			if ((o->dir == DOWN && o->blockd) || (o->dir == UP && o->blocku))
			{
				SmokeSide(o, 4, o->dir);
				quake(10);
				
				o->yinertia = 0;
				o->dir ^= 1;
				o->state = (o->dir==DOWN) ? 10 : 20;
			}
			
			if ((++o->timer % 10) == 6)
				sound(SND_BLOCK_MOVE);
		}
		break;
	}
}
Exemplo n.º 24
0
void ai_balrog_boss_running(Object *o)
{
	// try to catch player
	if (o->state == STATE_CHARGE+1 || o->state == STATE_JUMP)
	{
		if ((pdistlx(12 << CSF) && pdistly(8 << CSF)) && o->timer > 8)
		{
			hurtplayer(2);
			balrog_grab_player(o);
			o->state = STATE_CAUGHT_PLAYER;
		}
	}
	
	switch(o->state)
	{
		case 0:
		{
			FACEPLAYER;
			o->flags |= FLAG_SHOOTABLE;
			o->frame = 0;
			o->state = 1;
		}
		case 1:
		{
			if (++o->timer > 30)
			{
				o->state = STATE_CHARGE;
				o->timer2++;
			}
		}
		break;
		
		// running towards player
		case STATE_CHARGE:
		{
			o->state++;
			o->timer = 0;
			o->frame = 9;
			o->animtimer = 0;
		}
		case STATE_CHARGE+1:
		{
			XACCEL(0x10);
			walking_animation(o);
			
			if (++o->timer > 75 || \
				(o->dir == LEFT && o->blockl) ||
				(o->dir == RIGHT && o->blockr))
			{
				o->frame = 0;
				o->state = STATE_SLOW_DOWN;
				break;
			}
			
			// can jump every 3rd time, but if he catches the player
			// before he gets a chance to he does NOT jump on the next charge.
			if ((o->timer2 & 3) == 0)
			{
				if (o->timer > 25)
				{	// initiate jump
					o->frame = 3;
					o->yinertia = -0x400;
					o->state = STATE_JUMP;
				}
			}
		}
		break;
		
		// jumping
		case STATE_JUMP:
		{
			if (o->blockd && o->yinertia >= 0)
			{
				o->frame = 2;		// <-- Landed frame.
				quake(30);
				o->state = STATE_SLOW_DOWN;
			}
		}
		break;
		
		// slowing down after charging or jumping
		case STATE_SLOW_DOWN:
		{
			o->xinertia *= 4;
			o->xinertia /= 5;
			
			if (o->xinertia == 0)
				o->state = 0;
		}
		break;
		
		// caught player
		case STATE_CAUGHT_PLAYER:
		{
			if (balrog_toss_player_away(o))
				o->state = 0;
		}
		break;
	}
	
	o->yinertia += 0x20;
	LIMITX(0x400);
	LIMITY(0x5FF);
}