Beispiel #1
0
/* Cheap hack of process_exit from overland.c for ships */
ch_ret process_shipexit( char_data * ch, short map, short x, short y, int dir )
{
   int sector = get_terrain( map, x, y ), move;
   room_index *from_room;
   ship_data *ship = ch->on_ship;
   ch_ret retcode;
   short fx, fy, fmap;

   from_room = ch->in_room;
   fx = ch->mx;
   fy = ch->my;
   fmap = ch->cmap;

   retcode = rNONE;
   if( ch->has_pcflag( PCFLAG_MAPEDIT ) )
   {
      ch->print( "Get off the ship before you start editing.\r\n" );
      return rSTOP;
   }

   if( sector == SECT_EXIT )
   {
      mapexit_data *mexit;
      room_index *toroom = NULL;

      mexit = check_mapexit( map, x, y );

      if( mexit != NULL )
      {
         if( mexit->tomap != -1 )   /* Means exit goes to another map */
         {
            if( !can_move_ship( ch, get_terrain( mexit->tomap, mexit->therex, mexit->therey ) ) )
               return rSTOP;

            enter_map( ch, NULL, mexit->therex, mexit->therey, mexit->tomap );
            if( ch->mount )
               enter_map( ch->mount, NULL, mexit->therex, mexit->therey, mexit->tomap );

            list < char_data * >::iterator ich;
            size_t chars = from_room->people.size(  );
            size_t count = 0;
            for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
            {
               char_data *fch = *ich;
               ++ich;
               ++count;

               if( fch != ch  /* loop room bug fix here by Thoric */
                   && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) && fch->mx == fx && fch->my == fy && fch->cmap == fmap )
               {
                  if( !fch->isnpc(  ) )
                  {
                     act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[dir], TO_CHAR );
                     process_exit( fch, fch->cmap, x, y, dir, false );
                  }
                  else
                     enter_map( fch, NULL, mexit->therex, mexit->therey, mexit->tomap );
               }
            }
            return rSTOP;
         }

         if( !( toroom = get_room_index( mexit->vnum ) ) )
         {
            bug( "%s: Target vnum %d for map exit does not exist!", __FUNCTION__, mexit->vnum );
            ch->print( "Ooops. Something bad happened. Contact the immortals ASAP.\r\n" );
            return rSTOP;
         }

         if( !can_move_ship( ch, toroom->sector_type ) )
            return rSTOP;

         if( !str_cmp( ch->name, ship->owner ) )
            act_printf( AT_ACTION, ch, NULL, dir_name[dir], TO_ROOM, "%s sails off to the $T.", ship->name.c_str(  ) );

         ch->on_ship->room = toroom->vnum;

         leave_map( ch, NULL, toroom );

         list < char_data * >::iterator ich;
         size_t chars = from_room->people.size(  );
         size_t count = 0;
         for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
         {
            char_data *fch = *ich;
            ++ich;
            ++count;

            if( fch != ch  /* loop room bug fix here by Thoric */
                && fch->master == ch && fch->position == POS_STANDING && fch->mx == fx && fch->my == fy && fch->cmap == fmap )
            {
               if( !fch->isnpc(  ) )
               {
                  act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[dir], TO_CHAR );
                  process_shipexit( fch, fch->cmap, x, y, dir );
               }
               else
                  leave_map( fch, ch, toroom );
            }
         }
         return rSTOP;
      }
   }

   switch ( dir )
   {
      default:
         ch->print( "Alas, you cannot go that way...\r\n" );
         return rSTOP;

      case DIR_NORTH:
         if( y == -1 )
         {
            ch->print( "You cannot sail any further north!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_EAST:
         if( x == MAX_X )
         {
            ch->print( "You cannot sail any further east!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_SOUTH:
         if( y == MAX_Y )
         {
            ch->print( "You cannot sail any further south!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_WEST:
         if( x == -1 )
         {
            ch->print( "You cannot sail any further west!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_NORTHEAST:
         if( x == MAX_X || y == -1 )
         {
            ch->print( "You cannot sail any further northeast!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_NORTHWEST:
         if( x == -1 || y == -1 )
         {
            ch->print( "You cannot sail any further northwest!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_SOUTHEAST:
         if( x == MAX_X || y == MAX_Y )
         {
            ch->print( "You cannot sail any further southeast!\r\n" );
            return rSTOP;
         }
         break;

      case DIR_SOUTHWEST:
         if( x == -1 || y == MAX_Y )
         {
            ch->print( "You cannot sail any further southwest!\r\n" );
            return rSTOP;
         }
         break;
   }

   if( !can_move_ship( ch, sector ) )
      return rSTOP;

   move = sect_show[sector].move;

   if( ship->fuel < move && !ch->is_immortal(  ) )
   {
      ch->print( "Your ship is too low on magical energy to sail further ahead.\r\n" );
      return rSTOP;
   }

   if( !ch->is_immortal(  ) && !str_cmp( ch->name, ship->owner ) )
      ship->fuel -= move;

   if( !str_cmp( ch->name, ship->owner ) )
      act_printf( AT_ACTION, ch, NULL, dir_name[dir], TO_ROOM, "%s sails off to the $T.", ship->name.c_str(  ) );

   ch->mx = x;
   ch->my = y;
   ship->mx = x;
   ship->my = y;

   if( !str_cmp( ch->name, ship->owner ) )
   {
      const char *txt = rev_exit( dir );
      act_printf( AT_ACTION, ch, NULL, NULL, TO_ROOM, "%s sails in from the %s.", ship->name.c_str(  ), txt );
   }

   list < char_data * >::iterator ich;
   size_t chars = from_room->people.size(  );
   size_t count = 0;
   for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
   {
      char_data *fch = *ich;
      ++ich;
      ++count;

      if( fch != ch  /* loop room bug fix here by Thoric */
          && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) && fch->mx == fx && fch->my == fy )
      {
         if( !fch->isnpc(  ) )
         {
            act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[dir], TO_CHAR );
            process_exit( fch, fch->cmap, x, y, dir, false );
         }
         else
         {
            fch->mx = x;
            fch->my = y;
         }
      }
   }
   interpret( ch, "look" );
   return retcode;
}
Beispiel #2
0
/* Rehacked by Samson - had to clean up the mess */
ch_ret move_ship( char_data * ch, exit_data * pexit, int direction )
{
   ship_data *ship = ch->on_ship;
   ch_ret retcode;
   short door;
   int newx, newy, move;

   retcode = rNONE;

   if( ch->has_pcflag( PCFLAG_ONMAP ) || ch->has_actflag( ACT_ONMAP ) )
   {
      newx = ch->mx;
      newy = ch->my;

      switch ( direction )
      {
         default:
            break;
         case DIR_NORTH:
            newy = ch->my - 1;
            break;
         case DIR_EAST:
            newx = ch->mx + 1;
            break;
         case DIR_SOUTH:
            newy = ch->my + 1;
            break;
         case DIR_WEST:
            newx = ch->mx - 1;
            break;
         case DIR_NORTHEAST:
            newx = ch->mx + 1;
            newy = ch->my - 1;
            break;
         case DIR_NORTHWEST:
            newx = ch->mx - 1;
            newy = ch->my - 1;
            break;
         case DIR_SOUTHEAST:
            newx = ch->mx + 1;
            newy = ch->my + 1;
            break;
         case DIR_SOUTHWEST:
            newx = ch->mx - 1;
            newy = ch->my + 1;
            break;
      }
      if( newx == ch->mx && newy == ch->my )
         return rSTOP;

      retcode = process_shipexit( ch, ch->cmap, newx, newy, direction );
      return retcode;
   }

   room_index *in_room = ch->in_room;
   room_index *from_room = in_room;
   room_index *to_room;
   if( !pexit || !( to_room = pexit->to_room ) )
   {
      ch->print( "Alas, you cannot sail that way.\r\n" );
      check_sneaks( ch );
      return rSTOP;
   }

   door = pexit->vdir;

   /*
    * Overland Map stuff - Samson 7-31-99 
    */
   /*
    * Upgraded 4-28-00 to allow mounts and charmies to follow PC - Samson 
    */
   if( IS_EXIT_FLAG( pexit, EX_OVERLAND ) )
   {
      if( pexit->mx < 0 || pexit->mx >= MAX_X || pexit->my < 0 || pexit->my >= MAX_Y )
      {
         bug( "%s: Room #%d - Invalid exit coordinates: %d %d", __FUNCTION__, in_room->vnum, pexit->mx, pexit->my );
         ch->print( "Oops. Something is wrong with this map exit - notify the immortals.\r\n" );
         check_sneaks( ch );
         return rSTOP;
      }

      if( !ch->isnpc(  ) )
      {
         enter_map( ch, pexit, pexit->mx, pexit->my, -1 );
         if( ch->mount )
            enter_map( ch->mount, pexit, pexit->mx, pexit->my, -1 );

         list < char_data * >::iterator ich;
         size_t chars = from_room->people.size(  );
         size_t count = 0;
         for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
         {
            char_data *fch = *ich;
            ++ich;
            ++count;

            if( fch != ch  /* loop room bug fix here by Thoric */
                && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) )
            {
               if( !fch->isnpc(  ) )
               {
                  act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[direction], TO_CHAR );
                  move_char( fch, pexit, 0, direction, false );
               }
               else
                  enter_map( fch, pexit, pexit->mx, pexit->my, -1 );
            }
         }
      }
      else
      {
         if( !IS_EXIT_FLAG( pexit, EX_NOMOB ) )
         {
            enter_map( ch, pexit, pexit->mx, pexit->my, -1 );
            if( ch->mount )
               enter_map( ch->mount, pexit, pexit->mx, pexit->my, -1 );

            list < char_data * >::iterator ich;
            size_t chars = from_room->people.size(  );
            size_t count = 0;
            for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
            {
               char_data *fch = *ich;
               ++ich;
               ++count;

               if( fch != ch  /* loop room bug fix here by Thoric */
                   && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) )
               {
                  if( !fch->isnpc(  ) )
                  {
                     act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[direction], TO_CHAR );
                     move_char( fch, pexit, 0, direction, false );
                  }
                  else
                     enter_map( fch, pexit, pexit->mx, pexit->my, -1 );
               }
            }
         }
      }
      check_sneaks( ch );
      return rSTOP;
   }

   if( !can_move_ship( ch, pexit->to_room->sector_type ) )
   {
      check_sneaks( ch );
      return rSTOP;
   }

   if( IS_EXIT_FLAG( pexit, EX_PORTAL ) )
   {
      ch->print( "You cannot sail a ship through that!!\r\n" );
      check_sneaks( ch );
      return rSTOP;
   }

   if( !ch->is_immortal(  ) && !ch->isnpc(  ) && ch->in_room->area != to_room->area )
   {
      if( ch->level < to_room->area->low_hard_range )
      {
         switch ( to_room->area->low_hard_range - ch->level )
         {
            case 1:
               ch->print( "&[tell]A voice in your mind says, 'You are nearly ready to go that way...'\r\n" );
               break;
            case 2:
               ch->print( "&[tell]A voice in your mind says, 'Soon you shall be ready to travel down this path... soon.'\r\n" );
               break;
            case 3:
               ch->print( "&[tell]A voice in your mind says, 'You are not ready to go down that path... yet.'\r\n" );
               break;
            default:
               ch->print( "&[tell]A voice in your mind says, 'You are not ready to go down that path.'\r\n" );
         }
         check_sneaks( ch );
         return rSTOP;
      }
      else if( ch->level > to_room->area->hi_hard_range )
      {
         ch->print( "&[tell]A voice in your mind says, 'There is nothing more for you down that path.'" );
         check_sneaks( ch );
         return rSTOP;
      }
   }

   /*
    * Tunnels in water sectors only check for ships, not people since they're generally too small to matter 
    */
   if( to_room->tunnel > 0 )
   {
      int count = 0;
      list < ship_data * >::iterator other;

      for( other = shiplist.begin(  ); other != shiplist.end(  ); ++other )
      {
         ship_data *shp = *other;

         if( shp->room == to_room->vnum )
            ++count;

         if( count >= to_room->tunnel )
         {
            ch->print( "There are too many ships ahead to pass.\r\n" );
            check_sneaks( ch );
            return rSTOP;
         }
      }
   }

   move = sect_show[in_room->sector_type].move;

   if( ship->fuel < move && !ch->is_immortal(  ) )
   {
      ch->print( "Your ship is too low on magical energy to sail further ahead.\r\n" );
      return rSTOP;
   }

   if( !str_cmp( ch->name, ship->owner ) && !ch->is_immortal(  ) )
      ship->fuel -= move;

   rprog_leave_trigger( ch );
   if( ch->char_died(  ) )
      return global_retcode;

   if( !str_cmp( ch->name, ship->owner ) )
      act_printf( AT_ACTION, ch, NULL, dir_name[door], TO_ROOM, "%s sails off to the $T.", ship->name.c_str(  ) );

   ch->from_room(  );
   if( ch->mount )
   {
      rprog_leave_trigger( ch->mount );
      if( ch->char_died(  ) )
         return global_retcode;
      if( ch->mount )
      {
         ch->mount->from_room(  );
         if( !ch->mount->to_room( to_room ) )
            log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __FUNCTION__, __LINE__ );
      }
   }
   if( !ch->to_room( to_room ) )
      log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __FUNCTION__, __LINE__ );
   ship->room = to_room->vnum;
   check_sneaks( ch );

   if( !str_cmp( ch->name, ship->owner ) )
   {
      const char *txt = rev_exit( door );

      act_printf( AT_ACTION, ch, NULL, NULL, TO_ROOM, "%s sails in from the %s.", ship->name.c_str(  ), txt );
   }

   list < char_data * >::iterator ich;
   size_t chars = from_room->people.size(  );
   size_t count = 0;
   for( ich = from_room->people.begin(  ); ich != from_room->people.end(  ), ( count < chars ); )
   {
      char_data *fch = *ich;
      ++ich;
      ++count;

      if( fch != ch  /* loop room bug fix here by Thoric */
          && fch->master == ch && ( fch->position == POS_STANDING || fch->position == POS_MOUNTED ) )
      {
         act( AT_ACTION, "The ship sails $T.", fch, NULL, dir_name[door], TO_CHAR );
         move_char( fch, pexit, 0, direction, false );
      }
   }
   interpret( ch, "look" );
   return retcode;
}
Beispiel #3
0
/*
 * Generic use ranged attack function			-Thoric & Tricops
 */
ch_ret ranged_attack( char_data * ch, string argument, obj_data * weapon, obj_data * projectile, short dt, short range )
{
   string arg, arg1, temp;

   if( !argument.empty(  ) && argument[0] == '\'' )
   {
      one_argument( argument, temp );
      argument = temp;
   }

   argument = one_argument( argument, arg );
   argument = one_argument( argument, arg1 );

   if( arg.empty(  ) )
   {
      ch->print( "Where?  At who?\r\n" );
      return rNONE;
   }

   /*
    * get an exit or a victim 
    */
   short dir = -1;
   exit_data *pexit;
   char_data *victim = nullptr;
   if( !( pexit = find_door( ch, arg, true ) ) )
   {
      if( !( victim = ch->get_char_room( arg ) ) )
      {
         ch->print( "Aim in what direction?\r\n" );
         return rNONE;
      }
      else
      {
         if( ch->who_fighting(  ) == victim )
         {
            ch->print( "They are too close to release that type of attack!\r\n" );
            return rNONE;
         }
      }
   }
   else
      dir = pexit->vdir;

   /*
    * check for ranged attacks from private rooms, etc 
    */
   if( !victim )
   {
      if( ch->in_room->flags.test( ROOM_PRIVATE ) || ch->in_room->flags.test( ROOM_SOLITARY ) )
      {
         ch->print( "You cannot perform a ranged attack from a private room.\r\n" );
         return rNONE;
      }
      if( ch->in_room->tunnel > 0 )
      {
         if( ( int )ch->in_room->people.size(  ) >= ch->in_room->tunnel )
         {
            ch->print( "This room is too cramped to perform such an attack.\r\n" );
            return rNONE;
         }
      }
   }

   skill_type *skill = nullptr;
   if( IS_VALID_SN( dt ) )
      skill = skill_table[dt];

   if( pexit && !pexit->to_room )
   {
      ch->print( "Are you expecting to fire through a wall!?\r\n" );
      return rNONE;
   }

   /*
    * Check for obstruction 
    */
   if( pexit && IS_EXIT_FLAG( pexit, EX_CLOSED ) )
   {
      if( IS_EXIT_FLAG( pexit, EX_SECRET ) || IS_EXIT_FLAG( pexit, EX_DIG ) )
         ch->print( "Are you expecting to fire through a wall!?\r\n" );
      else
         ch->print( "Are you expecting to fire through a door!?\r\n" );
      return rNONE;
   }

   /*
    * Keeps em from firing through a wall but can still fire through an arrow slit or window, Marcus 
    */
   if( pexit )
   {
      if( ( IS_EXIT_FLAG( pexit, EX_FORTIFIED ) || IS_EXIT_FLAG( pexit, EX_HEAVY )
            || IS_EXIT_FLAG( pexit, EX_MEDIUM ) || IS_EXIT_FLAG( pexit, EX_LIGHT ) || IS_EXIT_FLAG( pexit, EX_CRUMBLING ) )
          && !IS_EXIT_FLAG( pexit, EX_WINDOW ) && !IS_EXIT_FLAG( pexit, EX_ASLIT ) )
      {
         ch->print( "Are you expecting to fire through a wall!?\r\n" );
         return rNONE;
      }
   }

   char_data *vch = nullptr;
   if( pexit && !arg1.empty(  ) )
   {
      if( !( vch = scan_for_vic( ch, pexit, arg1 ) ) )
      {
         ch->print( "You cannot see your target.\r\n" );
         return rNONE;
      }

      /*
       * don't allow attacks on mobs that are in a no-missile room --Shaddai 
       */
      if( vch->in_room->flags.test( ROOM_NOMISSILE ) )
      {
         ch->print( "You can't get a clean shot off.\r\n" );
         return rNONE;
      }

      /*
       * can't properly target someone heavily in battle 
       */
      if( vch->num_fighting > MAX_FIGHT )
      {
         ch->print( "There is too much activity there for you to get a clear shot.\r\n" );
         return rNONE;
      }
   }

   if( vch )
   {
      if( !vch->CAN_PKILL(  ) || !ch->CAN_PKILL(  ) )
      {
         ch->print( "You can't do that!\r\n" );
         return rNONE;
      }
      if( vch && is_safe( ch, vch ) )
         return rNONE;
   }

   room_index *was_in_room = ch->in_room;
   const char *stxt = "burst of energy";
   if( projectile )
   {
      projectile->separate(  );
      if( pexit )
      {
         if( weapon )
         {
            act( AT_GREY, "You fire $p $T.", ch, projectile, dir_name[dir], TO_CHAR );
            act( AT_GREY, "$n fires $p $T.", ch, projectile, dir_name[dir], TO_ROOM );
         }
         else
         {
            act( AT_GREY, "You throw $p $T.", ch, projectile, dir_name[dir], TO_CHAR );
            act( AT_GREY, "$n throw $p $T.", ch, projectile, dir_name[dir], TO_ROOM );
         }
      }
      else
      {
         if( weapon )
         {
            act( AT_GREY, "You fire $p at $N.", ch, projectile, victim, TO_CHAR );
            act( AT_GREY, "$n fires $p at $N.", ch, projectile, victim, TO_NOTVICT );
            act( AT_GREY, "$n fires $p at you!", ch, projectile, victim, TO_VICT );
         }
         else
         {
            act( AT_GREY, "You throw $p at $N.", ch, projectile, victim, TO_CHAR );
            act( AT_GREY, "$n throws $p at $N.", ch, projectile, victim, TO_NOTVICT );
            act( AT_GREY, "$n throws $p at you!", ch, projectile, victim, TO_VICT );
         }
      }
   }
   else if( skill )
   {
      if( skill->noun_damage && skill->noun_damage[0] != '\0' )
         stxt = skill->noun_damage;
      else
         stxt = skill->name;
      /*
       * a plain "spell" flying around seems boring 
       */
      if( !str_cmp( stxt, "spell" ) )
         stxt = "magical burst of energy";
      if( skill->type == SKILL_SPELL )
      {
         if( pexit )
         {
            act( AT_MAGIC, "You release $t $T.", ch, aoran( stxt ), dir_name[dir], TO_CHAR );
            act( AT_MAGIC, "$n releases $s $t $T.", ch, stxt, dir_name[dir], TO_ROOM );
         }
         else
         {
            act( AT_MAGIC, "You release $t at $N.", ch, aoran( stxt ), victim, TO_CHAR );
            act( AT_MAGIC, "$n releases $s $t at $N.", ch, stxt, victim, TO_NOTVICT );
            act( AT_MAGIC, "$n releases $s $t at you!", ch, stxt, victim, TO_VICT );
         }
      }
   }
   else
   {
      bug( "%s: no projectile, no skill dt %d", __func__, dt );
      return rNONE;
   }

   /*
    * victim in same room 
    */
   if( victim )
   {
      check_illegal_pk( ch, victim );
      check_attacker( ch, victim );
      return ranged_got_target( ch, victim, weapon, projectile, 0, dt, stxt, AT_MAGIC );
   }

   /*
    * assign scanned victim 
    */
   victim = vch;

   /*
    * reverse direction text from move_char 
    */
   const char *dtxt = rev_exit( pexit->vdir );
   int dist = 0;

   while( dist <= range )
   {
      ch->from_room(  );
      if( !ch->to_room( pexit->to_room ) )
         log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __func__, __LINE__ );

      if( IS_EXIT_FLAG( pexit, EX_CLOSED ) )
      {
         /*
          * whadoyahknow, the door's closed 
          */
         if( projectile )
            ch->printf( "&wYou see your %s pierce a door in the distance to the %s.", projectile->myobj(  ).c_str(  ), dir_name[dir] );
         else
            ch->printf( "&wYou see your %s hit a door in the distance to the %s.", stxt, dir_name[dir] );
         if( projectile )
            act_printf( AT_GREY, ch, projectile, nullptr, TO_ROOM, "$p flies in from %s and implants itself solidly in the %sern door.", dtxt, dir_name[dir] );
         else
            act_printf( AT_GREY, ch, nullptr, nullptr, TO_ROOM, "%s flies in from %s and implants itself solidly in the %sern door.", aoran( stxt ), dtxt, dir_name[dir] );
         break;
      }

      /*
       * no victim? pick a random one 
       */
      if( !victim )
      {
         list < char_data * >::iterator ich;
         for( ich = ch->in_room->people.begin(  ); ich != ch->in_room->people.end(  ); ++ich )
         {
            vch = *ich;

            if( ( ( ch->isnpc(  ) && !vch->isnpc(  ) ) || ( !ch->isnpc(  ) && vch->isnpc(  ) ) ) && number_bits( 1 ) == 0 )
            {
               victim = vch;
               break;
            }
         }
         if( victim && is_safe( ch, victim ) )
         {
            ch->from_room(  );
            if( !ch->to_room( was_in_room ) )
               log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __func__, __LINE__ );
            return rNONE;
         }
      }

      /*
       * In the same room as our victim? 
       */
      if( victim && ch->in_room == victim->in_room )
      {
         if( projectile )
            act( AT_GREY, "$p flies in from $T.", ch, projectile, dtxt, TO_ROOM );
         else
            act( AT_GREY, "$t flies in from $T.", ch, aoran( stxt ), dtxt, TO_ROOM );

         /*
          * get back before the action starts 
          */
         ch->from_room(  );
         if( !ch->to_room( was_in_room ) )
            log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __func__, __LINE__ );

         check_illegal_pk( ch, victim );
         check_attacker( ch, victim );
         return ranged_got_target( ch, victim, weapon, projectile, dist, dt, stxt, AT_GREY );
      }

      if( dist == range )
      {
         if( projectile )
         {
            act( AT_GREY, "Your $t falls harmlessly to the ground to the $T.", ch, projectile->myobj(  ).c_str(  ), dir_name[dir], TO_CHAR );
            act( AT_GREY, "$p flies in from $T and falls harmlessly to the ground here.", ch, projectile, dtxt, TO_ROOM );
            if( projectile->in_obj )
               projectile->from_obj(  );
            if( projectile->carried_by )
               projectile->from_char(  );
            projectile->to_room( ch->in_room, ch );
         }
         else
         {
            act( AT_MAGIC, "Your $t fizzles out harmlessly to the $T.", ch, stxt, dir_name[dir], TO_CHAR );
            act( AT_MAGIC, "$t flies in from $T and fizzles out harmlessly.", ch, aoran( stxt ), dtxt, TO_ROOM );
         }
         break;
      }

      if( !( pexit = ch->in_room->get_exit( dir ) ) )
      {
         if( projectile )
         {
            act( AT_GREY, "Your $t hits a wall and bounces harmlessly to the ground to the $T.", ch, projectile->myobj(  ).c_str(  ), dir_name[dir], TO_CHAR );
            act( AT_GREY, "$p strikes the $Tsern wall and falls harmlessly to the ground.", ch, projectile, dir_name[dir], TO_ROOM );
            if( projectile->in_obj )
               projectile->from_obj(  );
            if( projectile->carried_by )
               projectile->from_char(  );
            projectile->to_room( ch->in_room, ch );
         }
         else
         {
            act( AT_MAGIC, "Your $t harmlessly hits a wall to the $T.", ch, stxt, dir_name[dir], TO_CHAR );
            act( AT_MAGIC, "$t strikes the $Tsern wall and falls harmlessly to the ground.", ch, aoran( stxt ), dir_name[dir], TO_ROOM );
         }
         break;
      }
      if( projectile )
         act( AT_GREY, "$p flies in from $T.", ch, projectile, dtxt, TO_ROOM );
      else
         act( AT_MAGIC, "$t flies in from $T.", ch, aoran( stxt ), dtxt, TO_ROOM );
      ++dist;
   }

   ch->from_room(  );
   if( !ch->to_room( was_in_room ) )
      log_printf( "char_to_room: %s:%s, line %d.", __FILE__, __func__, __LINE__ );

   if( projectile->carried_by == ch )
      projectile->extract(  );
   return rNONE;
}