SC/finger/
SC/notes/
SC/player/s/
#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "merc.h"

void	fire_miniguns	args( ( CHAR_DATA *ch, char *argument ) );
void	fire_buster	args( ( CHAR_DATA *ch, int dam, int dir ) );
void	fire_flamethrower args( (CHAR_DATA *ch ) );
bool	shields_check	args( ( CHAR_DATA *ch, CHAR_DATA *victim, int dam ) );

void do_mount( CHAR_DATA *ch, char *argument )
{
  OBJ_DATA *obj;
  int i, suit;

  if ( IS_NPC(ch) )
    return;
  if ( ch->fighting != NULL )
  { send_to_char( "You can't do that in the middle of combat!\n\r", ch );
    return;
  }
  if ( IS_SUIT( ch ) )
  { send_to_char( "You're already in a mobile suit.\n\r", ch );
    return;
  }
  if ( argument[0] == '\0' )
  { send_to_char( "Mount what?\n\r", ch );
    return;
  }
  if ( ( obj = get_obj_here( ch, argument ) ) == NULL )
  { send_to_char( "That suit isn't here.\n\r", ch );
    return;
  }
  if ( obj->item_type != ITEM_SUIT )
  { send_to_char( "You can only mount mobile suits.\n\r", ch );
    return;
  }
  suit = obj->weight;
  for ( i = 10; i <= 13; i++ )
  { if ( ch->pcdata->suit[i] < suit_table[suit].requisite )
    { send_to_char( "You are not a strong enough pilot to use that suit.\n\r", ch );
      return;
    }
  }

  if ( IS_SET(ch->in_room->room_flags, ROOM_HANGER) )
  {
    if ( ch->pcdata->clan[CLAN] != ch->in_room->clan )
    {
      stc( "Planet defensors activate, preventing you from entering.\n\r", ch );
      return;
    }
  }

  act( "You mount $p and close the hatch.", ch, obj, NULL, TO_CHAR );
  act( "$n mounts $p and closes the hatch.", ch, obj, NULL, TO_ROOM );
  for ( i = 0; i <= 3; i++ )
    ch->pcdata->suit[i] = obj->value[i];
  ch->pcdata->suit[SUIT_NUMBER] = suit;
  for ( i = 0; i <= 3; i++ )
    ch->pcdata->suit[i+5] = obj->extra[i];
  ch->pcdata->suit[SUIT_MISSILES] = obj->extra[4];
  extract_obj( obj );

  return;
}


void do_leave( CHAR_DATA *ch, char *argument )
{
  OBJ_DATA *obj;
  int i, suit, count = 0;

  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You're not in a mobile suit!\n\r", ch );
    return;
  }
  if ( ch->fighting != NULL )
  { send_to_char( "You can't do that in the middle of a battle!\n\r", ch );
    return;
  }

  for ( obj = ch->in_room->contents; obj != NULL; obj = obj->next_content )
  {
    if ( obj->item_type == ITEM_SUIT )
      count++;
  }
  if ( count >= 4 && IS_SET(ch->in_room->room_flags, ROOM_HANGER) )
  {
    stc( "The hanger is already full!", ch );
    return;
  }

  /* suits start at vnum 60 in limbo */
  suit = ch->pcdata->suit[SUIT_NUMBER] + 59;
  obj = create_object( get_obj_index( suit ), 0 );
  for ( i = 0; i <= 3; i++ )
    obj->value[i] = ch->pcdata->suit[i];
  for ( i = 0; i <= 3; i++ )
    obj->extra[i] = ch->pcdata->suit[i+5];
  obj->extra[4] = ch->pcdata->suit[SUIT_MISSILES];
  /* clear out ch's suit values */
  for ( i = 0; i <= 9; i++ )
    ch->pcdata->suit[i] = 0;
  ch->pcdata->suit[SUIT_MISSILES] = 0;
  obj_to_room( obj, ch->in_room );
  act( "You open the hatch and leave $p", ch, obj, NULL, TO_CHAR );
  act( "$n opens the hatch and leaves $p", ch, obj, NULL, TO_ROOM );
  WAIT_STATE(ch,20);
  return;
}

void do_fly( CHAR_DATA *ch, char *argument )
{ int dir = DIR_NORTH, wait;
  ROOM_INDEX_DATA *location;
  int mod = 0;
  char arg[MAX_INPUT_LENGTH];

  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "But you're not in a suit.\n\r", ch );
    return;
  }
  if ( ch->position < POS_FIGHTING )
  {
    stc( "You're too relaxed.\n\r", ch );
    return;
  }
  if ( IS_TIED(ch) )
  {
    stc( "Your suit has been immobilized!\n\r", ch );
    return;
  }

  argument = one_argument( argument, arg );
  if ( arg[0] == '\0' )
  {
    stc( "Fly where?\n\r", ch );
    return;
  }
  if ( !str_prefix( arg, "north" ) )
    dir = DIR_NORTH;
  else if ( !str_prefix( arg, "east" ) )
    dir = DIR_EAST;
  else if ( !str_prefix( arg, "south" ) )
    dir = DIR_SOUTH;
  else if ( !str_prefix( arg, "west" ) )
    dir = DIR_WEST;
  else if ( !str_prefix( arg, "up" ) )
    dir = DIR_UP;
  else if ( !str_prefix( arg, "down" ) )
    dir = DIR_DOWN;
  else if ( !str_prefix( arg, "home" ) )
  { if ( ( location = get_room_index( ch->pcdata->extras[6] ) ) == NULL )
    { send_to_char( "You are completely lost.\n\r", ch );
      return;
    }
    if ( ch->pcdata->extras[TIMER] > 16 )
    { send_to_char( "The gods do not heed the prayers of cowards.\n\r", ch );
      return;
    }
    if ( IS_SET(ch->pcdata->actnew,NEW_RETIRED) )
    {
      stc( "You're already in the home.\n\r", ch );
      return;
    }
    if ( ch->in_room == location )
      return;
    if ( IS_SET(ch->in_room->room_flags, ROOM_NO_RECALL) )
    {
        send_to_char( "God has forsaken you.\n\r", ch );
        return;
    }

    if ( ch->fighting != NULL )
    {
      send_to_char( "Duhhhhhh what? don't you mean FLEE?\n\r", ch );
      return;
    }

    ch->move -= 50;
    act( "$n disappears.", ch, NULL, NULL, TO_ROOM );
    char_from_room( ch );
    char_to_room( ch, location );
    act( "$n appears in the room.", ch, NULL, NULL, TO_ROOM );
    do_look( ch, "auto" );
    return;
  }
  else
  { send_to_char( "You can't fly that way!\n\r", ch );
    return;
  }

  if ( ch->in_room->exit[dir] == NULL
  ||   ch->in_room->exit[dir]->to_room == NULL )
  {
    send_to_char( "Alas, you cannot fly that way.\n\r", ch );
    return;
  }

  if ( ch->pcdata->suit[SUIT_FUEL] <= 0 )
  {
    stc( "But you're out of fuel!\n\r", ch );
    return;
  }
  if ( ch->fighting != NULL )
  {
    CHAR_DATA *victim = ch->fighting;
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    char buf[MAX_STRING_LENGTH];
    int attackers = 0;

    for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
    { vch_next = vch->next_in_room;
      if ( vch->fighting == ch )
      attackers++;
    }

    /* mod is for attackers Over the required first */
    attackers = UMAX(0,attackers - 1);

    if ( IS_NPC(ch->fighting) )
      attackers++;

    /* Karma disabled
    if ( !IS_NPC(ch) )
      mod += ch->pcdata->extras[PUSSY];
    */
 
    if ( number_percent() > (40 + mod + attackers*20) )
    { act( "You fail!", ch, NULL, victim, TO_CHAR );
      act( "$n attempts to fly away.", ch, NULL, victim, TO_VICT );
      act( "$n attempts to fly away.", ch, NULL, victim,TO_NOTVICT);
      WAIT_STATE(ch,8);
      return;
    }
 
    if ( !IS_NPC(ch) && !IS_NPC(victim) )
    { switch( attackers )
      { case 0:
	  sprintf( buf, "%s is fleeing in terror from %s.", ch->name, victim->name );
	  break;
	case 1:
 	  sprintf( buf, "%s is on the run from %s's group.", ch->name, victim->name );
 	  break;
 	case 2:
 	  sprintf( buf, "%s is running for their life from %s's posse.", ch->name, victim->name );
 	  break;
 	default:
 	  sprintf( buf, "%s has successfully evaded %s's gangbang.", ch->name, victim->name );
 	  break;
      }
 	do_info( ch, buf );
    }
    stop_fighting( ch, TRUE ); 
  }

  wait = 4 - ((suit_table[ch->pcdata->suit[SUIT_NUMBER]].speed - 95)/15);
  wait = UMAX( wait, 1 );
  move_char( ch, dir );
  WAIT_STATE(ch,wait);
  return;
}


