Beispiel #1
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;
}
Beispiel #2
0
bool load_class_file( const char *fname )
{
    char                    buf[MSL];
    const char             *word;
    bool                    fMatch;
    struct class_type      *Class;
    int                     cl = -1,
        tlev = 0;
    FILE                   *fp;

    snprintf( buf, MSL, "%s%s", CLASSDIR, fname );
    if ( ( fp = FileOpen( buf, "r" ) ) == NULL ) {
        perror( buf );
        return FALSE;
    }
    CREATE( Class, struct class_type, 1 );
    /*
     * Setup defaults for additions to class structure
     */
    Class->starting = FALSE;
    Class->attr_second = 0;
    Class->attr_deficient = 0;
    xCLEAR_BITS( Class->affected );
    Class->resist = 0;
    Class->suscept = 0;

    for ( ;; ) {
        word = feof( fp ) ? "End" : fread_word( fp );
        fMatch = FALSE;
        switch ( UPPER( word[0] ) ) {
            case '*':
                fMatch = TRUE;
                fread_to_eol( fp );
                break;
            case 'A':
                KEY( "Affected", Class->affected, fread_bitvector( fp ) );
                KEY( "AttrPrime", Class->attr_prime, fread_number( fp ) );
                KEY( "AttrSecond", Class->attr_second, fread_number( fp ) );
                KEY( "AttrDeficient", Class->attr_deficient, fread_number( fp ) );
                break;
            case 'C':
                KEY( "Class", cl, fread_number( fp ) );
                KEY( "Craftbase", Class->craft_base, fread_number( fp ) );
                break;
            case 'E':
                if ( !str_cmp( word, "End" ) )
                    if ( !str_cmp( word, "End" ) ) {
                        FileClose( fp );
                        if ( cl < 0 || cl >= MAX_CLASS ) {
                            bug( "Load_class_file: Class (%s) bad/not found (%d)",
                                 Class->who_name ? Class->who_name : "name not found", cl );
                            if ( VLD_STR( Class->who_name ) )
                                STRFREE( Class->who_name );
                            if ( VLD_STR( Class->filename ) )
                                STRFREE( Class->filename );
                            DISPOSE( Class );
                            return FALSE;
                        }
                        if ( !Class->filename )
                            Class->filename = STRALLOC( Class->who_name );
                        class_table[cl] = Class;
                        return TRUE;
                    }
                KEY( "ExpBase", Class->exp_base, fread_number( fp ) );
                break;
            case 'F':
                KEY( "Filename", Class->filename, fread_string( fp ) );
            case 'H':
                KEY( "HpMax", Class->hp_max, fread_number( fp ) );
                KEY( "HpMin", Class->hp_min, fread_number( fp ) );
                break;
            case 'M':
                KEY( "ManaMax", Class->mana_max, fread_number( fp ) );
                KEY( "ManaMin", Class->mana_min, fread_number( fp ) );
                break;
            case 'N':
                KEY( "Nocombo", Class->combo_restriction, fread_number( fp ) );
                KEY( "Name", Class->who_name, fread_string( fp ) );
                break;
            case 'R':
                KEY( "Races", Class->race_restriction, fread_number( fp ) );
                if ( !str_cmp( word, "Reclass" ) ) {
                    Class->reclass1 = fread_number( fp );
                    Class->reclass2 = fread_number( fp );
                    Class->reclass3 = fread_number( fp );
                    fMatch = TRUE;
                    break;
                }
                KEY( "Resist", Class->resist, fread_number( fp ) );
                break;
            case 'S':
                KEY( "Starting", Class->starting, fread_number( fp ) );
                if ( !str_cmp( word, "Skill" ) ) {
                    int                     sn,
                                            lev,
                                            adp;

                    word = fread_word( fp );
                    lev = fread_number( fp );
                    adp = fread_number( fp );
                    sn = skill_lookup( word );
                    if ( cl < 0 || cl >= MAX_CLASS )
                        bug( "load_class_file: Skill %s -- class bad/not found (%d)", word, cl );
                    else if ( !IS_VALID_SN( sn ) )
                        bug( "load_class_file: Skill %s unknown", word );
                    else {
                        skill_table[sn]->skill_level[cl] = lev;
                        skill_table[sn]->skill_adept[cl] = adp;
                    }
                    fMatch = TRUE;
                    break;
                }
                KEY( "Skilladept", Class->skill_adept, fread_number( fp ) );
                KEY( "Suscept", Class->suscept, fread_number( fp ) );
                break;
            case 'T':
                if ( !str_cmp( word, "Title" ) ) {
                    if ( cl < 0 || cl >= MAX_CLASS ) {
                        char                   *tmp;

                        bug( "load_class_file: Title -- class bad/not found (%d)", cl );
                        tmp = fread_string( fp );
                        DISPOSE( tmp );
                        tmp = fread_string( fp );
                        DISPOSE( tmp );
                    }
                    else if ( tlev < MAX_LEVEL + 1 ) {
                        title_table[cl][tlev][0] = fread_string( fp );
                        title_table[cl][tlev][1] = fread_string( fp );
                        ++tlev;
                    }
                    else
                        bug( "%s", "load_class_file: Too many titles" );
                    fMatch = TRUE;
                    break;
                }
                KEY( "Thac0", Class->thac0_00, fread_number( fp ) );
                KEY( "Thac32", Class->thac0_32, fread_number( fp ) );
                break;
        }
        if ( !fMatch ) {
            bug( "load_class_file: no match: %s", word );
            fread_to_eol( fp );
        }
    }
    return FALSE;
}
Beispiel #3
0
/*
 * Hit one guy with a projectile.
 * Handles use of missile weapons (wield = missile weapon)
 * or thrown items/weapons
 */
