Bowfire Code v1.0 (c)1997-99 Feudal Realms 

This is my bow and arrow code that I wrote based off of a thrown weapon code
that I had from long ago (if you wrote it let me know so I can give you
credit for that part, I do not have it anymore), it's a little more complex 
than I had originally wanted, but well, it works.  There are a couple things 
that are involved which if you don't want to use, remove them, that simple.  
One of them are the use of the "lodged" wearbits.  The code is designed to 
lodge an arrow in a victim, not just do damage to them once, and there are three
places it can lodge, etc.  Included are all of the pieces of code for quivers,
arrows, drawing arrows, dislodging, etc.  Use whatever of this code that you
want, if you have a credits page, add me on there, and please drop me an email
at mustang@roscoe.mudservices.com so I know its out there somewhere being used.

Any bugs that people find, if you email me, I will fix, unless it's something
from a modification that you made, and if that's the case, I will probably
help you figure out what's up with it if I can.  My code is not stock, and I
tried to add in everything that people might need to add in this feature.

Thanks,
Tch

===============================================================================
Features in v1.0

- Bowfire from adjacent rooms at targets
- Arrows lodge in various body parts (leg, arm, and chest)
- Quiver and arrow new item types
- Shoulder wearbit used for quivers (if you want it)
- Dislodging arrows does damage
- OLC support for arrows and quivers

===============================================================================

Add in a bow weapon type with the other ones on the list.(if you don't know 
how to do this, grep/search for sword and add in bow in the respective places)
		
===============================================================================

In act_info.c in "void do_look" add this

case ITEM_QUIVER:
		if ( obj->value[0] <= 0 )
		{
		send_to_char( "{WThe quiver is out of arrows.{x\n\r", ch );
		break;
		}
		
		if (obj->value[0] == 1 )
		{
		send_to_char( "{WThe quiver has 1 arrow remaining in it.{x\n\r", ch );
		break;
		}
		
		if (obj->value[0] > 1 )
		{
		sprintf( buf, "{WThe quiver has %d arrows in it.{x\n\r", obj->value[0]);
		}
		send_to_char( buf, ch);
		break;

And add these to the end of "char *	const	where_name	[] ="

	"{W({Rlodged in a leg{W){x  ",
	"{W({Rlodged in an arm{W){x ",
	"{W({Rlodged in a rib{W){x  ",

===============================================================================