void do_status( CHAR_DATA *ch, char *argument )
{ CHAR_DATA *victim;
  char buf[MAX_STRING_LENGTH];
  char *con;
  int suit, cond, i, j;

  if ( IS_NPC(ch) )
    return;
  if ( ch->level < 20 )
    victim = ch;
  else if ( argument[0] == '\0' )
    victim = ch;
  else if ( ( victim = get_char_room( ch, argument ) ) == NULL )
  { send_to_char( "They aren't here.\n\r", ch );
    return;
  }

  if ( IS_NPC(victim ) )
  { send_to_char( "they're a mob.\n\r", ch );
    return;
  }
  suit = victim->pcdata->suit[SUIT_NUMBER];
  cond = 0; j = 1;
  for ( i = 0; i < 12; i++ )
  { if ( IS_SET(victim->pcdata->suit[SUIT_COND],j) )
      cond++;
    j *= 2;
  }
  if ( cond == 0 )
    con = "Perfect";
  else if ( cond < 3 )
    con = "Good";
  else if ( cond < 6 )
    con = "Damaged";
  else if ( cond < 9 )
    con = "Seriously Damaged";
  else if ( cond < 12 )
    con = "Critically Damaged";
  else
    con = "Seriously fucked up";
  send_to_char( "`d------------------------------------------------------------`n\n\r", ch);
  sprintf( buf, "        Mobile Suit: %s    Condition: %s\n\r\n\r", suit_table[suit].name, con);
  send_to_char( buf, ch  );
  sprintf( buf, "                Missiles:  %4d  Armor:    %4d  Fuel: %4d\n\r", 
  	victim->pcdata->suit[14], victim->pcdata->suit[2], victim->pcdata->suit[3] );
  send_to_char( buf, ch );
  sprintf( buf, "Bullets:  %4d  Shells:    %4d  Plasma:   %4d  Beam: %4d\n\r\n\r",
 	victim->pcdata->suit[5],        victim->pcdata->suit[6],
  	victim->pcdata->suit[7],        victim->pcdata->suit[8] );
  send_to_char( buf, ch );
  sprintf( buf, "Weapon:  %5d  Combat:   %5d  Reflex:  %5d  Aim: %5d\n\r",
 	victim->pcdata->suit[10],        victim->pcdata->suit[11],
  	victim->pcdata->suit[12],        victim->pcdata->suit[13] );
  send_to_char( buf, ch );
  send_to_char( "`d------------------------------------------------------------`n\n\r", ch );

  return;
}


void do_load( CHAR_DATA *ch, char *argument )
{
  OBJ_DATA *obj;
  int max;

  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You must be in a mobile suit to load munitions.\n\r", ch );
    return;
  }
  if ( ch->fighting != NULL )
  { send_to_char( "You can't do that in the middle of a fight.\n\r", ch );
    return;
  }
  if ( argument[0] == '\0' )
  { send_to_char( "Load up what?\n\r", ch );
    return;
  }
  if ( ( obj = get_obj_carry( ch, argument ) ) == NULL )
  { send_to_char( "You aren't carrying that.\n\r", ch );
    return;
  }
  if ( obj->item_type != ITEM_MUNITION )
  { send_to_char( "You can't load that into a mobile suit.\n\r", ch );
    return;
  }

  if ( obj->value[0] != 3 && obj->value[0] != 5 && obj->value[0] != 6 &&
       obj->value[0] != 7 && obj->value[0] != 8 && obj->value[0] != 14 )
  { send_to_char( "don't load that, it'll fuck up your suit.\n\r", ch );
    return;
  }
  max = 1000;
  if ( obj->value[0] == SUIT_MISSILES )
  {
    switch( ch->pcdata->suit[SUIT_NUMBER] )
    {
      case 2:	max = 8;	break;
      case 11:	max = 64;	break;
      case 12:	max = 2;	break;
      case 15:	max = 64;	break;
      default:	max = 0;	break;
    }
  }
  if ( ch->pcdata->suit[obj->value[0]] + obj->value[1] > max )
  { send_to_char( "You can't load up any more.\n\r", ch );
    return;
  }
  ch->pcdata->suit[obj->value[0]] += obj->value[1];

  act( "You load $p into your mobile suit.", ch, obj, NULL, TO_CHAR );
  act( "$n loads $p into $s mobile suit.", ch, obj, NULL, TO_ROOM );
  if ( obj->value[0] == SUIT_MISSILES )
  {
    WAIT_STATE(ch,8);
  }
  extract_obj( obj );
  return;
}