ch_ret projectile_hit( char_data * ch, char_data * victim, obj_data * wield, obj_data * projectile, short dist )
{
   int vic_ac, thac0, plusris, diceroll, prof_bonus, prof_gsn = -1, proj_bonus, dt, pchance;
   double dam = 0;
   ch_ret retcode;

   if( !projectile )
      return rNONE;

   if( projectile->item_type == ITEM_PROJECTILE || projectile->item_type == ITEM_WEAPON )
   {
      dt = TYPE_HIT + projectile->value[3];
      if( wield )
         proj_bonus = number_range( wield->value[1], wield->value[2] );
      else
         proj_bonus = 0;
   }
   else
   {
      dt = TYPE_UNDEFINED;
      proj_bonus = 0;
   }

   /*
    * Can't beat a dead char!
    */
   if( victim->position == POS_DEAD || victim->char_died(  ) )
   {
      projectile->extract(  );
      return rVICT_DIED;
   }

   if( wield )
      prof_bonus = weapon_prof_bonus_check( ch, wield, prof_gsn );
   else
      prof_bonus = 0;

   if( dt == TYPE_UNDEFINED )
   {
      dt = TYPE_HIT;
      if( wield && wield->item_type == ITEM_MISSILE_WEAPON )
         dt += wield->value[3];
   }

   thac0 = calc_thac0( ch, victim, dist );

   vic_ac = umax( -19, ( victim->GET_AC(  ) / 10 ) );

   /*
    * if you can't see what's coming... 
    */
   if( !victim->can_see_obj( projectile, false ) )
      vic_ac += 1;
   if( !ch->can_see( victim, false ) )
      vic_ac -= 4;

   /*
    * Weapon proficiency bonus 
    */
   vic_ac += prof_bonus;

   /*
    * The moment of excitement!
    */
   while( ( diceroll = number_bits( 5 ) ) >= 20 )
      ;

   if( diceroll == 0 || ( diceroll != 19 && diceroll < thac0 - vic_ac ) )
   {
      /*
       * Miss. 
       */
      if( prof_gsn != -1 )
         ch->learn_from_failure( prof_gsn );

      /*
       * Do something with the projectile 
       */
      if( number_percent(  ) < 50 )
         projectile->extract(  );
      else
      {
         if( projectile->carried_by )
            projectile->from_char(  );
         projectile->to_room( victim->in_room, victim );
      }
      damage( ch, victim, 0, dt );
      return rNONE;
   }

   /*
    * Hit.
    * Calc damage.
    */

   pchance = number_range( 1, 10 );

   switch ( pchance )
   {
      case 1:
      case 2:
      case 3: /* Hit in the arm */
         dam = number_range( projectile->value[1], projectile->value[2] ) + proj_bonus;
         break;

      case 4:
      case 5:
      case 6: /* Hit in the leg */
         dam = number_range( ( 2 * projectile->value[1] ), ( 2 * projectile->value[2] ) ) + proj_bonus;
         break;

      default:
      case 7:
      case 8:
      case 9:
      case 10:   /* Hit in the chest */
         dam = number_range( ( 3 * projectile->value[1] ), ( 3 * projectile->value[2] ) ) + proj_bonus;
         break;
   }

   /*
    * Bonuses.
    */
   dam += ch->GET_DAMROLL(  );

   if( prof_bonus )
      dam += prof_bonus / 4;

   /*
    * Calculate Damage Modifiers from Victim's Fighting Style
    */
   if( victim->position == POS_BERSERK )
      dam = 1.2 * dam;
   else if( victim->position == POS_AGGRESSIVE )
      dam = 1.1 * dam;
   else if( victim->position == POS_DEFENSIVE )
      dam = .85 * dam;
   else if( victim->position == POS_EVASIVE )
      dam = .8 * dam;

   if( !ch->isnpc(  ) && ch->pcdata->learned[gsn_enhanced_damage] > 0 && number_percent(  ) < ch->pcdata->learned[gsn_enhanced_damage] )
      dam += ( int )( dam * ch->LEARNED( gsn_enhanced_damage ) / 120 );
   else
      ch->learn_from_failure( gsn_enhanced_damage );

   if( !victim->IS_AWAKE(  ) )
      dam *= 2;

   if( dam <= 0 )
      dam = 1;

   plusris = 0;

   if( projectile->extra_flags.test( ITEM_MAGIC ) )
      dam = ris_damage( victim, dam, RIS_MAGIC );
   else
      dam = ris_damage( victim, dam, RIS_NONMAGIC );

   /*
    * Handle PLUS1 - PLUS6 ris bits vs. weapon hitroll   -Thoric
    */
   if( wield )
      plusris = wield->hitroll(  );

   /*
    * check for RIS_PLUSx - Thoric 
    */
   if( dam )
   {
      int x, res, imm, sus, mod;

      if( plusris )
         plusris = RIS_PLUS1 << UMIN( plusris, 7 );

      /*
       * initialize values to handle a zero plusris 
       */
      imm = res = -1;
      sus = 1;

      /*
       * find high ris 
       *//*
       * FIXME: Absorb handling needs to be included
       */
      for( x = RIS_PLUS1; x <= RIS_PLUS6; ++x )
      {
         if( victim->has_immune( x ) )
            imm = x;
         if( victim->has_resist( x ) )
            res = x;
         if( victim->has_suscep( x ) )
            sus = x;
      }
      mod = 10;
      if( imm >= plusris )
         mod -= 10;
      if( res >= plusris )
         mod -= 2;
      if( sus <= plusris )
         mod += 2;

      /*
       * check if immune 
       */
      if( mod <= 0 )
         dam = -1;
      if( mod != 10 )
         dam = ( dam * mod ) / 10;
   }

   /*
    * immune to damage 
    */
   if( dam == -1 )
   {
      if( dt >= 0 && dt < num_skills )
      {
         skill_type *skill = skill_table[dt];
         bool found = false;

         if( skill->imm_char && skill->imm_char[0] != '\0' )
         {
            act( AT_HIT, skill->imm_char, ch, nullptr, victim, TO_CHAR );
            found = true;
         }
         if( skill->imm_vict && skill->imm_vict[0] != '\0' )
         {
            act( AT_HITME, skill->imm_vict, ch, nullptr, victim, TO_VICT );
            found = true;
         }
         if( skill->imm_room && skill->imm_room[0] != '\0' )
         {
            act( AT_ACTION, skill->imm_room, ch, nullptr, victim, TO_NOTVICT );
            found = true;
         }
         if( found )
         {
            if( number_percent(  ) < 50 )
               projectile->extract(  );
            else
            {
               if( projectile->carried_by )
                  projectile->from_char(  );
               projectile->to_room( victim->in_room, victim );
            }
            return rNONE;
         }
      }
      dam = 0;
   }
   if( ( retcode = damage( ch, victim, dam, dt ) ) != rNONE )
   {
      if( projectile->value[5] == PROJ_STONE )
         projectile->extract(  );
      else
      {
         if( victim->char_died(  ) )
         {
            projectile->extract(  );
            return rVICT_DIED;
         }
         projectile->from_char(  );
         projectile->to_char( victim );
         projectile->extra_flags.set( ITEM_LODGED );

         switch ( pchance )
         {
            case 1:
            case 2:
            case 3: /* Hit in the arm */
               projectile->wear_flags.set( ITEM_LODGE_ARM );
               wear_obj( victim, projectile, true, get_wflag( "lodge_arm" ) );
               break;

            case 4:
            case 5:
            case 6: /* Hit in the leg */
               projectile->wear_flags.set( ITEM_LODGE_LEG );
               wear_obj( victim, projectile, true, get_wflag( "lodge_leg" ) );
               break;

            default:
            case 7:
            case 8:
            case 9:
            case 10:   /* Hit in the chest */
               projectile->wear_flags.set( ITEM_LODGE_RIB );
               wear_obj( victim, projectile, true, get_wflag( "lodge_rib" ) );
               break;
         }
      }
      return retcode;
   }
   if( ch->char_died(  ) )
   {
      projectile->extract(  );
      return rCHAR_DIED;
   }
   if( victim->char_died(  ) )
   {
      projectile->extract(  );
      return rVICT_DIED;
   }

   retcode = rNONE;
   if( dam == 0 )
   {
      if( number_percent(  ) < 50 )
         projectile->extract(  );
      else
      {
         if( projectile->carried_by )
            projectile->from_char(  );
         projectile->to_room( victim->in_room, victim );
      }
      return retcode;
   }

   /*
    * weapon spells -Thoric 
    */
   if( wield && !victim->has_immune( RIS_MAGIC ) && !victim->in_room->flags.test( ROOM_NO_MAGIC ) )
   {
      list < affect_data * >::iterator paf;

      for( paf = wield->pIndexData->affects.begin(  ); paf != wield->pIndexData->affects.end(  ); ++paf )
      {
         affect_data *af = *paf;

         if( af->location == APPLY_WEAPONSPELL && IS_VALID_SN( af->modifier ) && skill_table[af->modifier]->spell_fun )
            retcode = ( *skill_table[af->modifier]->spell_fun ) ( af->modifier, 7, ch, victim );
      }
      if( retcode != rNONE || ch->char_died(  ) || victim->char_died(  ) )
      {
         projectile->extract(  );
         return retcode;
      }

      for( paf = wield->affects.begin(  ); paf != wield->affects.end(  ); ++paf )
      {
         affect_data *af = *paf;

         if( af->location == APPLY_WEAPONSPELL && IS_VALID_SN( af->modifier ) && skill_table[af->modifier]->spell_fun )
            retcode = ( *skill_table[af->modifier]->spell_fun ) ( af->modifier, 7, ch, victim );
      }
      if( retcode != rNONE || ch->char_died(  ) || victim->char_died(  ) )
      {
         projectile->extract(  );
         return retcode;
      }
   }
   projectile->extract(  );
   return retcode;
}