In act_obj.c add these (or whatever file you want, that's just where mine is)


/* Bowfire code -- used to draw an arrow from a quiver */
void do_draw( CHAR_DATA *ch, char *argument )
{  
    OBJ_DATA *quiver;
	OBJ_DATA *arrow;
    int hand_count= 0;
	
    if ( ( quiver = get_eq_char( ch, WEAR_SHOULDER ) ) == NULL )
    {
	send_to_char( "{WYou aren't wearing a quiver where you can get to it.{x\n\r", ch );
	return;
    }

    if ( quiver->item_type != ITEM_QUIVER )
    {
	send_to_char( "{WYou can only draw arrows from a quiver.{x\n\r", ch );
	return;
    }

	if (get_eq_char(ch,WEAR_LIGHT) != NULL) hand_count++;
   	if (get_eq_char(ch,WEAR_SHIELD)!= NULL) hand_count++; 
   	if (get_eq_char(ch,WEAR_HOLD)  != NULL) hand_count++;  
   	if (get_eq_char(ch,WEAR_WIELD) != NULL) hand_count++;
	if ( hand_count > 1)
	{
		send_to_char (	"{WYou need a free hand to draw an arrow.{x\n\r", ch );
		return;
	}
	
	if ( get_eq_char(ch, WEAR_HOLD) != NULL)
	{
	       send_to_char ( "{WYour hand is not empty!{x\n\r", ch );
	       return;
	}

    if ( quiver->value[0] > 0 )
    {
	WAIT_STATE( ch, PULSE_VIOLENCE );	
	act( "{W$n draws an arrow from $p{W.{x", ch, quiver, NULL, TO_ROOM );
	act( "{WYou draw an arrow from $p{W.{x", ch, quiver, NULL, TO_CHAR );
	
	arrow = create_object(get_obj_index(OBJ_VNUM_ARROW), 0);
	arrow->value[1] = quiver->value[1];
	arrow->value[2] = quiver->value[2];
	arrow->level    = quiver->level;
	obj_to_char(arrow,ch);
	wear_obj( ch,arrow,TRUE );
	quiver->value[0] -= quiver->value[1];
	
	
    if ( quiver->value[0] <= 0 )
    {
	act( "{WYour $p {Wis now out of arrows, you need to find another one.{x", ch, quiver, NULL, TO_CHAR );
	extract_obj(quiver);
    }

    return;
	}
}


/* Bowfire code -- Used to dislodge an arrow already lodged */
void do_dislodge( CHAR_DATA *ch, char *argument )
{
	OBJ_DATA * arrow = NULL;
	int dam = 0;
	
    if (argument[0] == '\0') /* empty */
    {
        send_to_char ("{WDislodge what?{x\n\r",ch);
        return;
    }	
	
	if ( get_eq_char(ch, WEAR_LODGE_RIB) != NULL)
	{
	arrow = get_eq_char( ch, WEAR_LODGE_RIB );
	act( "{WWith a wrenching pull, you dislodge $p {Wfrom your chest.{x", ch, arrow, NULL, TO_CHAR );
	unequip_char( ch, arrow );
	arrow->extra_flags = arrow->extra_flags - 134217728;
	dam      =  dice((3 * arrow->value[1]), (3 * arrow->value[2]));
	damage( ch, ch, dam, gsn_bow, DAM_SLASH, TRUE );
	return;
	}	
	
	else
	if (get_eq_char(ch,WEAR_LODGE_ARM) != NULL)
	{
	arrow = get_eq_char( ch, WEAR_LODGE_ARM );
	act( "{WWith a tug you dislodge $p {Wfrom your arm.{x", ch, arrow, NULL, TO_CHAR );
	unequip_char( ch, arrow );
	arrow->extra_flags = arrow->extra_flags - 134217728;
	dam      =  dice((3 * arrow->value[1]), (2 * arrow->value[2]));
	damage( ch, ch, dam, gsn_bow, DAM_SLASH, TRUE );
	return;
	}	
	
	else
	if (get_eq_char(ch,WEAR_LODGE_LEG) != NULL)  
	{
	arrow = get_eq_char( ch, WEAR_LODGE_LEG );
	act( "{WWith a tug you dislodge $p {Wfrom your leg.{x", ch, arrow, NULL, TO_CHAR );
	unequip_char( ch, arrow );
	arrow->extra_flags = arrow->extra_flags - 134217728;
	dam      =  dice((2 * arrow->value[1]), (2 * arrow->value[2]));
	damage( ch, ch, dam, gsn_bow, DAM_SLASH, TRUE );
	return;
	}
	else
	{	
	send_to_char("{WYou have nothing lodged in your body.{x\n\r", ch);
	return;
	}
}	

===============================================================================

In act_wiz.c add this to do_ostat

    case ITEM_QUIVER:
		sprintf(buf,"{WIt holds {R%d %d{Wd{R%d {Warrows.{x\n\r",
		obj->value[0], obj->value[1], obj->value[2]);
		send_to_char(buf,ch);
		break;
	case ITEM_ARROW:
		sprintf(buf,"{WThis arrow will do {R%d{Wd{R%d {Wdamage for an average of {R%d{W.{x\n\r",
		obj->value[1], obj->value[2], ( obj->value[1] + obj->value[2] ) / 2 );
		send_to_char(buf,ch);
		break;


===============================================================================

In const.c add this (modify it to your # of classes of course)

	{
    "bow",               
	{ IM, IM, IM, IM, IM, 25, IM, 10, IM },     
	{ 0,  0,  0,  0, 0,  5, 0, 4, 0},
    spell_null,             TAR_IGNORE,             POS_FIGHTING,
    &gsn_bow,     			SLOT( 0),       0,      0,
    "arrow",                     "!Bow!",		""
    },
	
and this to the "const struct item_type		item_table	[]	="

	{	ITEM_QUIVER,	"quiver"	},
	{	ITEM_ARROW,		"arrow",	},
	
===============================================================================

In db.c add this to "void load_old_obj" add in what's between the arrows

->	case ITEM_STAFF:
	case ITEM_QUIVER:
	case ITEM_ARROW:
->	case ITEM_WAND:
	    pObjIndex->value[3] = slot_lookup( pObjIndex->value[3] );
	    break;

And in "void reset_room" add in what's between the arrows

->             case ITEM_WAND:         olevel = number_range( 10, 20 ); break;
			   case ITEM_QUIVER:         olevel = number_range( 10, 20 ); break;
			   case ITEM_ARROW:         olevel = number_range( 10, 20 ); break;
->             case ITEM_STAFF:        olevel = number_range( 15, 25 ); break;

And in "OBJ_DATA *create_object" add in what's between the arrows

->	break;

    case ITEM_QUIVER:
	case ITEM_ARROW:
->	case ITEM_WEAPON:

===============================================================================

In db2.c in "void load_objects" add this anywhere

	case ITEM_QUIVER:
	case ITEM_ARROW:
			pObjIndex->value[0]		= fread_number(fp);
		    pObjIndex->value[1]		= fread_number(fp);
		    pObjIndex->value[2]		= fread_number(fp);
		    pObjIndex->value[3]		= fread_number(fp);
		    pObjIndex->value[4]		= fread_number(fp);
		    break;

And in "void convert_object" add in what's between the arrows

->      case ITEM_BOAT:
		case ITEM_QUIVER:
		case ITEM_ARROW:
->      case ITEM_CORPSE_NPC:

===============================================================================

In fight.c add this

/* Bowfire code -- actual firing function */
void do_fire( CHAR_DATA *ch, char *argument )
{
    char arg[MAX_INPUT_LENGTH];
    CHAR_DATA *victim = NULL;
    OBJ_DATA *arrow;
	OBJ_DATA *bow;
    ROOM_INDEX_DATA *was_in_room;
    EXIT_DATA *pexit;
    int dam ,door ,chance;


    bow = get_eq_char(ch, WEAR_WIELD);
    if (bow == NULL)
	{
	send_to_char("{WWhat are you going to do, throw the arrow at them?{x\n\r", ch);
	return;
	}

    if (bow->value[0] != WEAPON_BOW)
	{
	send_to_char("{WYou might want to use a bow to fire that arrow with{x\n\r", ch);
	return;
	}    

    one_argument( argument, arg );
    if ( arg[0] == '\0' && ch->fighting == NULL )
    {
        send_to_char( "{WFire an arrow at who?{x\n\r", ch );
        return;
    }

	if (!str_cmp(arg, "none") || !str_cmp(arg, "self") || victim == ch)
	{
		send_to_char("{WHow exactly did you plan on firing an arrow at yourself?{x\n\r", ch );
		return;
	}

    if ( ( arrow = get_eq_char( ch, WEAR_HOLD ) ) == NULL )
    {
        send_to_char( "{WYou hold nothing in your hand.{x\n\r", ch );
        return;
    }


    if ( arrow->item_type != ITEM_ARROW )
    {
        send_to_char( "{WYou can only a fire arrows or quarrels.{x\n\r", ch );
        return;
    }
	
    if ( arg[0] == '\0' )
    {
        if ( ch->fighting != NULL )
        {
            victim = ch->fighting;
        }
        else
        {
            send_to_char( "{WFire at whom or what?{x\n\r", ch );
            return;
        }
    }
    else
    {
        
	/* See if who you are trying to shoot at is nearby... */

        if ( ( victim = get_char_room ( ch, arg ) ) == NULL)
        {
            was_in_room=ch->in_room;


            for( door=0 ; door<=5 && victim==NULL ; door++ )
             { 
                if ( (  pexit = was_in_room->exit[door] ) != NULL
                   &&   pexit->u1.to_room != NULL
                   &&   pexit->u1.to_room != was_in_room 
                   &&   !strcmp( pexit->u1.to_room->area->name ,
                                was_in_room->area->name ) )
                   { 
                     ch->in_room = pexit->u1.to_room;
                     victim = get_char_room ( ch, arg ); 
                    }
               
              }


            ch->in_room=was_in_room;
            if(victim==NULL)
              {
               send_to_char( "{WYou can't find it.{x\n\r", ch );
               return;
              }
            else
              {  if(IS_SET(pexit->exit_info,EX_CLOSED))
                    { send_to_char("{WYou can't fire through a door.{x",ch);
                      return;
                     } 
             }
        }
    }




if((ch->in_room) == (victim->in_room))
{
send_to_char("{WDon't you think that standing a bit further away would be wise?{x\n\r", ch);
return;
}

/* Lag the bowman... */
WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); 

/* Fire the damn thing finally! */


if(arrow->item_type== ITEM_ARROW )
   {
        
      /* Valid target? */
        
        if ( victim != NULL )
        {
            act( "{W$r {Wfires $p {Wat $R{W.{x", ch,  arrow, victim, TO_NOTVICT );
            act( "{WYou fire $p {Wat $R{W.{x", ch,   arrow, victim, TO_CHAR );
            act( "{W$r {Wfires $p {Wat you.{x",ch,   arrow, victim, TO_VICT );
        }


      /* Did it hit? */
      
        if (ch->level <   arrow->level
        ||  number_percent() >= 20 + get_skill(ch,gsn_bow) * 4/5 )
        {       
             /* denied... */
                     
              act( "{WYou fire $p {Wmissing, and it lands harmlessly on the ground.{x",
                 ch,  arrow,NULL,TO_CHAR);
              act( "{W$r fires $p {Wmissing, and it lands harmlessly on the ground.{x",
                 ch,  arrow,NULL,TO_ROOM);
              obj_from_char(arrow);
			  obj_to_room(arrow, victim->in_room);
          check_improve(ch,gsn_bow,FALSE,2);
        }
        else
        {      
               /* Shawing battah!  Now, where did it thud into? */


	chance=dice(1,10);
    switch (chance)
    {
    case 1 :
	case 2 :
	case 3 :
	case 4 :
	case 5 :
	case 6 :
            obj_from_char(arrow);
			obj_to_char(arrow, victim);
			arrow->wear_flags = 8388609;
			wear_obj(victim, arrow,TRUE);
			arrow->wear_flags = 65537;
			arrow->extra_flags = arrow->extra_flags + 134217728;
            dam      =  dice(arrow->value[1],arrow->value[2]);
			damage( ch, victim, dam, gsn_bow, DAM_PIERCE, TRUE );						
			check_improve(ch,gsn_bow,TRUE,2);
			break;
	case 7 :
	case 8 :
	case 9 :
            obj_from_char(arrow);
			obj_to_char(arrow, victim);
			arrow->wear_flags = 16777217;
			wear_obj(victim, arrow,TRUE);
			arrow->wear_flags = 65537;
			arrow->extra_flags = arrow->extra_flags + 134217728;
            dam      = 3*( dice(arrow->value[1],arrow->value[2]))/2;
			damage( ch, victim, dam, gsn_bow, DAM_PIERCE, TRUE );						
			check_improve(ch,gsn_bow,TRUE,2);
			break;
	case 10 :
            obj_from_char(arrow);
			obj_to_char(arrow, victim);
			arrow->wear_flags = 33554433;
			wear_obj(victim, arrow,TRUE);
			arrow->wear_flags = 65537;
			arrow->extra_flags = arrow->extra_flags + 134217728;
            dam      = 2*( dice(arrow->value[1],arrow->value[2]));
			damage( ch, victim, dam, gsn_bow, DAM_PIERCE, TRUE );						
			check_improve(ch,gsn_bow,TRUE,2);
			break;
	}		
   }

  } 

    return;
}

===============================================================================

In handler.c add this to "char *extra_bit_name( int extra_flags )"

	if ( extra_flags & ITEM_LODGED		 ) strcat( buf, " lodged"		);

===============================================================================

In merc.h add these with the other wearbit defines

#define WEAR_LODGE_LEG				27
#define WEAR_LODGE_ARM				28
#define WEAR_LODGE_RIB				29

*** If you change the numbers, change the stuff on dislodge and such, they match
    up to the numbers in there to make it work right...
	
And add this to the extra flags for items

#define ITEM_LODGED			(bb)

And add this to the item declarations

#define ITEM_QUIVER			 	35
#define ITEM_ARROW				36

And add this to the static eq vnums (you can change the 1208, that's just what
I used, it can go in any area, it really doesn't matter, I put it in immortal)

#define OBJ_VNUM_ARROW			   1208 

===============================================================================	

In olc_act.c (if you use OLC) add this to "void show_obj_values"

	case ITEM_QUIVER:
		sprintf( buf, "[v0] Number of Arrows:     %d\n\r", obj->value[0] );
		send_to_char( buf, ch);
		sprintf( buf, "[v1] Number of Dice:       %d\n\r", obj->value[1] );
		send_to_char( buf, ch);
		sprintf( buf, "[v2] Type of Dice:         %d\n\r", obj->value[2] );
		send_to_char( buf, ch);		
		sprintf( buf, "[v3] Spell:                %s\n\r",
		obj->value[3] != -1 ? skill_table[obj->value[3]].name
				                    : "none" );
		send_to_char( buf, ch);
		break;

	case ITEM_ARROW:
		sprintf( buf, "[v1] Number of Dice:       %d\n\r", obj->value[1] );
		send_to_char( buf, ch);
		sprintf( buf, "[v2] Type of Dice:         %d\n\r", obj->value[2] );
		send_to_char( buf, ch);		
		sprintf( buf, "[v3] Spell:                %s\n\r",
		obj->value[3] != -1 ? skill_table[obj->value[3]].name
				                    : "none" );
		send_to_char( buf, ch);
		break;
		
And in "bool set_obj_values" add this in

	case ITEM_QUIVER:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_QUIVER" );
	            return FALSE;
	        case 0:
	            send_to_char( "NUMBER OF ARROWS SET.\n\r\n\r", ch );
	            pObj->value[0] = atoi( argument );
	            break;
	        case 1:
	            send_to_char( "NUMBER OF DICE SET.\n\r\n\r", ch );
	            pObj->value[1] = atoi( argument );
	            break;
	        case 2:
	            send_to_char( "TYPE OF DICE SET.\n\r\n\r", ch );
	            pObj->value[2] = atoi( argument );
	            break;
	    }
            break;

case ITEM_ARROW:
	    switch ( value_num )
	    {
	        default:
		    do_help( ch, "ITEM_ARROW" );
	            return FALSE;
				
	        case 1:
	            send_to_char( "NUMBER OF DICE SET.\n\r\n\r", ch );
	            pObj->value[1] = atoi( argument );
	            break;
	        case 2:
	            send_to_char( "TYPE OF DICE SET.\n\r\n\r", ch );
	            pObj->value[2] = atoi( argument );
	            break;
	    }
            break;

===============================================================================	
	
In olc_save.c (if you use OLC) add this to "void save_object"

	  	case ITEM_QUIVER:
			fprintf( fp, "%d ", pObjIndex->value[0] );
			fprintf( fp, "%d ", pObjIndex->value[1] );
			fprintf( fp, "%d 0 0\n", pObjIndex->value[2]);
			break;

	  	case ITEM_ARROW:
			fprintf( fp, "0 %d ", pObjIndex->value[1] );
			fprintf( fp, "%d 0 0\n", pObjIndex->value[2]);
			break;

===============================================================================

In tables.c add these to the end of "const struct flag_type wear_loc_flags[] ="

	{	"lodge_leg",	WEAR_LODGE_LEG,	TRUE	},
	{	"lodge_arm",	WEAR_LODGE_ARM,	TRUE	},
	{	"lodge_rib",	WEAR_LODGE_RIB,	TRUE	},
	
And add this to "const struct flag_type extra_flags[] ="
	
	{	"lodged",			ITEM_LODGED,		TRUE	},

And add this to "const struct flag_type type_flags[] ="

	{	"quiver",		ITEM_QUIVER,		TRUE	},
	{	"arrow",		ITEM_ARROW,			TRUE	},
	
===============================================================================	

In immortal.are add this to the object list (or any other area/vnum, just change
the declaration for it in merc.h if you do)

#1208
an arrow~
an arrow~
A wooden arrow is here.~
unknown~
arrow 0 AQ
0 0 0 0 0
9 0 0 P


===============================================================================