void do_ready( CHAR_DATA *ch, char *argument )
{ int weap;
  char *buf;

  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You can only do that in a mobile suit.\n\r", ch );
    return;
  }
  if ( argument[0] == '\0' )
  { send_to_char( "Ready what?\n\r", ch );
    return;
  }
  if ( !str_prefix( argument, "machine gun" ) )
  { weap = MS_MACHINE_GUN;
    buf = "105mm machine gun";
  }
  else if ( !str_prefix( argument, "beam rifle" ) )
  { weap = MS_BEAM_RIFLE;
    buf = "beam rifle";
  }
  else if ( !str_prefix( argument, "dobergun" ) )
  { weap = MS_DOBERGUN;
    buf = "dobergun";
  }
  else if ( !str_prefix( argument, "beam cannon" ) )
  { weap = MS_BEAM_CANNON;
    buf = "beam cannon";
  }
  else if ( !str_prefix( argument, "laser cannon" ) )
  { weap = MS_LASER_CANNON;
    buf = "laser cannon";
  }
  else if ( !str_prefix( argument, "heavy beam cannon" ) )
  { weap = MS_HEAVY_BEAM_CANNON;
    buf = "heavy beam cannon";
  }
  else if ( !str_prefix( argument, "vulcan" ) )
  { weap = MS_VULCAN;
    buf = "vulcan cannons";
  }
  else if ( !str_prefix( argument, "beam sabre" ) )
  { weap = MS_BEAM_SABRE;
    buf = "beam sabre";
  }
  else if ( !str_prefix( argument, "beam sword" ) )
  { weap = MS_BEAM_SWORD;
    buf = "beam sword";
  }
  else if ( !str_prefix( argument, "crasher" ) )
  { weap = MS_CRASHER;
    buf = "crasher";
  }
  else if ( !str_prefix( argument, "buster rifle" ) )
  { weap = MS_BUSTER_RIFLE;
    buf = "buster rifle";
  }
  else if ( !str_prefix( argument, "twin buster rifle" ) )
  { weap = MS_TWIN_BUSTER_RIFLE;
    buf = "twin buster rifle";
  }
  else if ( !str_prefix( argument, "beam scythe" ) )
  { weap = MS_BEAM_SCYTHE;
    buf = "beam scythe";
  }
  else if ( !str_prefix( argument, "gatling gun" ) )
  { weap = MS_GATLING_GUN;
    buf = "gatling gun";
  }
  else if ( !str_prefix( argument, "miniguns" ) )
  { weap = MS_MINIGUNS;
    buf = "miniguns";
  }
  else if ( !str_prefix( argument, "heat shotels" ) )
  { weap = MS_HEAT_SHOTELS;
    buf = "heat shotels";
  }
  else if ( !str_prefix( argument, "beam glaive" ) )
  { weap = MS_BEAM_GLAIVE;
    buf = "beam glaive";
  }
  else if ( !str_prefix( argument, "dragon fang" ) )
  { weap = MS_DRAGON_FANG;
    buf = "dragon fang";
  }
  else if ( !str_prefix( argument, "heat rod" ) )
  { weap = MS_HEAT_ROD;
    buf = "heat rod";
  }
  else if ( !str_prefix( argument, "flamethrower" ) )
  {
    weap = MS_FLAMETHROWER;
    buf = "flamethrower";
  }

  else
  { send_to_char( "That's not a known mobile suit weapon.\n\r", ch );
    return;
  }

  if ( !IS_SET(ch->pcdata->suit[SUIT_EQ],weap) )
  { send_to_char( "Your mobile suit is not equipped with one of those.\n\r", ch );
    return;
  }

  ch->pcdata->suit[SUIT_READY] = weap;
  act( "You ready your $T.", ch, NULL, buf, TO_CHAR );
  act( "$n readies $s $T.", ch, NULL, buf, TO_ROOM );
  return;
}

void do_fire( CHAR_DATA *ch, char *argument )
{ CHAR_DATA *vch;
  CHAR_DATA *vch_next;
  CHAR_DATA *victim = NULL;
  ROOM_INDEX_DATA *in_room;
  ROOM_INDEX_DATA *to_room;
  EXIT_DATA *pexit;
  extern char * const dir_name[];
  char buf1[MAX_STRING_LENGTH];
  char buf2[MAX_STRING_LENGTH];
  char buf3[MAX_STRING_LENGTH];
  char *buf;
  int dam, dam1, wait, ammo, i, j, k, type;
  int aim, weapon, attacks, count, cost, dir = 0, range = 0;
  bool hitpc = FALSE;
  bool targeted = FALSE;

  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You can't do that without a mobile suit.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_READY] == 0 )
  { send_to_char( "You don't have a weapon readied.", ch );
    return;
  }
  cost = 1;
  range = 0;
  attacks = 1;
  aim = ch->pcdata->suit[SUIT_AIM];
  weapon = suit_table[ch->pcdata->suit[SUIT_NUMBER]].weapon;

  if ( ch->pcdata->suit[SUIT_READY] == MS_FLAMETHROWER )
  {
    fire_flamethrower( ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_READY] == MS_MINIGUNS )
  {
    fire_miniguns( ch, argument );
    return;
  }

  switch( ch->pcdata->suit[SUIT_READY] )
  { case MS_MACHINE_GUN:
 	dam = dice( 1, 50 + aim / 5 ) + (weapon-90)*5;
 	buf = "machine gun";
 	wait = 6;
 	ammo = SUIT_BULLETS;
 	range = 1;
 	type = DAM_BULLETS;
 	attacks = 5;
 	break;
    case MS_BEAM_RIFLE:
    	dam = 150 + dice( 8, aim / 5 ) + (weapon-90)*10;
    	buf = "beam rifle";
    	wait = 6;
    	ammo = SUIT_BEAM;
    	cost = 1;
    	range = 1;
    	type = DAM_BEAMRIFLE;
    	break;
    case MS_BEAM_CANNON:
    	dam = 650 + dice( 5, aim / 3 ) + (weapon-90)*10;
    	buf = "beam cannon";
    	wait = 6;
    	ammo = SUIT_BEAM;
    	cost = 3;
    	range = 2;
    	type = DAM_BEAMRIFLE;
    	break;
    case MS_LASER_CANNON:
    	dam = 1500 + dice( 8, aim / 2 ) + (weapon-90)*10;
    	buf = "laser cannon";
    	wait = 8;
    	ammo = SUIT_PLASMA;
    	cost = 1;
    	range = 1;
    	type = DAM_BEAMRIFLE;
    	break;
    case MS_HEAVY_BEAM_CANNON:
    	dam = 1500 + dice( 3, aim ) + (weapon-90)*50;
    	buf = "heavy beam cannon";
    	wait = 12;
    	ammo = SUIT_BEAM;
    	cost = 10;
    	range = 10;
    	type = DAM_BEAMRIFLE;
    	break;
    case MS_VULCAN:
    	dam = dice( 2, 50 + aim / 5 ) + (weapon-90)*5;
    	buf = "vulcan cannon";
    	wait = 4;
    	ammo = SUIT_BULLETS;
    	cost = 1;
    	range = 1;
    	type = DAM_BULLETS;
    	attacks = 8;
    	break;
    case MS_DOBERGUN:
    	dam = dice( 3, aim ) + (weapon-90)*10;
    	buf = "dobergun";
    	wait = 16-((suit_table[ch->pcdata->suit[SUIT_NUMBER]].speed-80)/10);
    	ammo = SUIT_SHELLS;
    	cost = 1;
    	range = 0;
    	type = DAM_SHELLS;
    	break;
    case MS_BUSTER_RIFLE:
    	dam = aim + dice(3,aim) + (weapon-90)*10;
    	buf = "buster rifle";
    	wait = 12;
    	ammo = SUIT_BEAM;
    	cost = 200;
    	range = 3;
    	type = DAM_BEAMRIFLE;
    	break;
    case MS_TWIN_BUSTER_RIFLE:
    	dam = aim + dice(6,aim) + (weapon-90)*20;
    	buf = "twin buster rifle";
    	wait = 8;
    	ammo = SUIT_BEAM;
    	cost = 200;
    	range = 10;
    	type = DAM_BEAMRIFLE;
    	break;
    case MS_GATLING_GUN:
        dam = dice( 2, 50 + aim/3 ) + (weapon-90)*5;
        buf = "gatling gun";
        wait = 6;
        ammo = SUIT_BULLETS;
        cost = 1;
        range = 2;
        type = DAM_BULLETS;
        attacks = 10;
        break;
    case MS_MINIGUNS:
        dam = dice( 2, 50 + aim/4 ) + (weapon-90)*5;
        buf = "miniguns";
        wait = 8;
        ammo = SUIT_BULLETS;
        cost = 1;
        range = 0;
        type = DAM_BULLETS;
	break;
    default:
    	send_to_char( "You can't fire that!\n\r", ch );
    	buf = "fuck this";
    	wait = 12;
    	ammo = SUIT_BULLETS;
    	range = 0;
    	type = TYPE_HIT;
    	return;
  }

  if ( ch->fighting != NULL )
  {
    victim = ch->fighting;
    if ( !IS_NPC(victim) && victim->level < 2 )
    { send_to_char( "Not on mortals.\n\r", ch );
      return;
    }
    targeted = TRUE;
  }
  else if ( argument[0] == '\0' )
  {
    send_to_char( "Fire at whom?\n\r", ch );
    WAIT_STATE( ch, 4 );
    return;
  }
  else if ( !str_cmp( argument, "north" ) )
    dir = DIR_NORTH;
  else if ( !str_cmp( argument, "east" ) )
    dir = DIR_EAST;
  else if ( !str_cmp( argument, "south" ) )
    dir = DIR_SOUTH;
  else if ( !str_cmp( argument, "west" ) )
    dir = DIR_WEST;
  else if ( !str_cmp( argument, "up" ) )
    dir = DIR_UP;
  else if ( !str_cmp( argument, "down" ) )
    dir = DIR_DOWN;
  else if ( (victim = get_char_room(ch,argument)) == NULL )
  { send_to_char( "Fire at whom?\n\r", ch );
    return;
  }
  else
    targeted = TRUE;


  if ( !targeted && range <= 0 )
  { send_to_char( "You may only fire that at nearby targets.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[ammo] <= cost )
  { send_to_char( "You don't have enough ammunition to do that!\n\r", ch );
    return;
  }

  /* break for special attacks for gundams */
  if ((ch->pcdata->suit[SUIT_READY] == MS_BUSTER_RIFLE
    || ch->pcdata->suit[SUIT_READY] == MS_TWIN_BUSTER_RIFLE)
    && !targeted )
  { fire_buster( ch, dam, dir );
    return;
  }

  if ( targeted )
  { sprintf( buf1, "You fire your %s at $N!", buf );
    sprintf( buf2, "$n fires $s %s at you!", buf );
    sprintf( buf3, "$n fires $s %s at $N.", buf );
    act( buf1, ch, NULL, victim, TO_CHAR );
    act( buf2, ch, NULL, victim, TO_VICT );
    act( buf3, ch, NULL, victim, TO_NOTVICT );
  }
  else
  { sprintf( buf1, "You fire your %s to the %s!", buf, dir_name[dir] );
    sprintf( buf2, "$n fires $s %s to the %s!", buf, dir_name[dir] ); 
    act( buf1, ch, NULL, NULL, TO_CHAR );
    act( buf2, ch, NULL, NULL, TO_ROOM );
  }

  dam1 = dam;
  if ( targeted )
  {

    if ( !IS_NPC(victim) )
    {
      hitpc = TRUE;
      if ( victim->level < 2 )
      {
        stc( "Firing on mortals isn't nice.\n\r", ch );
        return;
      }
    }

    for ( i = 0; i < attacks && victim && ch->pcdata->suit[ammo] >= cost; i++ )
    {
      if ( attacks > 1 )
        dam1 = dice( 5, dam ) / 5;

      if ( !IS_NPC(victim) && number_percent() < (victim->pcdata->body-60)
        && !IS_SUIT(victim) && type == DAM_BULLETS )
      {
        if ( !IS_SET( victim->act, PLR_BRIEF ) )
          act( "You dodge $n's bullets.",  ch, NULL, victim, TO_VICT    );
        if ( !IS_SET( ch->act, PLR_BRIEF ) )
          act( "$N dodges your bullets.", ch, NULL, victim, TO_CHAR    );
      }
      else if ( !shields_check( ch, victim, type ) )
      {
        if ( IS_NPC(victim)
          && ch->in_room->clan != ch->pcdata->clan[CLAN]
          && dice(1, 1+aim + isquare(aim)) >= aim
          && aim < 2500
          && ch->in_room == victim->in_room
          && aim < ch->pcdata->extras2[EVAL]*45 )
        {
          ch->pcdata->suit[SUIT_AIM]++;
        }
        damage( ch, victim, dam1, type );
      }

      ch->pcdata->suit[ammo] -= cost;
    }
  }
  else
  { in_room = ch->in_room;
    if ( ( pexit = in_room->exit[dir] ) == NULL
      || ( pexit->to_room ) == NULL )
    { send_to_char( ".. and manage to hit the wall.\n\r", ch );
      return;
    }
    for ( i = 0; i < range; i++ )
    { /* check for a room being in the direction */
      if ( ( pexit = in_room->exit[dir] ) == NULL
        || ( to_room = pexit->to_room ) == NULL )  
      {
        continue;
      }
      /* no looping through loop rooms */
      if ( in_room == to_room )
      {
        continue;
      }
      /* find out how many people thre are in the room */
      count = 0;
      for ( vch = to_room->people; vch != NULL; vch = vch_next )
      { vch_next = vch->next_in_room;
        count++;
      }

      /* now pick a victim */
      if ( count > 0 )
      count = dice(1,count);
      vch = to_room->people;
      dam1 = dam;
      if ( count > 0 )
      { for ( j = 1; j < count; j++ )
          vch = vch->next_in_room;
        for ( k = 0; k < attacks && vch && ch->pcdata->suit[ammo] >= cost; k++ )
        { /* randomize damage for multiple attacks */
          if ( attacks > 1 )
            dam1 = dice( 5, dam ) / 5;
          if ( ch->pcdata->suit[ammo] >= cost && !shields_check( ch, vch, type ) ) 
          { 
            if ( !IS_NPC(vch) )
              hitpc = TRUE;

            if ( !IS_NPC(vch) && number_percent() < (vch->pcdata->body-60)
              && !IS_SUIT(vch) && type == DAM_BULLETS )
            {
              if ( !IS_SET( vch->act, PLR_BRIEF ) )
                act( "You dodge $n's bullets.", ch, NULL, vch, TO_VICT);
              if ( !IS_SET( ch->act, PLR_BRIEF ) )
                act( "$N dodges your bullets.", ch, NULL, vch, TO_CHAR );
            }
            else
              damage( ch, vch, dam1, type );

            if ( vch != NULL && vch->fighting == ch
            && !(!IS_NPC(vch) && IS_SET(vch->act,PLR_FIREBACK)) )
              stop_fighting( vch, FALSE );

            ch->pcdata->suit[ammo] -= cost;
          }
        } 
      }
      /* set the stage for 2nd and 3rd room attacks */
      in_room = to_room;
    }
  }



  WAIT_STATE(ch,wait);
  return;
}

void do_shell( CHAR_DATA *ch, char *argument )
{ CHAR_DATA *vch;
  CHAR_DATA *vch_next;
  ROOM_INDEX_DATA *in_room;
  ROOM_INDEX_DATA *to_room;
  extern char * const dir_name[];
  char arg1[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  EXIT_DATA *pexit;
  int range, aim, i, dam, dir;
  bool hitpc = FALSE;

  if ( !IS_SUIT(ch) )
  { send_to_char( "You can't do that without a mobile suit!\n\r", ch );
    return;
  }
  aim = ch->pcdata->suit[SUIT_AIM];
  if ( ch->fighting != NULL )
  { send_to_char( "You can't shell while in combat.\n\r", ch );
    return;
  }
  if ( !IS_SET(ch->pcdata->suit[SUIT_READY],MS_DOBERGUN) )
  { send_to_char( "You need a Dobergun to shell.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_SHELLS] < 1 )
  { send_to_char( "You have no shells to fire!\n\r", ch );
    return;
  }
  if ( argument[0] == '\0' )
  { send_to_char( "Syntax is shell <direction> <number of rooms>.\n\r", ch );
    return;
  }
  argument = one_argument( argument, arg1 );
  argument = one_argument( argument, arg2 );
  if ( arg1[0] == '\0' || arg2[0] == '\0' )
 { send_to_char( "Syntax is shell <direction> <number of rooms>.\n\r", ch );
    return;
  }
  if ( !is_number( arg2 ) )
  { send_to_char( "The distance must be an integer between 1 and 50.\n\r", ch );
    return;
  }
  range = atoi( arg2 );
  if ( range <= 0 || range > 50 )
  { send_to_char( "Acceptable ranges are between 1 and 50.\n\r", ch );
    return;
  }
  if ( !str_prefix( arg1, "north" ) )
    dir = DIR_NORTH;
  else if ( !str_prefix( arg1, "east" ) )
    dir = DIR_EAST;
  else if ( !str_prefix( arg1, "south" ) )
    dir = DIR_SOUTH;
  else if ( !str_prefix( arg1, "west" ) )
    dir = DIR_WEST;
  else if ( !str_prefix( arg1, "up" ) )
    dir = DIR_UP;
  else if ( !str_prefix( arg1, "down" ) )
    dir = DIR_DOWN;  
  else
  { send_to_char( "That isn't a direction.\n\r", ch );
    return;
  }
  act( "You fire a shell $T!", ch, NULL, dir_name[dir], TO_CHAR );
  act( "$n fires a shell $T!", ch, NULL, dir_name[dir], TO_ROOM );
  in_room = ch->in_room;
  if ( ( pexit = in_room->exit[dir] ) == NULL
    || ( pexit->to_room ) == NULL )
  { send_to_char( "You fire against the wall.\n\r", ch );
    return;
  } 
  to_room = in_room;
  for ( i = 0; i < range; i++ )
  { if ( ( pexit = in_room->exit[dir] ) == NULL
      || ( to_room = pexit->to_room ) == NULL )  
    { send_to_char( "Your shell smashes into a wall.\n\r", ch );
      return;
    }
    in_room = to_room;
  }
  if ( to_room->people == NULL )
  { send_to_char( "Your shell explodes harmlessly.\n\r", ch );
    WAIT_STATE( ch, 20-((suit_table[ch->pcdata->suit[SUIT_NUMBER]].speed-90)/5) );
    return;
  }
  else
  { act( "A shell arcs in and explodes!", in_room->people, NULL, NULL, TO_ROOM );
    for ( vch = in_room->people; vch != NULL; vch = vch_next )
    { 
      vch_next = vch->next_in_room;

      if ( !can_see(ch,vch) )
        continue;

      dam = dice(3,aim) + (suit_table[ch->pcdata->suit[SUIT_NUMBER]].weapon - 90)*10;
      if ( !IS_NPC(vch) )
        hitpc = TRUE;

      if ( !shields_check( ch, vch, DAM_SHELLS ) )
      { 
        damage( ch, vch, dam, DAM_SHELLS );
        if ( vch != NULL && vch->fighting == ch )
          stop_fighting( vch, FALSE );
        if ( ch->fighting == vch )
          stop_fighting( ch, FALSE );
      }
    }
  }
  
  ch->pcdata->suit[SUIT_SHELLS]--;
  WAIT_STATE( ch, 20-((suit_table[ch->pcdata->suit[SUIT_NUMBER]].speed-90)/5) );  
  return;
}

void do_punch( CHAR_DATA *ch, char *argument )
{ int dam, combat, suit;
  CHAR_DATA *victim;
  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You can't do that without a mobile suit.\n\r", ch );
    return;
  }

  if ( ch->fighting != NULL )
    victim = ch->fighting;
  else if ( argument[0] == '\0' )
  { send_to_char( "Punch who?\n\r", ch );
    return;
  }
  else if ( ( victim = get_char_room( ch, argument ) ) == NULL )
  { send_to_char( "They aren't here.\n\r", ch );
    return;
  }

  combat = ch->pcdata->suit[SUIT_COMBAT];
  suit = ch->pcdata->suit[SUIT_NUMBER];
  dam = isquare( combat ) * dice(5,10) + (suit_table[suit].fight - 90)*10;
  dam += (suit_table[suit].power - 90) * 10;

  if ( IS_NPC(victim)
    && ch->in_room->clan != ch->pcdata->clan[CLAN]
    && dice(1,1+combat+isquare(combat)*2) >= combat
    && combat < 2500
    && combat < ch->pcdata->extras2[EVAL]*45 )
  {
      ch->pcdata->suit[SUIT_COMBAT]++;
  }
  damage( ch, victim, dam, TYPE_HIT );


  if ( dice(1,1+combat+isquare(combat)*2) >= combat )
    if ( combat < 2500 && victim && victim->position > POS_STUNNED
      && combat < ch->pcdata->extras2[EVAL]*45 )
      ch->pcdata->suit[SUIT_COMBAT]++;
  WAIT_STATE( ch, 5 );
  return;
}

void do_slash( CHAR_DATA *ch, char *argument )
{ int dam, weapon, suit, fuel, cost;
  CHAR_DATA *victim;
  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You can't do that without a mobile suit.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_READY] != MS_BEAM_SABRE
    && ch->pcdata->suit[SUIT_READY] != MS_BEAM_SWORD
    && ch->pcdata->suit[SUIT_READY] != MS_CRASHER
    && ch->pcdata->suit[SUIT_READY] != MS_BEAM_SCYTHE
    && ch->pcdata->suit[SUIT_READY] != MS_HEAT_SHOTELS
    && ch->pcdata->suit[SUIT_READY] != MS_BEAM_GLAIVE )
  { send_to_char( "You need a melee weapon to slash with.\n\r", ch );
    return;
  }
  if ( ch->fighting != NULL )
    victim = ch->fighting;
  else if ( argument[0] == '\0' )
  { send_to_char( "Slash who?\n\r", ch );
    return;
  }
  else if ( ( victim = get_char_room( ch, argument ) ) == NULL )
  { send_to_char( "They aren't here.\n\r", ch );
    return;
  }
  weapon = ch->pcdata->suit[SUIT_WEAPON];
  suit = ch->pcdata->suit[SUIT_NUMBER];
  cost = 1;
  dam = isquare( weapon ) * dice(5,10);
  dam += (suit_table[suit].fight-90) * 10;
  dam += (suit_table[suit].power - 90) * 10;
  fuel = SUIT_BEAM;
  switch( ch->pcdata->suit[SUIT_READY] )
  { case MS_CRASHER:
    case MS_BEAM_SABRE:		dam *= 2;	break;
    case MS_BEAM_SWORD:	dam *= 4; cost=10;	break;
    case MS_BEAM_SCYTHE:
    case MS_BEAM_GLAIVE:	dam *= 3;	break;
    case MS_HEAT_SHOTELS: fuel = SUIT_PLASMA;	break;
    default:					break;
  }
  if ( ch->pcdata->suit[fuel] < cost )
  { send_to_char( "You need at least one unit of ammo.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_READY] == MS_HEAT_SHOTELS && IS_SUIT(victim) )
    dam *= 3;

  if ( IS_NPC(victim)
    && ch->in_room->clan != ch->pcdata->clan[CLAN]
    && dice(1,+weapon+isquare(weapon)*2) >= weapon
    && weapon < 2500
    && weapon < ch->pcdata->extras2[EVAL]*45 )
  {
      ch->pcdata->suit[SUIT_WEAPON]++;
  }

  damage( ch, victim, dam, DAM_BEAMSABRE );
  ch->pcdata->suit[fuel] -= cost; 
  if ( ch->pcdata->suit[SUIT_READY] == MS_HEAT_SHOTELS
    && victim && ch->pcdata->suit[fuel] > 0 )
  {
    dam = dam/2 + dice(1,dam);
    damage( ch, victim, dam, DAM_BEAMSABRE );
    ch->pcdata->suit[fuel]--;
  }

  WAIT_STATE( ch, 12 - (suit_table[ch->pcdata->suit[SUIT_NUMBER]].speed-100)/10 );
  return;
}

void do_install( CHAR_DATA *ch, char *argument )
{ int item, suit, i, j;
  bool match = FALSE;
  OBJ_DATA *obj;

  if ( IS_NPC(ch) )
    return;
  if ( !IS_SUIT(ch) )
  { send_to_char( "You can only install equipment in a mobile suit.\n\r", ch );
    return;
  }
  if ( ch->fighting != NULL )
  { send_to_char( "You can't do that in combat!\n\r", ch );
    return;
  }
  if ( argument[0] == '\0' )
  { send_to_char( "Install what?\n\r", ch );
    return;
  }
  if  ( ( obj = get_obj_carry( ch, argument ) ) == NULL )
  { send_to_char( "You don't have that.\n\r", ch );
    return;
  }
  if ( obj->item_type != ITEM_ACCESSORY )
  { send_to_char( "You can't install that in a mobile suit.\n\r", ch );
    return;
  }
  suit = ch->pcdata->suit[SUIT_NUMBER];
  item = obj->value[0];
  if ( item == 0 )
  { if ( ch->pcdata->suit[SUIT_COND] == 0
      && ch->pcdata->suit[SUIT_ARMOR] >= (suit_table[suit].armor * 15) )
    { send_to_char( "Your mobile suit needs no repairs.\n\r", ch );
      return;
    }
    ch->pcdata->suit[SUIT_ARMOR] = suit_table[suit].armor * 15;
    j = 1;
    for ( i = 0; i < 12 && !match; i++ )
    { if ( IS_SET(ch->pcdata->suit[SUIT_COND],j) )
      { REMOVE_BIT(ch->pcdata->suit[SUIT_COND],j);
        match = TRUE;
      }
      j *= 2;
    }
    act( "You patch up your $T with a field repair kit.",
    	ch, NULL, suit_table[suit].name, TO_CHAR );
    act( "$n patches up $s $T with a field repair kit.",
    	ch, NULL, suit_table[suit].name, TO_ROOM );
    extract_obj( obj );
    WAIT_STATE( ch, 20 );
    return;
  }
  if ( !IS_SET( suit_table[suit].eq, item ) )
  { send_to_char( "Your mobile suit is not equipped to use this.\n\r", ch );
    return;
  }
  if ( IS_SET( ch->pcdata->suit[SUIT_EQ], item ) )
  { send_to_char( "your mobile suit already has one of those.\n\r", ch );
    return;
  }

  SET_BIT(ch->pcdata->suit[SUIT_EQ],item);
  act( "You install $p in your mobile suit.", ch, obj, NULL, TO_CHAR );
  act( "$n installs $p in $s mobile suit.", ch, obj, NULL, TO_ROOM );
  extract_obj( obj );
  return;
}

void fire_miniguns( CHAR_DATA *ch, char *argument )
{
  CHAR_DATA *victim;
  CHAR_DATA *vch;
  CHAR_DATA *vch_next;
  char arg[MAX_INPUT_LENGTH];
  int aim, bullets, i;

  if ( IS_NPC(ch) || !IS_SUIT(ch) )
    return;

  if ( ch->pcdata->suit[SUIT_READY] != MS_MINIGUNS )
  {
    stc( "You don't have Miniguns readied.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_BULLETS] < 1 )
  {
    stc( "You're out of ammo!\n\r", ch );
    return;
  }

  argument = one_argument( argument, arg );

  if ( ch->fighting != NULL )
    victim = ch->fighting;
  else
  {
    if ( arg[0] == '\0' )
    {
      stc( "Fire at who?\n\r", ch );
      return;
    }
    if ( (victim = get_char_room(ch,arg)) == NULL )
    {
      stc( "They aren't here.\n\r", ch );
      WAIT_STATE(ch,4);
      return;
    }
  }

  bullets = ch->pcdata->suit[SUIT_BULLETS];
  aim = ch->pcdata->suit[SUIT_AIM];

  act( "You open up with a burst of minigun fire.", ch, NULL, NULL, TO_CHAR );
  act( "$n opens up on the room with a burst of minigun fire!", ch, NULL, NULL, TO_ROOM );
  for ( vch = ch->in_room->people; vch != NULL && bullets > 0; vch = vch_next )
  {
    vch_next = vch->next_in_room;

    if ( !IS_NPC(vch) && vch->level < 2 )
      continue;
    if ( !is_same_group(victim,vch) && !(IS_NPC(vch) && IS_NPC(victim))  )
      continue;

    for ( i = 0; i < 6 && vch != NULL && bullets > 0; i++ )
    {
      bullets--;
      ch->pcdata->suit[SUIT_BULLETS]--;
      damage( ch, vch, dice(3,50+aim/5), DAM_BULLETS );
    }
  }

  WAIT_STATE(ch,10);
  return;
}

void fire_buster( CHAR_DATA *ch, int dam, int dir )
{ ROOM_INDEX_DATA *in_room;
  ROOM_INDEX_DATA *to_room;
  EXIT_DATA *pexit;
  CHAR_DATA *vch;
  CHAR_DATA *vch_next;
  char buf1[MAX_STRING_LENGTH];
  char buf2[MAX_STRING_LENGTH];
  int i, cost, range, wait;
  extern char * const dir_name[];
  bool hitpc = FALSE;

  if ( ch->pcdata->suit[SUIT_READY] == MS_BUSTER_RIFLE )
  { cost = 200;
    range = 3;
    wait = 14;
  }
  else
  { cost = 250;
    range = 10;
    wait = 8;
  }

  if ( ch->pcdata->suit[SUIT_BEAM] < cost )
  { send_to_char( "You don't have enough beam energy.\n\r", ch );
    return;
  }

  in_room = ch->in_room;
  if ( ( pexit = in_room->exit[dir] ) == NULL
    || ( pexit->to_room ) == NULL )
  { send_to_char( ".. and manage to hit the wall.\n\r", ch );
    return;
  }
  else
  { sprintf( buf1, "You fire your buster rifle to the %s!", dir_name[dir] );
    sprintf( buf2, "$n fires $s buster rifle to the %s!", dir_name[dir] );
    act( buf1, ch, NULL, NULL, TO_CHAR );
    act( buf2, ch, NULL, NULL, TO_ROOM );
  }
  for ( i = 0; i < range; i++ )
  { /* check for a room being in the direction */
    if ( ( pexit = in_room->exit[dir] ) == NULL
      || ( to_room = pexit->to_room ) == NULL )
    { continue;
    }
    /* No looping fire */
    if ( to_room == in_room )
    {
      continue;
    }
    for ( vch = to_room->people; vch != NULL; vch = vch_next )
    {
      vch_next = vch->next_in_room;
      if ( vch != NULL  )
      {
        if ( !can_see(ch,vch) )
          continue;
        if ( !IS_NPC(vch) )
          hitpc = TRUE;
        damage( ch, vch, dam, DAM_BEAMRIFLE );
        if ( vch != NULL && vch->fighting == ch
          && !(!IS_NPC(vch) && IS_SET(vch->act,PLR_FIREBACK)) )
          stop_fighting( vch, FALSE );
      }
    }
    /* set the stage for 2nd and 3rd room attacks */
    in_room = to_room;
  }

  ch->pcdata->suit[SUIT_BEAM] -= cost;
  WAIT_STATE(ch,wait);
  return;
}

bool shields_check( CHAR_DATA *ch, CHAR_DATA *victim, int dt )
{
  if ( IS_NPC(victim) )
    return FALSE;
  if ( dt != DAM_BULLETS && dt != DAM_SHELLS )
    return FALSE;

  if ( IS_CLASS(victim,CLASS_SORCERER) && !IS_SUIT(victim) )
    if ( IS_AFFECTED(victim,AFF_WINDY_SHIELD) )
      if ( number_percent() < victim->pcdata->powers[SCHOOL_WIND] )
      { if ( !IS_SET( ch->act, PLR_BRIEF ) )
          act( "$N's windy shield deflects your bullets.", ch, NULL, victim, TO_CHAR );
        if ( !IS_SET( victim->act, PLR_BRIEF ) )
          act( "Your windy shield deflects $n's bullets!", ch, NULL, victim, TO_VICT );
        return TRUE;
      }

  if ( IS_SUIT(victim) && IS_SET(victim->pcdata->suit[SUIT_EQ],MS_SHIELDS) )
    if ( victim->pcdata->suit[SUIT_PLASMA] > 0 )
      if ( number_percent() < 75 )
      { victim->pcdata->suit[SUIT_PLASMA]--;
        if ( !IS_SET( ch->act, PLR_BRIEF ) )
          act( "$N's planet defensors deflect your bullets.", ch, NULL, victim, TO_CHAR );
        if ( !IS_SET( victim->act, PLR_BRIEF ) )
          act( "Your planet defensors deflect $n's bullets!", ch, NULL, victim, TO_VICT );
        return TRUE;
      }

  return FALSE;
}

bool is_cloaked( CHAR_DATA *ch, CHAR_DATA *victim )
{ 
  OBJ_DATA *obj;
  int i, j, cond;

  /* Mriswith cloak */
  if ( !IS_SUIT(ch)
    && ((obj = get_eq_char( ch, WEAR_ABOUT )) != NULL)
    && obj->pIndexData->vnum == OBJ_VNUM_MRISWITH
    && ch->fighting == NULL
    && ch->position == POS_STANDING
    && ((IS_NPC(victim) && victim->level < 90) || ch == victim) )
  {
    return TRUE;
  }


  /* Deathscythe cloaker */
  if ( !IS_SUIT(ch) )
    return FALSE;
  if ( !IS_SET(ch->pcdata->suit[SUIT_EQ],MS_CLOAKER) )
    return FALSE;
  if ( ch->fighting != NULL )
    return FALSE;
  if ( IS_NPC(victim) && victim->level >= 100 )
    return FALSE;

  cond = 0; j = 1;
  for ( i = 0; i < 12; i++ )
  { if ( IS_SET(ch->pcdata->suit[SUIT_COND],j) )
     cond++;
    j *= 2;
  }
  if ( cond >= 6 ) // Serious condition
    return FALSE;

  return TRUE;
}

void do_wreck( CHAR_DATA *ch, char *argument )
{
  char arg[MAX_INPUT_LENGTH];
  char *buf;
  OBJ_DATA *suit;
  int i, j, part;
  bool match = FALSE;

  argument = one_argument( argument, arg );

  if ( arg[0] == '\0' )
  { send_to_char( "Wreck what?\n\r", ch );
    return;
  }
  if ( ( suit = get_obj_list( ch, arg, ch->in_room->contents ) ) == NULL )
  { send_to_char( "That isn't here.\n\r", ch );
    return;
  }
  if ( suit->item_type != ITEM_SUIT )
  { send_to_char( "You can't wreck that.\n\r", ch );
    return;
  }

  if ( IS_SET(ch->in_room->room_flags, ROOM_HANGER) )
  {
    if ( ch->pcdata->clan[CLAN] != ch->in_room->clan )
    {
      stc( "Planet defensors activate and absorb your attack.\n\r", ch );
      return;
    }
  }
  if ( IS_NPC(ch) )
  { act( "You give $p a good hard kick!", ch, suit, NULL, TO_CHAR );
    act( "$n gives $p a good hard kick!", ch, suit, NULL, TO_ROOM );
  }
  else
  { switch( ch->class )
    { case CLASS_SAIYAN:
        act( "You blast $p with Ki flame!", ch, suit, NULL, TO_CHAR );
        act( "$n blasts $p with Ki flame.", ch, suit, NULL, TO_ROOM );
        break;
      case CLASS_PATRYN:
        act( "You short circuit $p with a bolt of lightning!", ch, suit, NULL, TO_CHAR );
        act( "$n short circuits $p with a bolt of lightning.", ch, suit, NULL, TO_ROOM );
        break;
      case CLASS_FIST:
        act( "You slam your fist into $p, crushing it!", ch, suit, NULL, TO_CHAR );
        act( "$n slam your fist into $p, crushing it.", ch, suit, NULL, TO_ROOM );
        break;
      case CLASS_SORCERER:
        act( "You drop a fireball on $p!", ch, suit, NULL, TO_CHAR );
        act( "$n drops a fireball on $p.", ch, suit, NULL, TO_ROOM );
        break;
      case CLASS_MAZOKU:
        act( "You engulf $p in demonic energy!", ch, suit, NULL, TO_CHAR );
        act( "$n engulfs $p in demonic energy!", ch, suit, NULL, TO_ROOM );
        break;
      default:
        act( "You give $p a good hard kick!", ch, suit, NULL, TO_CHAR );
        act( "$n gives $p a good hard kick!", ch, suit, NULL, TO_ROOM );
        break;
    };
  }

  part = 1;
  if ( suit->value[SUIT_COND] < 4095 )
  { while ( !match )
    { i = dice(1,12) - 1;
      part = 1;
      for ( j = 0; j < i; j++ )
        part *= 2;
      if ( !IS_SET(suit->value[SUIT_COND],part) )
        match = TRUE;
    }
    SET_BIT(suit->value[SUIT_COND],part);
  }

  switch( part )
  { case 1:     buf = "torso has been damaged";         break;
    case 2:     buf = "guidance package has been damaged";      break;
    case 4:     buf = "head has been damaged";          break;
    case 8:     buf = "camera has been damaged";        break;
    case 16:    buf = "left leg has been damaged";      break;
    case 32:    buf = "right hand has been damaged";    break;
    case 64:    buf = "right leg has been damaged";     break;
    case 128:   buf = "left hand has been damaged";     break;
    case 256:   buf = "left arm has been damaged";      break;
    case 512:   buf = "radar system has been damaged";  break;
    case 1024:  buf = "right arm has been damaged";     break;
    case 2048:  buf = "propulsion system has been damaged";     break;
    default:    buf = "This is a bug";			break;
  };

  act( "The $T.", ch, NULL, buf, TO_CHAR );
  act( "The $T.", ch, NULL, buf, TO_ROOM );

  if ( suit->value[SUIT_COND] >= 4095 )
  { act( "$p collapses into a pile of scraps!", ch, suit, NULL, TO_CHAR );
    act( "$p collapses into a pile of scraps!", ch, suit, NULL, TO_ROOM );
    extract_obj( suit );
  }

  WAIT_STATE(ch,8);
  return;
}

void fire_flamethrower( CHAR_DATA *ch )
{
  CHAR_DATA *vch;
  CHAR_DATA *vch_next;
  int dam, combat;

  if ( IS_NPC(ch) || !IS_SUIT(ch) )
    return;

  if ( ch->pcdata->suit[SUIT_PLASMA] < 10 )
  {
    stc( "You need at least 10 units of plasma.\n\r", ch );
    return;
  }

  combat = ch->pcdata->suit[SUIT_COMBAT];
  ch->pcdata->suit[SUIT_PLASMA] -= 10;

  act( "You bathe your enemies in flame!", ch, NULL, NULL, TO_CHAR );
  act( "$n looses a huge gout of flame-like plasma!", ch, NULL, NULL, TO_ROOM );
  for ( vch = ch->in_room->people; vch != NULL; vch = vch_next )
  {
    vch_next = vch->next_in_room;
    if ( is_same_group( ch, vch ) )
      continue;
    dam = number_range( 3 * combat, 4 * combat );
    damage( ch, vch, dam, DAM_FIRE );
  }

  WAIT_STATE(ch,12);
  return;
}

void do_salvo( CHAR_DATA *ch, char *argument )
{
  ROOM_INDEX_DATA *in_room;
  EXIT_DATA *pexit;
  extern char * const dir_name[];
  CHAR_DATA *victim = NULL;
  char arg[MAX_INPUT_LENGTH];
  int i, j, aim, weapon, wait, missiles, dam, rdam, dir;

  if ( ch->position < POS_FIGHTING )
  {
    stc( "You're too relaxed.\n\r", ch );
    return;
  }
  if ( ch->position == POS_FIGHTING )
  {
    stc( "At this range? Are you suicidal?\n\r", ch );
    return;
  }
  if ( !IS_SUIT(ch) )
  {
    stc( "Go behind a tree, will ya?\n\r", ch );
    return;
  }
  if ( !IS_SET(ch->pcdata->suit[SUIT_EQ],MS_MISSILES) )
  {
    stc( "Your suit is not equipped with missiles.\n\r", ch );
    return;
  }
  if ( ch->pcdata->suit[SUIT_MISSILES] < 1 )
  {
    stc( "You have no missiles left.\n\r", ch );
    return;
  }
  argument = one_argument( argument, arg );

  if ( arg[0] == '\0' )
  {
    stc( "Fire your missiles in which direction?\n\r", ch );
    return;
  }
  if ( !str_prefix( arg, "north" ) )
    dir = DIR_NORTH;
  else if ( !str_prefix( arg, "east" ) )
    dir = DIR_EAST;
  else if ( !str_prefix( arg, "south" ) )
    dir = DIR_SOUTH;
  else if ( !str_prefix( arg, "west" ) )
    dir = DIR_WEST;
  else if ( !str_prefix( arg, "up" ) )
    dir = DIR_UP;
  else if ( !str_prefix( arg, "down" ) )
    dir = DIR_DOWN;
  else
  {
    stc( "ERROR: That direction does not parse.\n\r", ch );
    return;
  }

  act( "You launch missiles to the $T.", ch, NULL, dir_name[dir], TO_CHAR );
  act( "$n launches missiles to the $T.", ch, NULL, dir_name[dir], TO_ROOM );

  weapon = suit_table[ch->pcdata->suit[SUIT_NUMBER]].weapon;
  aim = ch->pcdata->suit[SUIT_AIM];
  switch( ch->pcdata->suit[SUIT_NUMBER] )
  {
    case 2: /* Aries */
      missiles = 4;
      wait = 4;
      dam = weapon + dice(3,aim/10);
      break;
    case 11: /* Heavyarms */
      missiles = 16;
      wait = 16;
      dam = weapon*5 + dice(10,aim/10);
      break;
    case 12: /* Sandrock */
      missiles = 2;
      wait = 4;
      dam = weapon*20 + dice(20,aim/10);
      break;
    case 15: /* M1A1 Tank */
      missiles = 8;
      wait = 2;
      dam = weapon*10 + dice(10,aim/5);
      break;
    default:
      return;
      break;
  }

  missiles = UMIN( ch->pcdata->suit[SUIT_MISSILES], missiles );
  ch->pcdata->suit[SUIT_MISSILES] -= missiles;
  in_room = ch->in_room;

  for ( ; ; )
  {
    if ( (pexit = in_room->exit[dir]) == NULL ||
         (in_room = pexit->to_room) == NULL )
    {
      stc( "The missiles explode against a wall.\n\r", ch );
      WAIT_STATE(ch,wait);
      return;
    }

    if ( in_room->people == NULL )
      continue;

    for ( i = 0; i < missiles && in_room->people != NULL; i++ )
    {
      rdam = dice(10,dam) / 5;
      j = 0;
      while ( victim != NULL )
      {
        j++;
        victim = victim->next_in_room;
      }
      j = dice(1,j);
      victim = in_room->people;
      for ( ; j > 1 && victim->next_in_room != NULL; j-- )
        victim  = victim->next_in_room;

      damage( ch, victim, rdam, DAM_MISSILES );
      if ( ch->fighting == victim )
        stop_fighting( ch, FALSE );
      if ( victim != NULL && victim->fighting == ch
        && !(!IS_NPC(victim) && IS_SET(victim->act,PLR_FIREBACK)) )
        stop_fighting( victim, FALSE );
    }
    break;
  }

  WAIT_STATE(ch,wait);
  return;
}