/*___________________________________________________________________________*
)()( DalekenMUD 1.12 (C) 2000 )()(
`][' by Martin Thomson, Lee Brooks, `]['
|| Ken Herbert and David Jacques ||
|| ----------------------------------------------------------------- ||
|| Envy Diku Mud improvements copyright (C) 1994 by Michael Quan, ||
|| David Love, Guilherme 'Willie' Arnold, and Mitchell Tse. ||
|| Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael ||
|| Chastain, Michael Quan, and Mitchell Tse. ||
|| Original Diku Mud copyright (C) 1990, 1991 ||
|| by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt, ||
|| Tom Madsen, and Katja Nyboe. ||
|| ----------------------------------------------------------------- ||
|| Any use of this software must follow the licenses of the ||
|| creators. Much time and thought has gone into this software and ||
|| you are benefitting. We hope that you share your changes too. ||
|| What goes around, comes around. ||
|| ----------------------------------------------------------------- ||
|| act_obj.c ||
|| Object manipulation code. ||
*_/<>\_________________________________________________________________/<>\_*/
#include "mud.h"
#include "event.h"
/*
* Local Functions.
*/
void sac_obj args( ( CHAR_DATA *ch, OBJ_DATA *obj ) );
/*
* Wear location / body part reliance table, new slots can be added easily here.
* Format:
* ITEM_WEAR_* - where the item is worn.
* BODY_PART_* - what body part(s) is/are required to wear.
* - message when they don't have the part(s).
* - display of slot for 'equipment' and 'peek'.
* - message that the character gets when they wear it, see act().
* - message that everyone else gets when they wear it, see act().
*/
const struct wear_stuff wear_table[MAX_WEAR] =
{
{ 0, 0, NULL, NULL },
{
ITEM_WEAR_HEAD,
BODY_PART_HEAD, "You don't have a head.",
"&b<worn on head> &n",
"&bYou wear $p on your head.",
"&b$n wears $p on $s head."
},
{
ITEM_WEAR_HORNS,
BODY_PART_HORNS, "You don't have any horns.",
"&b<worn on horns> &n",
"&bYou wear $p on your horns.",
"&b$n wears $p on $s horns."
},
{
ITEM_WEAR_EAR,
BODY_PART_EAR_L, "You don't have a left ear.",
"&b<worn through left ear> &n",
"&bYou stick $p through your left ear.",
"&b$n sticks $p through $s left ear."
},
{
ITEM_WEAR_EAR,
BODY_PART_EAR_R, "You don't have a right ear.",
"&b<worn through right ear> &n",
"&bYou stick $p through your right ear.",
"&b$n sticks $p through $s right ear."
},
{
ITEM_WEAR_FACE,
BODY_PART_HEAD, "You don't have a head.",
"&b<worn on face> &n",
"&bYou put $p on your face.",
"&b$n puts $p on $s face."
},
{
ITEM_WEAR_NOSE,
BODY_PART_NOSE, "You don't have a nose.",
"&b<worn on nose> &n",
"&bYou wear $p on your nose.",
"&b$n wears $p on $s nose."
},
{
ITEM_WEAR_NECK,
BODY_PART_HEAD | BODY_PART_TORSO, "You don't have a head and body.",
"&b<worn on neck (1)> &n",
"&bYou slip $p over your head.",
"&b$n slips $p over $s head."
},
{
ITEM_WEAR_NECK,
BODY_PART_HEAD | BODY_PART_TORSO, "You don't have a head and body.",
"&b<worn on neck (2)> &n",
"&bYou slip $p over your head.",
"&b$n slips $p over $s head."
},
{
ITEM_WEAR_SHOULDERS,
BODY_PART_TORSO, "You don't have a body.",
"&b<worn about shoulders> &n",
"&bYou arrange $p around your shoulders.",
"&b$n arranges $p around $s shoulders."
},
{
ITEM_WEAR_WINGS,
BODY_PART_WINGS, "You don't have any wings.",
"&b<worn on wings> &n",
"&bYou wear $p on your wings.",
"&b$n wears $p on $s wings."
},
{
ITEM_FLOAT,
0, "You stupid, stupid monkey!",
"&b<floating over left shoulder> &n",
"&bYou release $p to float over your left shoulder.",
"&b$n releases $p to float over $s left shoulder."
},
{
ITEM_FLOAT,
0, "You stupid, stupid monkey!",
"&b<floating over right shoulder>&n",
"&bYou release $p to float over your right shoulder.",
"&b$n releases $p to float over $s right shoulder."
},
{
ITEM_WEAR_ARMS,
BODY_PART_ARMS, "You don't have any arms.",
"&b<worn on arms> &n",
"&bYou wear $p on your arms.",
"&b$n wears $p on $s arms."
},
{
ITEM_WEAR_WRIST,
BODY_PART_ARM_L, "You don't have a left arm.",
"&b<worn on left wrist> &n",
"&bYou clasp $p around your left wrist.",
"&b$n clasps $p around $s left wrist."
},
{
ITEM_WEAR_WRIST,
BODY_PART_ARM_R, "You don't have a right arm.",
"&b<worn on right wrist> &n",
"&bYou clasp $p around your right wrist.",
"&b$n clasps $p around $s right wrist."
},
{
ITEM_WEAR_HANDS,
BODY_PART_HANDS, "You don't have a left and right hand.",
"&b<worn on hands> &n",
"&bYou slip your hands into $p.",
"&b$n slip your hands into $p."
},
{
ITEM_WEAR_FINGER,
BODY_PART_FINGERS_L, "You don't have any left hand fingers.",
"&b<worn on left finger> &n",
"&bYou slip $p into a finger on your left hand.",
"&b$n slips $p onto a finger on $s left hand."
},
{
ITEM_WEAR_FINGER,
BODY_PART_FINGERS_R, "You don't have any right hand fingers.",
"&b<worn on right finger> &n",
"&bYou slip $p onto a finger on your right hand.",
"&b$n slips $p onto a finger on $s right hand."
},
{
ITEM_WIELD,
BODY_PART_HAND_R | BODY_PART_FINGERS_R, "You don't have a right hand and fingers.",
"&b<wielded in right hand> &n",
"&bYou wield $p in your right hand.",
"&b$n wields $p in $s right hand."
},
{
ITEM_HOLD,
BODY_PART_HAND_L | BODY_PART_FINGERS_L, "You don't have a left hand and fingers.",
"&b<held in left hand> &n",
"&bYou hold $p in your left hand.",
"&b$n holds $p in $s left hand."
},
{
ITEM_HOLD,
BODY_PART_HAND_R | BODY_PART_FINGERS_R, "You don't have a right hand and fingers.",
"&b<held in right hand> &n",
"&bYou hold $p in your right hand.",
"&b$n holds $p in $s right hand."
},
{
ITEM_WEAR_SHIELD,
BODY_PART_HAND_L | BODY_PART_FINGERS_L, "You don't have a left hand and fingers.",
"&b<worn as a shield> &n",
"&bYou wear $p in your shield hand.",
"&b$n wears $p in $s shield hand."
},
{
ITEM_WIELD,
BODY_PART_HAND_L | BODY_PART_FINGERS_L, "You don't have a left hand and fingers.",
"&b<wielded in left hand> &n",
"&bYou wield $p in your left hand.",
"&b$n wields $p in $s left hand."
},
{
ITEM_WIELD_DOUBLE,
BODY_PART_HANDS | BODY_PART_FINGERS, "You don't have enough hands and fingers.",
"&b<wielded two-handed> &n",
"&bYou wield $p in both hands, ururur.",
"&b$n wields $p two-handed, pretty impressive eh?"
},
{
ITEM_WEAR_BODY,
BODY_PART_TORSO, "You don't have a body.",
"&b<worn on body> &n",
"&bYou wear $p on your body.",
"&b$n wears $p on $s body."
},
{
ITEM_WEAR_WAIST,
BODY_PART_TORSO, "You don't have a body.",
"&b<worn about waist> &n",
"&bYou wrap $p around your waist.",
"&b$n wraps $p around $s waist."
},
{
ITEM_WEAR_LEGS,
BODY_PART_LEGS, "You don't have any legs.",
"&b<worn on legs> &n",
"&bYou slip your legs into $p.",
"&b$n slips $s legs into $p."
},
{
ITEM_WEAR_ANKLE,
BODY_PART_LEG_L | BODY_PART_FOOT_L,
"You don't have a left leg or foot.",
"&b<worn on left ankle> &n",
"&bYou clasp $p around your left ankle.",
"&b$n clasps $p around $s left ankle."
},
{
ITEM_WEAR_ANKLE,
BODY_PART_LEG_R | BODY_PART_FOOT_R,
"You don't have a right leg or foot.",
"&b<worn on right ankle> &n",
"&bYou clasp $p around your right ankle.",
"&b$n clasps $p around $s right ankle."
},
{
ITEM_WEAR_FEET,
BODY_PART_FEET, "You don't have any feet.",
"&b<worn on feet> &n",
"&bYou wear $p on your feet.",
"&b$n wears $p on $s feet."
},
{
0, /* not here for wearing -- Juggling */
BODY_PART_FEET, "You are a hopeless juggler.",
"&b<whirling above the head> &n",
"&bYou toss $p up and begin to juggle it nervously.",
"&b$n throws $p in the air juggling it easily."
}
};
/*
* Local functions.
*/
void get_obj args( ( CHAR_DATA *ch, OBJ_DATA *obj,
OBJ_DATA *container ) );
void wear_obj args( ( CHAR_DATA *ch, OBJ_DATA *obj,
bool fReplace ) );
CHAR_DATA *find_keeper args( ( CHAR_DATA *ch, char *argument ) );
int get_cost args( ( CHAR_DATA *keeper, CHAR_DATA *customer, OBJ_DATA *obj,
bool fBuy ) );
void get_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container )
{
if( !CAN_WEAR( obj, ITEM_TAKE ) )
{
send_to_char( "You can't take that.\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_BURIED ) )
{
send_to_char( "That item is buried, you cant get it.\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_QUEST )
&& ( IS_NPC( ch ) || ch->pcdata->quest->target != obj ) )
{
send_to_char( "You can't touch someone elses quest item.\n\r", ch );
return;
}
if( obj->item_type != ITEM_MONEY )
{
if( ch->carry_number >= can_carry_n( ch ) )
{
act( "&c$d&g: you can't carry that many items.&n",
ch, NULL, obj->name, TO_CHAR );
return;
}
if( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
{
act( "&c$d&g: you can't carry that much weight.&n",
ch, NULL, obj->name, TO_CHAR );
return;
}
}
if( obj->in_room != NULL )
{
CHAR_DATA *gch;
for( gch = obj->in_room->people; gch != NULL; gch = gch->next_in_room )
if( gch->on == obj )
{
act( "$N appear$% to be using $p.", ch, obj, gch, TO_CHAR );
return;
}
}
if( xIS_SET( obj->pIndexData->progtypes, GET_PROG ) )
{
if( oprog_percent_check( ch, obj, NULL, GET_PROG ) == 0 )
return;
}
if( container )
{
act( "&gYou get $p from $P.&n", ch, obj, container, TO_CHAR );
act( "&g$n gets $p from $P.&n", ch, obj, container, TO_ROOM );
if( container->item_type == ITEM_PORTAL )
{
ROOM_INDEX_DATA *room = obj->in_room;
obj_from_room( obj );
if( room && room->people )
{
act( "&gYou see a large arm come and take $p.&n",
room->people, obj, NULL, TO_CHAR );
act( "&gYou see a large arm come and take $p.&n",
room->people, obj, NULL, TO_ROOM );
}
}
else
obj_from_obj( obj );
}
else
{
act( "&gYou get $p.&n", ch, obj, container, TO_CHAR );
act( "&g$n gets $p.&n", ch, obj, container, TO_ROOM );
obj_from_room( obj );
}
if( IS_OBJ_STAT( obj, ITEM_HOLY ) )
{
act( "&gYou are burned by &rHOLY FIRE&g from $p. &rOuch!&n",
ch, obj, NULL, TO_CHAR );
act( "&g$n is burned by &rHOLY FIRE&g from $p!&n",
ch, obj, NULL, TO_ROOM );
damage( ch, ch, 50, gsn_burn, WEAR_NONE );
if( ch->deleted )
return;
}
if( obj->item_type == ITEM_MONEY )
{
char buf[MAX_INPUT_LENGTH];
int amount;
amount = obj->value[0];
ch->gold += amount;
if( IS_NPC( ch ) )
ch->in_room->area->economy += amount;
if( amount > 1 )
{
charprintf( ch, "&gYou counted &y%d&g coins.&n\n\r", amount );
/* Autosplit by Symposium */
if( xIS_SET( ch->act, PLR_AUTOSPLIT ) && amount > 1 )
{
sprintf( buf, "%d " AUTOLOOK, amount );
do_split( ch, buf );
}
}
extract_obj( obj );
return;
}
obj_to_char( obj, ch );
return;
}
void do_get( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
OBJ_DATA *container;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *room = NULL;
bool found;
argument = one_argument( argument, arg1 );
one_argument( argument, arg2 );
/*
* Get type.
*/
if( arg1[0] == '\0' )
{
send_to_char( "Get what?\n\r", ch );
return;
}
if( arg2[0] == '\0' )
{
if( IS_AFFECTED( ch, AFF_GHOUL ) )
{
send_to_char( "You can't get anything in ghoul form.\n\r", ch );
return;
}
if( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
{
/*
* 'get obj'
*/
obj = get_obj_list( ch, arg1, ch->in_room->contents );
if( !obj )
{
act( "&gI see no $T here.&n", ch, NULL, arg1, TO_CHAR );
return;
}
get_obj( ch, obj, NULL );
}
else
{
/*
* 'get all' or 'get all.obj'
*/
OBJ_DATA *obj_next;
found = FALSE;
for( obj = ch->in_room->contents; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( ( arg1[3] == '\0' || is_obj_name( obj, &arg1[4] ) )
&& can_see_obj( ch, obj ) )
{
found = TRUE;
get_obj( ch, obj, NULL );
}
}
if( !found )
{
if( arg1[3] == '\0' )
send_to_char( "I see nothing here.\n\r", ch );
else
act( "&gI see no $T here.&n", ch, NULL, &arg1[4], TO_CHAR );
}
}
}
else
{
/*
'get ... container'
*/
if( !str_cmp( arg2, "all" ) || !str_prefix( "all.", arg2 ) )
{
send_to_char( "You can't do that.\n\r", ch );
return;
}
if( !( container = get_obj_here( ch, arg2 ) ) )
{
act( "&gI see no $T here.&n", ch, NULL, arg2, TO_CHAR );
return;
}
if( IS_AFFECTED( ch, AFF_GHOUL )
&& container->item_type != ITEM_CORPSE_PC
&& container->carried_by != ch )
{
send_to_char( "&gYou can't get anything in ghoul form.&n\n\r", ch );
return;
}
switch( container->item_type )
{
default:
send_to_char( "&gThat's not a container.&n\n\r", ch );
return;
case ITEM_PORTAL:
room = get_room_index( container->value[0] );
if( !room )
{
send_to_char( "You can't use that.\n\r", ch );
return;
}
break;
case ITEM_CONTAINER:
case ITEM_CORPSE_NPC:
break;
case ITEM_CORPSE_PC:
if( IS_NPC( ch ) || ( !IS_IMMORTAL( ch )
&& str_infix( ch->name, container->name ) ) )
{
send_to_char( "&gYou can't do that.&n\n\r", ch );
return;
}
}
if( !room && IS_SET( container->value[1], CONT_CLOSED ) )
{
act( "&gThe $d is closed.&n", ch, NULL, container->name, TO_CHAR );
return;
}
if( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
{
/*
'get obj container'
*/
if( !room )
obj = get_obj_list( ch, arg1, container->contains );
else
obj = get_obj_list( ch, arg1, room->contents );
if( !obj )
{
act( "&gI see nothing like that in the $T.&n",
ch, NULL, arg2, TO_CHAR );
return;
}
if( !xIS_SET( container->pIndexData->progtypes, LOOT_PROG )
|| oprog_percent_check( ch, container, NULL, LOOT_PROG ) )
get_obj( ch, obj, container );
}
else
{
/*
'get all container' or 'get all.obj container'
*/
OBJ_DATA *obj_next;
found = FALSE;
for( obj = ( room ) ? room->contents : container->contains;
obj; obj = obj_next )
{
obj_next = obj->next_content;
if( ( arg1[3] == '\0' || is_obj_name( obj, &arg1[4] ) )
&& can_see_obj( ch, obj ) )
{
found = TRUE;
get_obj( ch, obj, container );
}
}
if( !xIS_SET( container->pIndexData->progtypes, LOOT_PROG )
|| oprog_percent_check( ch, container, NULL, LOOT_PROG ) )
{
if( !found )
{
if( arg1[3] == '\0' )
act( "&gI see nothing in the $T.&n",
ch, NULL, arg2, TO_CHAR );
else
act( "&gI see nothing like that in the $T.&n",
ch, NULL, arg2, TO_CHAR );
}
}
}
}
return;
}
void do_put( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *container;
OBJ_DATA *obj;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
ROOM_INDEX_DATA *room = NULL;
argument = one_argument( argument, arg1 );
one_argument( argument, arg2 );
if( arg1[0] == '\0' || arg2[0] == '\0' )
{
send_to_char( "Put what in what?\n\r", ch );
return;
}
if( !str_cmp( arg2, "all" ) || !str_prefix( "all.", arg2 ) )
{
send_to_char( "You can't do that.\n\r", ch );
return;
}
if( !( container = get_obj_here( ch, arg2 ) ) )
{
act( "I see no $T here.", ch, NULL, arg2, TO_CHAR );
return;
}
if( container->item_type != ITEM_CONTAINER
&& container->item_type != ITEM_PORTAL )
{
send_to_char( "That's not a container.\n\r", ch );
return;
}
if( container->item_type == ITEM_PORTAL )
room = get_room_index( container->value[0] );
if( IS_SET( container->value[1], CONT_CLOSED ) )
{
act( "The $d is closed.", ch, NULL, container->name, TO_CHAR );
return;
}
if( str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) )
{
/*
'put obj container'
*/
if( !( obj = get_obj_carry( ch, arg1 ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( obj == container )
{
send_to_char( "You can't fold it into itself.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( container->item_type == ITEM_CONTAINER
&& !IS_SET( container->value[1], CONT_WEIGHTLESS )
&& get_obj_weight( obj ) + get_obj_weight( container )
- container->weight > container->value[0] )
{
send_to_char( "It won't fit.\n\r", ch );
return;
}
obj_from_char( obj );
act( "&gYou put $p &gin $P&g.&n", ch, obj, container, TO_CHAR );
act( "&g$n puts $p &gin $P&g.&n", ch, obj, container, TO_ROOM );
if( container->item_type == ITEM_PORTAL )
{
if( room )
{
obj_to_room( obj, room );
if( room->people )
{
act( "$p drops from the sky.", room->people,
obj, NULL, TO_CHAR );
act( "$p drops from the sky.", room->people,
obj, NULL, TO_ROOM );
}
}
}
else
{
if( IS_SET( container->value[1], CONT_HOLEY ) )
{
act( "&g$p &gdrops through to the floor.&n",
ch, obj, container, TO_ROOM );
obj_to_room( obj, ch->in_room );
}
else if( IS_SET( container->value[1], CONT_HUNGRY ) )
{
extract_obj( obj );
act( "&r$P &rburps loudly.&n", ch, NULL, container, TO_CHAR );
act( "&r$P &rburps loudly.&n", ch, NULL, container, TO_ROOM );
}
else
obj_to_obj( obj, container );
oprog_container_putin( ch, container, obj );
}
}
else
{
/*
* 'put all container' or 'put all.obj container'
*/
OBJ_DATA *obj_next;
for( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( ( arg1[3] == '\0' || is_obj_name( obj, &arg1[4] ) )
&& can_see_obj( ch, obj )
&& obj->wear_loc == WEAR_NONE
&& obj != container
&& can_drop_obj( ch, obj )
&& ( ( container->item_type == ITEM_CONTAINER
&& ( IS_SET( container->value[1], CONT_WEIGHTLESS )
|| get_obj_weight( obj ) + get_obj_weight( container )
<= container->value[0] ) )
|| ( container->item_type == ITEM_PORTAL && room ) )
&& !( obj->item_type == ITEM_WEAPON && ch->level < L_APP
&& IS_SET( obj->extra_flags, ITEM_CHARGED ) ) )
{
obj_from_char( obj );
act( "&gYou put $p&g in $P&g.&n",
ch, obj, container, TO_CHAR );
act( "&g$n puts $p&g in $P&g.&n",
ch, obj, container, TO_ROOM );
if( room )
{
obj_to_room( obj, room );
if( room->people )
{
act( "$p drops from the sky.",
room->people, obj, NULL, TO_CHAR );
act( "$p drops from the sky.",
room->people, obj, NULL, TO_ROOM );
}
}
else
{
if( IS_SET( container->value[1], CONT_HOLEY ) )
{
act( "$p drops through to the floor.",
ch, obj, container, TO_ROOM );
obj_to_room( obj, ch->in_room );
}
else if( IS_SET( container->value[1], CONT_HUNGRY ) )
{
extract_obj( obj );
act( "$P burps loudly.",
ch, NULL, container, TO_CHAR );
act( "$P burps loudly.",
ch, NULL, container, TO_ROOM );
}
else
obj_to_obj( obj, container );
oprog_container_putin( ch, container, obj );
}
}
}
}
return;
}
void do_drop( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
char arg[MAX_INPUT_LENGTH];
bool found;
argument = one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "Drop what?\n\r", ch );
return;
}
if( is_number_special( arg ) )
{
/*
* 'drop NNNN coins'
*/
OBJ_DATA *obj_next;
int amount;
amount = atoi_special( arg );
one_argument( argument, arg );
if( amount <= 0 || str_prefix( arg, "coins" ) )
{
send_to_char( "Sorry, you can't do that.\n\r", ch );
return;
}
if( ch->gold < amount )
{
send_to_char( "You haven't got that many coins.\n\r", ch );
return;
}
ch->gold -= amount;
if( IS_NPC( ch ) )
ch->in_room->area->economy -= amount;
for( obj = ch->in_room->contents; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( obj->deleted )
continue;
switch( obj->pIndexData->vnum )
{
case OBJ_VNUM_MONEY_ONE:
amount += 1;
extract_obj( obj );
break;
case OBJ_VNUM_MONEY_SOME:
amount += obj->value[0];
extract_obj( obj );
break;
}
}
send_to_char( "OK.\n\r", ch );
act( "$n drops some gold.", ch, NULL, NULL, TO_ROOM );
obj = create_money( amount );
obj_to_room( obj, ch->in_room );
return;
}
if( str_cmp( arg, "all" ) && str_prefix( "all.", arg ) )
{
/*
* 'drop obj'
*/
if( !( obj = get_obj_carry( ch, arg ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( xIS_SET( obj->pIndexData->progtypes, DROP_PROG ) )
{
if( oprog_percent_check( ch, obj, NULL, DROP_PROG ) == 0 )
return;
}
if( xIS_SET( ch->in_room->progtypes, DROP_PROG ) )
{
if( rprog_percent_check( ch->in_room, ch, NULL, NULL, DROP_PROG ) == 0 )
return;
}
obj_from_char( obj );
act( "&gYou drop $p&g.&n", ch, obj, NULL, TO_CHAR );
act( "&g$n drops $p&g.&n", ch, obj, NULL, TO_ROOM );
if( IS_SET( obj->extra_flags, ITEM_FRAGILE ) && number_bits( 1 ) == 0 )
{
act( "&g$p crumbles into dust as it hits the ground.",
ch, obj, NULL, TO_CHAR );
act( "&g$p crumbles into dust as it hits the ground.",
ch, obj, NULL, TO_ROOM );
extract_obj( obj );
}
else
{
obj_to_room( obj, ch->in_room );
}
}
else
{
/*
* 'drop all' or 'drop all.obj'
*/
OBJ_DATA *obj_next;
found = FALSE;
for( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( ( arg[3] == '\0' || is_obj_name( obj, &arg[4] ) )
&& can_see_obj( ch, obj )
&& obj->wear_loc == WEAR_NONE
&& can_drop_obj( ch, obj )
&& ( !xIS_SET( obj->pIndexData->progtypes, DROP_PROG )
|| oprog_percent_check( ch, obj, NULL, DROP_PROG ) ) )
{
found = TRUE;
obj_from_char( obj );
act( "&gYou drop $p&g.&n", ch, obj, NULL, TO_CHAR );
act( "&g$n drops $p&g.&n", ch, obj, NULL, TO_ROOM );
if( IS_SET( obj->extra_flags, ITEM_FRAGILE )
&& number_bits( 1 ) == 0 )
{
act( "&g$p crumbles into dust as it hits the ground.",
ch, obj, NULL, TO_CHAR );
act( "&g$p crumbles into dust as it hits the ground.",
ch, obj, NULL, TO_ROOM );
extract_obj( obj );
}
else
obj_to_room( obj, ch->in_room );
}
}
if( !found )
{
if( arg[3] == '\0' )
send_to_char( "You are not carrying anything.\n\r", ch );
else
act( "You are not carrying any $T.",
ch, NULL, &arg[4], TO_CHAR );
}
}
return;
}
void do_give( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *victim;
OBJ_DATA *obj;
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
argument = one_argument( argument, arg1 );
argument = one_argument( argument, arg2 );
if( arg1[0] == '\0' || arg2[0] == '\0' )
{
send_to_char( "Give what to whom?\n\r", ch );
return;
}
if( is_number_special( arg1 ) )
{
/*
* 'give NNNN coins victim'
*/
char buf[MAX_STRING_LENGTH];
int amount;
amount = atoi_special( arg1 );
if( amount <= 0 || str_prefix( arg2, "coins" ) )
{
send_to_char( "Sorry, you can't do that.\n\r", ch );
return;
}
one_argument( argument, arg2 );
if( arg2[0] == '\0' )
{
send_to_char( "Give what to whom?\n\r", ch );
return;
}
if( !( victim = get_char_room( ch, arg2 ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( ch->gold < amount )
{
send_to_char( "You haven't got that much gold.\n\r", ch );
return;
}
ch->gold -= amount;
victim->gold += amount;
if( IS_NPC( victim ) )
victim->in_room->area->economy += amount;
act( "You give $N some gold.", ch, NULL, victim, TO_CHAR );
sprintf( buf, "$n gives you %d gold.", amount );
act( buf, ch, NULL, victim, TO_VICT );
act( "$n gives $N some gold.", ch, NULL, victim, TO_NOTVICT );
if( IS_NPC( victim ) &&
IS_SET( spec_table[victim->spec_fun].usage, SPEC_BRIBE ) )
( *spec_table[victim->spec_fun].spec_fun )
( victim, ch, SPEC_GIVE, &amount );
mprog_bribe_trigger( victim, ch, amount );
return;
}
if( !( obj = get_obj_carry( ch, arg1 ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "You must remove it first.\n\r", ch );
return;
}
if( !( victim = get_char_room( ch, arg2 ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( ( IS_OBJ_STAT( obj, ITEM_HOLY )
&& !str_cmp( race_table[victim->race].name, "Vampire" ) )
|| ( IS_NPC( victim ) && ( victim->pIndexData->pShop ) ) )
{
act( "$N refuses the $p.", ch, obj, victim, TO_CHAR );
act( "$n tries to give $N a $p but $E refuses.",
ch, obj, victim, TO_ROOM );
act( "You refuse to accept the $p from $n.",
ch, obj, victim, TO_VICT );
return;
}
if( victim->carry_number >= can_carry_n( victim ) )
{
act( "$N has $S hands full.", ch, NULL, victim, TO_CHAR );
return;
}
if( victim->carry_weight + get_obj_weight( obj ) > can_carry_w( victim ) )
{
act( "$N can't carry that much weight.", ch, NULL, victim, TO_CHAR );
return;
}
if( !can_see_obj( victim, obj ) )
{
act( "$N can't see it.", ch, NULL, victim, TO_CHAR );
return;
}
if( xIS_SET( obj->pIndexData->progtypes, GIVE_PROG ) )
{
if( oprog_percent_check( ch, obj, NULL, GIVE_PROG ) == 0 )
return;
}
obj_from_char( obj );
obj_to_char( obj, victim );
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
act( "You give $p to $N.", ch, obj, victim, TO_CHAR );
REMOVE_BIT( SysInfo->flags, SYSINFO_ACT_TRIGGER );
act( "$n gives you $p.", ch, obj, victim, TO_VICT );
act( "$n gives $p to $N.", ch, obj, victim, TO_NOTVICT );
if( IS_NPC( victim ) &&
IS_SET( spec_table[victim->spec_fun].usage, SPEC_GIVE ) )
( *spec_table[victim->spec_fun].spec_fun )
( victim, ch, SPEC_GIVE, obj );
mprog_give_trigger( victim, ch, obj );
return;
}
void do_fill( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
OBJ_DATA *fountain;
bool found;
if( !check_blind( ch ) )
return;
if( argument[0] == '\0' )
{
send_to_char( "Fill what?\n\r", ch );
return;
}
if( !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
found = FALSE;
for( fountain = ch->in_room->contents; fountain;
fountain = fountain->next_content )
{
if( fountain->item_type == ITEM_FOUNTAIN )
{
found = TRUE;
break;
}
}
if( !found )
{
send_to_char( "There is no fountain here!\n\r", ch );
return;
}
if( obj->item_type != ITEM_DRINK_CON )
{
send_to_char( "You can't fill that.\n\r", ch );
return;
}
if( obj->value[1] != 0 && obj->value[2] != fountain->value[2] )
{
send_to_char( "There is a different liquid in it.\n\r", ch );
return;
}
if( obj->value[1] >= obj->value[0] )
{
send_to_char( "Your container is full.\n\r", ch );
return;
}
act( "You fill $p from $P.", ch, obj, fountain, TO_CHAR );
weight_change_object( obj, UMAX( 0, obj->value[0] - obj->value[1] ) / 10 );
obj->value[2] = fountain->value[2];
obj->value[1] = obj->value[0];
return;
}
void do_drink( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int amount;
int liquid;
if( !check_blind( ch ) )
return;
if( argument[0] == '\0' )
{
for( obj = ch->in_room->contents; obj; obj = obj->next_content )
{
if( !obj->deleted && obj->item_type == ITEM_FOUNTAIN )
break;
}
if( !obj )
{
send_to_char( "Drink what?\n\r", ch );
return;
}
}
else
{
if( !( obj = get_obj_here( ch, argument ) ) )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
}
if( !IS_NPC( ch ) && ch->pcdata->condition[COND_DRUNK] > 500 )
{
send_to_char( "You fail to reach your mouth. *Hic*\n\r", ch );
return;
}
switch( obj->item_type )
{
default:
send_to_char( "You can't drink from that.\n\r", ch );
break;
case ITEM_FOUNTAIN:
liquid = obj->value[2];
if( !str_cmp( race_table[ch->race].name, "vampire" )
&& liquid != LIQ_BLOOD )
{
send_to_char( "You can't drink from that.\n\r", ch );
break;
}
if( !IS_NPC( ch ) )
{
if( liq_table[liquid].liq_affect[COND_THIRST] > 0 )
{
amount = race_table[ch->race].thirst_mod * 10
- ch->pcdata->condition[COND_THIRST];
amount /= liq_table[liquid].liq_affect[COND_THIRST];
ch->pcdata->condition[COND_THIRST]
= race_table[ch->race].thirst_mod * 10;
}
else
/* drink 10 times until you find it doesn't quench thirst */
{
amount = 100;
gain_condition( ch, COND_THIRST,
100 * liq_table[liquid].liq_affect[COND_THIRST] );
}
gain_condition( ch, COND_FULL,
amount * liq_table[liquid].liq_affect[COND_FULL] );
gain_condition( ch, COND_DRUNK,
amount * liq_table[liquid].liq_affect[COND_DRUNK] );
}
act( "You drink $T from $p.", ch, obj,
liq_table[liquid].liq_name, TO_CHAR );
act( "$n drinks $T from $p.", ch, obj,
liq_table[liquid].liq_name, TO_ROOM );
if( obj->action && obj->action[0] != '\0' )
send_to_char( obj->action, ch );
if( IS_NPC( ch ) || ch->pcdata->condition[COND_THIRST]
> race_table[ch->race].thirst_mod * 8 )
send_to_char( "You have quenched your thirst completely.\n\r", ch );
else
send_to_char( "The drink fails to refresh your thirst.\n\r", ch );
break;
case ITEM_DRINK_CON:
liquid = obj->value[2];
if( obj->value[1] <= 0 )
{
send_to_char( "It is already empty.\n\r", ch );
return;
}
act( "You drink $T from $p.",
ch, obj, liq_table[liquid].liq_name, TO_CHAR );
act( "$n drinks $T from $p.",
ch, obj, liq_table[liquid].liq_name, TO_ROOM );
if( obj->action && obj->action[0] != '\0' )
send_to_char( obj->action, ch );
amount = number_range( 3, 10 );
amount = UMIN( amount, obj->value[1] ) * 10;
weight_change_object( obj, 0 - UMIN( amount, obj->weight ) / 10 );
gain_condition( ch, COND_DRUNK,
amount * liq_table[liquid].liq_affect[COND_DRUNK] );
if( str_cmp( race_table[ch->race].name, "vampire" ) )
{
gain_condition( ch, COND_FULL,
amount * liq_table[liquid].liq_affect[COND_FULL] );
gain_condition( ch, COND_THIRST,
amount * liq_table[liquid].liq_affect[COND_THIRST] );
}
else if( liquid == LIQ_BLOOD )
{
gain_condition( ch, COND_FULL, amount * 20 );
gain_condition( ch, COND_THIRST, amount * 12 );
}
if( !IS_NPC( ch ) )
{
if( ch->pcdata->condition[COND_DRUNK] > 300 )
send_to_char( "You feel drunk.\n\r", ch );
if( ch->pcdata->condition[COND_FULL]
> race_table[ch->race].hunger_mod * 8 )
send_to_char( "You are full.\n\r", ch );
if( ch->pcdata->condition[COND_THIRST]
> race_table[ch->race].thirst_mod * 8 )
send_to_char( "You do not feel thirsty.\n\r", ch );
}
if( obj->value[3] != 0
&& !IS_SET( race_table[ch->race].race_abilities, RACE_NO_POISON ) )
{
/* The shit was poisoned ! */
AFFECT_DATA af;
send_to_char( "You choke and gag.\n\r", ch );
act( "$n chokes and gags.", ch, NULL, NULL, TO_ROOM );
af.type = gsn_poison;
af.duration = 3 * amount;
af.location = APPLY_STR;
af.modifier = -2;
vset( af.bitvector, AFF_POISON );
affect_join( ch, &af );
}
obj->value[1] -= amount / 10;
if( obj->value[1] <= 0 ) /* empty - no poison */
obj->value[3] = 0;
break;
}
return;
}
void do_eat( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
if( !check_blind( ch ) )
return;
if( argument[0] == '\0' )
{
send_to_char( "Eat what?\n\r", ch );
return;
}
if( !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( !IS_IMMORTAL( ch ) )
{
if( obj->item_type != ITEM_FOOD && obj->item_type != ITEM_PILL
&& obj->item_type != ITEM_LIMB
&& ( obj->item_type != ITEM_CORPSE_NPC
|| get_size( ch ) - 40 < race_table[obj->value[0]].size ) )
{
send_to_char( "That's not edible.\n\r", ch );
return;
}
if( !IS_NPC( ch ) && ch->pcdata->condition[COND_FULL]
> race_table[ch->race].hunger_mod * 8 )
{
send_to_char( "You are too full to eat more.\n\r", ch );
return;
}
}
act( "You eat $p.", ch, obj, NULL, TO_CHAR );
act( "$n eats $p.", ch, obj, NULL, TO_ROOM );
switch( obj->item_type )
{
case ITEM_LIMB:
case ITEM_FOOD:
case ITEM_CORPSE_NPC:
if( obj->action && obj->action[0] )
send_to_char( obj->action, ch );
if( !IS_NPC( ch ) )
{
int condition;
condition = ch->pcdata->condition[COND_FULL];
if( str_cmp( race_table[ch->race].name, "vampire" ) )
gain_condition( ch, COND_FULL,
obj->item_type == ITEM_FOOD
? obj->value[0] * 10 :
obj->item_type == ITEM_LIMB
? 150 : 750 );
if( ch->pcdata->condition[COND_FULL]
> race_table[ch->race].hunger_mod * 8 )
send_to_char( "You are full.\n\r", ch );
else if( condition == 0 && ch->pcdata->condition[COND_FULL] > 0 )
send_to_char( "You are no longer hungry.\n\r", ch );
}
if( obj->item_type != ITEM_CORPSE_NPC && obj->value[3] != 0
&& !IS_SET( race_table[ch->race].race_abilities, RACE_NO_POISON ) )
{
/* The shit was poisoned! */
AFFECT_DATA af;
act( "$n chokes and gags.", ch, 0, 0, TO_ROOM );
send_to_char( "You choke and gag.\n\r", ch );
af.type = gsn_poison;
af.duration = 2 * obj->value[0];
af.location = APPLY_STR;
af.modifier = -2;
vset( af.bitvector, AFF_POISON );
affect_join( ch, &af );
}
if( xIS_SET( obj->pIndexData->progtypes, USE_PROG ) )
oprog_percent_check( ch, obj, NULL, USE_PROG );
break;
case ITEM_PILL:
if( obj->action && obj->action[0] )
send_to_char( obj->action, ch );
if( obj->level > ch->level + 3 )
act( "$p is too high level for you.", ch, obj, NULL, TO_CHAR );
else
{
obj_cast_spell( obj->value[1], obj->value[0], ch, ch, NULL, NULL );
obj_cast_spell( obj->value[2], obj->value[0], ch, ch, NULL, NULL );
obj_cast_spell( obj->value[3], obj->value[0], ch, ch, NULL, NULL );
}
if( xIS_SET( obj->pIndexData->progtypes, USE_PROG ) )
oprog_percent_check( ch, obj, NULL, USE_PROG );
break;
}
if( !IS_NPC( ch )
|| ( IS_NPC( ch ) && is_affected( ch, gsn_charm_person ) ) )
extract_obj( obj );
return;
}
/*
* Remove an object.
*/
bool remove_obj( CHAR_DATA *ch, int iWear, bool fReplace )
{
OBJ_DATA *obj;
if( !( obj = get_eq_char( ch, iWear ) ) )
return TRUE;
if( !fReplace )
return FALSE;
if( IS_SET( obj->extra_flags, ITEM_NOREMOVE ) )
{
act( "You can't remove $p.", ch, obj, NULL, TO_CHAR );
return FALSE;
}
/* Questionable code */
if( ch->class == CLASS_ANGEL && obj->pIndexData->vnum == 46 )
{
send_to_char( "Angels cannot remove their wings.\n\r", ch );
return FALSE;
}
if( !xIS_SET( obj->pIndexData->progtypes, REMOVE_PROG )
|| oprog_percent_check( ch, obj, NULL, REMOVE_PROG ) )
{
act( "$n stops using $p.", ch, obj, NULL, TO_ROOM );
act( "You stop using $p.", ch, obj, NULL, TO_CHAR );
unequip_char( ch, obj );
return TRUE;
}
else
return FALSE;
}
void remove_juggled( CHAR_DATA *ch, OBJ_DATA *obj )
{
if( obj->wear_loc != WEAR_JUGGLED )
return;
act( "$n smoothly catches $p.", ch, obj, NULL, TO_ROOM );
act( "You grab $p carefully.", ch, obj, NULL, TO_CHAR );
unequip_char( ch, obj );
if( xIS_SET( obj->pIndexData->progtypes, REMOVE_PROG ) )
oprog_percent_check( ch, obj, NULL, REMOVE_PROG );
}
/*
* New, neater wear_obj, still the need for some yucky stuff though,
* watch for the hands, this requires some sticky code.
* Compatible with the previous version in all respects.
* --Symposium.
*/
void wear_obj( CHAR_DATA *ch, OBJ_DATA *obj, bool fReplace )
{
int i, j;
int wear_right = WEAR_NONE;
int wear_left = WEAR_NONE;
int weight;
if( IS_SET( obj->extra_flags, ITEM_BURIED ) )
{
send_to_char( "You cant very well wear a buried item.\n\r", ch );
return;
}
if( ch->level < obj->level - 3 && obj->item_type != ITEM_LIMB )
{
charprintf( ch, "You must be level %d to use this object.\n\r",
obj->level - 3 );
act( "$n tries to use $p, but is too inexperienced.",
ch, obj, NULL, TO_ROOM );
return;
}
if( obj->required_skill > 0 && !can_use( ch, obj->required_skill ) )
{
send_to_char( "You need a skill to use this item.\n\r", ch );
act( "$n tries to wear $p but lacks the skill.",
ch, obj, NULL, TO_ROOM );
return;
}
if( obj->item_type == ITEM_ARMOUR && obj->value[1] >= 0
&& ( get_size( ch ) + 10 < obj->value[1]
|| get_size( ch ) - 10 > obj->value[1] ) )
{
if( get_size( ch ) > obj->value[1] )
send_to_char(
"You find that it is a little too small for you.\n\r", ch );
else
send_to_char(
"You find that it is a little too large for you.\n\r", ch );
act( "$n tries to wear $p, but it doesn't fit.",
ch, obj, NULL, TO_ROOM );
return;
}
for( i = 0; i < MAX_WEAR; i++ )
{
if( !CAN_WEAR( obj, wear_table[i].wear_flag ) )
continue;
/* find if there is another slot that the item can occupy */
for( j = i+1; j < MAX_WEAR; j++ )
if( CAN_WEAR( obj, wear_table[j].wear_flag ) )
break;
/* WHAT A MESS!!!!! -- Symposium */
if( i == WEAR_WIELD_R || i == WEAR_HOLD_L || i == WEAR_WIELD_DOUBLE
|| i == WEAR_SHIELD )
{
if( get_eq_char( ch, WEAR_WIELD_R ) )
wear_right = WEAR_WIELD_R;
else if( get_eq_char( ch, WEAR_HOLD_R ) )
wear_right = WEAR_HOLD_R;
if( get_eq_char( ch, WEAR_WIELD_L ) )
wear_left = WEAR_WIELD_L;
else if( get_eq_char( ch, WEAR_HOLD_L ) )
wear_left = WEAR_HOLD_L;
else if( get_eq_char( ch, WEAR_SHIELD ) )
wear_left = WEAR_SHIELD;
if( get_eq_char( ch, WEAR_WIELD_DOUBLE ) )
{
wear_right = WEAR_WIELD_DOUBLE;
wear_left = WEAR_WIELD_DOUBLE;
}
switch( i )
{
case WEAR_WIELD_R:
if( ( IS_NPC( ch ) || can_use( ch, gsn_dual )
|| IS_SET( race_table[ch->race].race_abilities, RACE_DUAL_WIELD ) )
&& wear_right == WEAR_WIELD_R )
{
if( wear_left == WEAR_NONE
|| remove_obj( ch, wear_left, fReplace )
|| remove_obj( ch, wear_right, fReplace ) )
break;
else
continue;
}
else if( wear_right != WEAR_NONE
&& !remove_obj( ch, wear_right, fReplace ) )
continue;
if( get_obj_weight( obj ) > str_app_wield( get_curr_str( ch ) ) )
{
send_to_char( "It is too heavy for you to wield.\n\r", ch );
continue;
}
break;
case WEAR_HOLD_L:
if( wear_left == WEAR_NONE || wear_right == WEAR_NONE )
break;
if( !remove_obj( ch, wear_left, fReplace )
&& !remove_obj( ch, wear_right, fReplace ) )
continue;
if( get_eq_char( ch, wear_left ) )
i = WEAR_HOLD_R;
break;
case WEAR_SHIELD:
if( wear_left != WEAR_NONE
&& !remove_obj( ch, wear_left, fReplace ) )
continue;
break;
case WEAR_WIELD_DOUBLE:
if( !IS_NPC( ch ) && !can_use( ch, gsn_two_handed ) )
{
act( "You can't use $P yet.", ch, NULL, obj, TO_CHAR );
return;
}
if( wear_left == WEAR_WIELD_DOUBLE
&& !remove_obj( ch, wear_left, fReplace ) )
continue;
if( ( wear_left != WEAR_NONE
&& !remove_obj( ch, wear_left, fReplace ) )
|| ( wear_right != WEAR_NONE
&& !remove_obj( ch, wear_right, fReplace ) ) )
continue;
break;
}
/*
* weapon weight stuff, this is also a true mess!
* check if wielding in another hand and then check if
* combined weight is enough.
* --Symposium
*/
switch( i )
{
case WEAR_WIELD_R:
weight = get_obj_weight( obj );
if( get_eq_char( ch, WEAR_WIELD_L ) )
weight += get_obj_weight( get_eq_char( ch, WEAR_WIELD_L ) );
else if( get_eq_char( ch, WEAR_WIELD_R ) )
weight += get_obj_weight( get_eq_char( ch, WEAR_WIELD_R ) );
if( weight > str_app_wield( get_curr_str( ch ) ) )
{
send_to_char( "It is too heavy for you to wield.\n\r", ch );
continue;
}
case WEAR_WIELD_DOUBLE:
if( get_obj_weight( obj ) > str_app_wield( get_curr_str( ch ) ) )
{
send_to_char( "It is too heavy for you to wield.\n\r", ch );
return;
}
default:
break;
}
}
/* these should have been taken care of before */
else if( i == WEAR_WIELD_L || i == WEAR_HOLD_R )
continue;
/* second equip slot, check this too */
else if( j < MAX_WEAR )
{
if( get_eq_char( ch, i ) && get_eq_char( ch, j )
&& !remove_obj( ch, i, fReplace )
&& !remove_obj( ch, j, fReplace ) )
continue;
}
else
{
if( !remove_obj( ch, i, fReplace ) )
continue;
}
/*
* this problem could be avoided by making the first hand
* for held items the right hand, however this makes it a
* little less player friendly and the confusion with gear
* changes is allready sufficient.
* --Symposium
*/
if( get_eq_char( ch, i )
|| ( i == WEAR_HOLD_L && wear_left != WEAR_NONE
&& get_eq_char( ch, wear_left ) ) )
i = j;
if( ( ( ch->body_parts & wear_table[i].body_parts )
!= wear_table[i].body_parts ) )
{
if( j >= MAX_WEAR || get_eq_char( ch, j ) )
{
act( wear_table[i].no_part, ch, NULL, NULL, TO_CHAR );
continue;
}
i = j;
if( ( ch->body_parts & wear_table[i].body_parts )
!= wear_table[i].body_parts )
{
act( wear_table[i].no_part, ch, NULL, NULL, TO_CHAR );
continue;
}
}
if( !xIS_SET( obj->pIndexData->progtypes, WEAR_PROG )
|| oprog_percent_check( ch, obj, NULL, WEAR_PROG ) )
{
act( wear_table[i].wear_on_ch, ch, obj, NULL, TO_CHAR );
act( wear_table[i].wear_on_room, ch, obj, NULL, TO_ROOM );
equip_char( ch, obj, i );
}
return;
}
if( fReplace )
send_to_char( "You can't wear, wield, or hold that.\n\r", ch );
return;
}
void do_wear( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
if( !IS_NPC( ch ) && IS_AFFECTED( ch, AFF_GHOUL ) )
{
send_to_char(
"You may not wear, wield, or hold anything in ghoul form.\n\r",
ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char( "Wear, wield, or hold what?\n\r", ch );
return;
}
if( !str_cmp( argument, "all" ) )
{
OBJ_DATA *obj_next;
for( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( obj->wear_loc != WEAR_NONE || !can_see_obj( ch, obj ) )
continue;
if( CAN_WEAR( obj, ITEM_WIELD )
&& IS_SET( race_table[ch->race].race_abilities,
RACE_NO_WEAPON_WIELD ) )
continue;
wear_obj( ch, obj, FALSE );
}
return;
}
else
{
if( !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( CAN_WEAR( obj, ITEM_WIELD )
&& IS_SET( race_table[ch->race].race_abilities,
RACE_NO_WEAPON_WIELD ) )
{
send_to_char( "You are not able to wield a weapon.\n\r", ch );
return;
}
wear_obj( ch, obj, TRUE );
}
return;
}
void do_remove( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
if( argument[0] == '\0' )
{
send_to_char( "Remove what?\n\r", ch );
return;
}
if( !str_cmp( argument, "all" ) )
{
for( obj = ch->carrying; obj; obj = obj->next_content )
{
if( obj->deleted || !can_see_obj( ch, obj ) )
continue;
if( obj->wear_loc == WEAR_JUGGLED )
remove_juggled( ch, obj );
else if( obj->wear_loc != WEAR_NONE )
remove_obj( ch, obj->wear_loc, TRUE );
}
return;
}
if( !( obj = get_obj_wear( ch, argument ) ) )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( obj->wear_loc == WEAR_JUGGLED )
remove_juggled( ch, obj );
else
remove_obj( ch, obj->wear_loc, TRUE );
return;
}
void do_juggle( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
OBJ_DATA *other;
OBJ_DATA *right = NULL;
OBJ_DATA *left = NULL;
int num = 0;
int weight = 0;
if( !IS_NPC( ch ) && !can_use( ch, gsn_juggle ) )
{
send_to_char(
"You'd better not try to juggle dangerous implements just yet.\n\r", ch );
return;
}
if( argument[0] == '\0' )
{
send_to_char( "You want to juggle what?\n\r", ch );
return;
}
if( !IS_NPC( ch ) && IS_AFFECTED( ch, AFF_GHOUL ) )
{
send_to_char(
"You may not wear, wield, or hold anything in ghoul form.\n\r",
ch );
return;
}
if( !( obj = get_obj_here( ch, argument ) ) )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( IS_OBJ_STAT( obj, ITEM_NOREMOVE ) || IS_OBJ_STAT( obj, ITEM_NODROP )
|| obj->item_type != ITEM_WEAPON )
{
act( "$p is too clumsy to juggle.\n\r", ch, obj, NULL, TO_CHAR );
return;
}
for( other = ch->carrying; other; other = other->next_content )
{
if( other->deleted )
continue;
if( other->wear_loc == WEAR_WIELD_L )
left = other;
else if( other->wear_loc == WEAR_WIELD_R )
right = other;
else if( other->wear_loc == WEAR_JUGGLED )
{
if( ++num >= MAX_JUGGLED - 2 )
{
send_to_char( "You are testing your skills to the limit, no more.\n\r", ch );
return;
}
weight += get_obj_weight( other );
}
}
if( !left || !right )
{
send_to_char( "You have to have a weapon in each hand to start.\n\r",
ch );
return;
}
weight += get_obj_weight( left );
weight += get_obj_weight( right );
weight += get_obj_weight( obj );
if( weight > str_app_wield( get_curr_str( ch ) ) * 2 / 3 )
{
send_to_char( "You can't hold that much weight aloft.\n\r", ch );
return;
}
if( !xIS_SET( obj->pIndexData->progtypes, WEAR_PROG )
|| oprog_percent_check( ch, obj, NULL, WEAR_PROG ) )
{
act( wear_table[WEAR_JUGGLED].wear_on_ch, ch, obj, NULL, TO_CHAR );
act( wear_table[WEAR_JUGGLED].wear_on_room, ch, obj, NULL, TO_ROOM );
equip_char( ch, obj, WEAR_JUGGLED );
WAIT_STATE( ch, skill_table[gsn_juggle].beats );
}
return;
}
void stop_juggling( CHAR_DATA *ch )
{
OBJ_DATA *obj;
if( ch->position < POS_FIGHTING )
return;
juggle_shuffle( ch ); /* could be lethal */
if( ch->deleted || ch->position < POS_FIGHTING
|| !( obj = get_eq_char( ch, WEAR_JUGGLED ) ) )
return;
send_to_char( "You stop juggling.\n\r", ch );
do
{
unequip_char( ch, obj );
}
while( ( obj = get_eq_char( ch, WEAR_JUGGLED ) ) );
return;
}
void do_sacrifice( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
bool found = FALSE;
if( argument[0] == '\0' || !str_cmp( argument, ch->name ) )
{
send_to_char( "God appreciates your offer and may accept it later.\n\r", ch );
act( "$n offers $mself to $s God, who graciously declines.",
ch, NULL, NULL, TO_ROOM );
return;
}
if ( str_cmp( argument, "all" ) && str_prefix( "all.", argument ) )
{
obj = get_obj_list( ch, argument, ch->in_room->contents );
if( !obj )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( !CAN_WEAR( obj, ITEM_TAKE ) )
{
act( "$p is not an acceptable sacrifice.", ch, obj, NULL, TO_CHAR );
return;
}
sac_obj( ch, obj );
}
else
{
/* 'sac all' or 'sac all.obj' */
OBJ_DATA *obj_next;
for ( obj = ch->in_room->contents; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( ( argument[3] == '\0' || is_obj_name( obj, &argument[4] ) )
&& CAN_WEAR( obj, ITEM_TAKE ) )
{
found = TRUE;
sac_obj( ch, obj );
}
}
if( !found )
{
if( argument[3] == '\0' )
send_to_char( "You can't find anything to sacrifice.\n\r", ch );
else
act( "You can't find any $T to sacrifice.",
ch, NULL, &argument[4], TO_CHAR );
}
}
return;
}
void sac_obj( CHAR_DATA *ch, OBJ_DATA *obj )
{
AFFECT_DATA *af;
CHAR_DATA *mob;
MOB_INDEX_DATA *pMob;
char buf[MAX_STRING_LENGTH];
int i, event, level;
int race;
race = obj->value[0];
level = obj->level;
act( "$n sacrifices $p to $g.", ch, obj, NULL, TO_ROOM );
if( obj->item_type == ITEM_CORPSE_NPC && !IS_NPC( ch )
&& ch->pcdata->clan && ch->pcdata->clan->clan_type == CLAN_ORDER )
add_karma( ch->pcdata->clan, 1 );
if( xIS_SET( obj->pIndexData->progtypes, SAC_PROG )
&& oprog_percent_check( ch, obj, NULL, SAC_PROG ) == 0 )
return;
if( !obj->deleted )
extract_obj( obj );
event = number_bits( 4 );
if( IS_NPC( ch ) || !ch->pcdata->religion
|| !IS_SET( ch->pcdata->religion->sac_events, 1<<event ) )
event = SAC_EVENT_GOLD;
switch( event )
{
case SAC_EVENT_GOLD:
if( number_bits( 3 ) == 0 )
{
send_to_char( "Your god smiles on you.\n\r", ch );
level *= 2;
}
default:
level = number_fuzzy( level );
charprintf( ch, "&yGod gives you %d gold coin%s for your sacrifice.&n\n\r",
level, level != 1 ? "s" : "" );
ch->gold += level;
break;
case SAC_EVENT_BLESS:
act( "A light shines down on $n.", ch, NULL, NULL, TO_ROOM );
i = skill_lookup( "bless" );
spell_bless( i, UMIN( 30, level / 2 ), ch, ch );
break;
case SAC_EVENT_CURSE:
act( "A dark cloud surrounds $n.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You feel unclean.\n\r", ch );
af = new_affect( );
af->type = gsn_hex;
af->duration = UMIN( 10, level / 2 );
vzero( af->bitvector );
af->location = APPLY_HITROLL;
af->modifier = UMAX( -10, -2 - level / 20 );
affect_to_char( ch, af, NULL );
break;
case SAC_EVENT_ARMOUR:
act( "A light shines down on $n.", ch, NULL, NULL, TO_ROOM );
i = skill_lookup( "armour" );
spell_armour( i, UMIN( 40, level / 2 ), ch, ch );
break;
case SAC_EVENT_HEAL:
act( "A light shines down on $n.", ch, NULL, NULL, TO_ROOM );
i = skill_lookup( "cure" );
spell_cure( i, UMIN( 30, level / 2 ), ch, ch );
break;
case SAC_EVENT_DISPEL_EVIL:
act( "A ball of fire falls from the heavens upon $n.",
ch, NULL, NULL, TO_ROOM );
i = skill_lookup( "condemn" );
spell_condemn( i, UMIN( 30, level / 2 ), NULL, ch );
break;
case SAC_EVENT_BLIND:
act( "A very bright light shines down on $n",
ch, NULL, NULL, TO_ROOM );
send_to_char( "You are struck blind!\n\r", ch );
i = skill_lookup( "blindness" );
af = new_affect( );
af->type = i;
af->duration = UMIN( 10, level / 2 );
vset( af->bitvector, AFF_BLIND );
af->modifier = 0;
af->location = 0;
affect_to_char( ch, af, NULL );
break;
case SAC_EVENT_BAMF:
act( "$n disappears suddenly.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You have been transferred.\n\r", ch );
bamf( ch );
break;
case SAC_EVENT_MANA:
send_to_char( "You feel a strong burst of power.\n\r", ch );
mana_gain( ch );
break;
case SAC_EVENT_FOOD:
act( "$n's God provides for $m.", ch, NULL, NULL, TO_ROOM );
send_to_char( "God provides for you.\n\r", ch );
i = skill_lookup( "create food" );
spell_create_food( i, UMIN( 20, level / 2 ), ch, ch );
break;
case SAC_EVENT_WATER:
act( "$n's God provides for $m.", ch, NULL, NULL, TO_ROOM );
send_to_char( "God provides for you.\n\r", ch );
ch->pcdata->condition[COND_THIRST] = 96;
break;
case SAC_EVENT_DRUNK:
act( "$n's God makes fun for $m.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You feel a little light headed.\n\r", ch );
ch->pcdata->condition[COND_DRUNK] += UMIN( obj->level * 5, 300 );
break;
case SAC_EVENT_RAISE:
act( "$n tries to sacrifice the corpse but it's alive.",
ch, NULL, NULL, TO_ROOM );
send_to_char( "Oh No! It lives!\n\r", ch );
pMob = get_mob_index( MOB_VNUM_ZOMBIE );
pMob->level += level - 5;
mob = create_mobile( pMob );
pMob->level += 5 - level;
sprintf( buf, mob->name, race_table[race].name );
free_string( mob->name );
mob->name = str_dup( buf );
sprintf( buf, mob->short_descr, race_table[race].name );
free_string( mob->short_descr );
mob->short_descr = str_dup( buf );
sprintf( buf, mob->long_descr, race_table[race].name );
free_string( mob->long_descr );
mob->long_descr = str_dup( buf );
mob->gold = 0;
char_to_room( mob, ch->in_room );
act( "$n rises from the ground and attacks!",
mob, NULL, NULL, TO_ROOM );
multi_hit( mob, ch, TYPE_UNDEFINED );
create_char_event( mob, evn_gate_demon,
percent_fuzzy( level * 15 + 300, 12 )
* PULSE_PER_SECOND );
break;
case SAC_EVENT_PLAGUE:
act( "A dark cloud surrounds $n.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You feel cold and you shiver.\n\r", ch );
af = new_affect( );
af->type = gsn_plague;
af->duration = UMIN( 20, level / 2 );
af->location = APPLY_STR;
af->modifier = 0 - UMIN( 5, level / 10 );
vset( af->bitvector, AFF_PLAGUE );
affect_to_char( ch, af, NULL );
break;
}
return;
}
void do_study( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *book;
int amount, chance;
if( IS_NPC( ch ) )
{
send_to_char( "You can't learn anything more than you already know.\n\r",
ch );
return;
}
REMOVE_BIT( ch->pcdata->pc_bits, PC_BIT_RACIAL );
if( !( book = get_obj_carry( ch, argument ) ) )
{
send_to_char( "You do not have that scroll.\n\r", ch );
return;
}
if( book->item_type != ITEM_BOOK )
{
send_to_char( "You can study only books.\n\r", ch );
return;
}
if( book->level > ch->level + 3 )
{
send_to_char( "You are too inexperienced to use this.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_study].beats );
act( "$n concentrate$% hard on learning from $p.",
ch, book, NULL, TO_ALL );
if( book->action && book->action[0] )
send_to_char( book->action, ch );
if( book->value[0] <= 0 )
{
send_to_char( "The pages all seem to be blank!", ch );
return;
}
/*
* Scrolls skill by Binky for EnvyMud, modified by Thelonius
*/
if( !IS_NPC( ch )
&& !get_success( ch, gsn_study, 80 ) )
{
switch( number_bits( 3 ) )
{
case 0:
case 1:
case 2:
case 3:
act( "$n can't understand $p at all.",
ch, book, NULL, TO_ALL );
return;
case 4:
case 5:
case 6:
act( "$n must have said something incorrectly.",
ch, NULL, NULL, TO_ALL );
act( "$p disolves to dust in your hands.",
ch, book, NULL, TO_CHAR );
act( "$p suddenly disolves into fine dust.",
ch, book, NULL, TO_ROOM );
extract_obj( book );
return;
case 7:
act( "$n must have triggered something, $p suddenly explodes!",
ch, book, NULL, TO_ALL );
/*
* damage( ) call after extract_obj in case the damage would
* have extracted ch. This is okay because we merely mark
* obj->deleted; it still retains all values until list_update.
* Sloppy? Okay, create another integer variable. ---Thelonius
*/
extract_obj( book );
damage( ch, ch, 2 * book->level, gsn_study, WEAR_NONE );
return;
}
}
if( can_use( ch, book->value[0] ) )
amount = adept_level( ch, book->value[0] ) + book->value[2];
else
amount = book->value[2];
/* absolute maximum */
amount = UMIN( amount, book->value[3] );
amount -= ch->pcdata->learned[book->value[0]];
/* relative maximum */
amount = UMIN( amount, book->value[1] );
if( amount <= 0 )
{
act( "You can't learn any more from $p.", ch, book, NULL, TO_CHAR );
return;
}
chance = number_range( 1, get_curr_int( ch ) + get_curr_wis( ch ) / 2 );
if( chance < amount )
{
act( "&BWith some difficulty, you manage to learn about $T from $p.",
ch, book, skill_table[book->value[0]].name, TO_CHAR );
ch->pcdata->learned[book->value[0]] += chance;
}
else
{
act( "&BYou study $p and learn a little about $T!",
ch, book, skill_table[book->value[0]].name, TO_CHAR );
ch->pcdata->learned[book->value[0]] += amount;
}
act( "$n appears to have gleaned some knowledge from $p.",
ch, book, NULL, TO_ROOM );
extract_obj( book );
return;
}
void do_steal( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
CHAR_DATA *victim;
char buf[MAX_STRING_LENGTH];
char arg1[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg[MAX_INPUT_LENGTH];
int number;
int count;
int percent;
if( IS_NPC( ch ) )
{
send_to_char( "That, you cannot do.\n\r", ch );
return;
}
argument = one_argument( argument, arg1 );
one_argument( argument, arg2 );
if( arg1[0] == '\0' || arg2[0] == '\0' )
{
send_to_char( "Steal what from whom?\n\r", ch );
return;
}
if( !( victim = get_char_room( ch, arg2 ) ) )
{
send_to_char( "They aren't here.\n\r", ch );
return;
}
if( victim == ch )
{
send_to_char( "Instant success, you steal everything!\n\r", ch );
return;
}
if( is_safe( ch, victim ) )
{
send_to_char( "You cannot steal from them.\n\r", ch );
return;
}
obj = NULL;
WAIT_STATE( ch, skill_table[gsn_steal].beats );
/*
* Modified chances for stealing by Morpheus
*/
percent = ch->level - victim->level; /* Base value */
percent += number_range( -10, 10 ); /* Luck */
if( !IS_AWAKE( victim ) )
percent += 25; /* Sleeping characters are easier */
percent += ch->pcdata->learned[gsn_steal]; /* Character ability */
if( IS_AFFECTED( ch, AFF_SNEAK ) )
percent += 5; /* Quiet characters steal better */
if( !can_see( ch, victim ) )
percent += 10; /* Unseen characters steal better */
if( !str_prefix( arg1, "coins" ) || !str_cmp( arg1, "gold" ) )
percent = (int)( percent * 1.2 ); /* Gold is fairly easy to steal */
else
{
number = number_argument( arg1, arg );
count = 0;
for( obj = victim->carrying; obj; obj = obj->next_content )
{
if( can_see_obj( ch, obj )
&& is_obj_name( obj, arg ) )
{
if( ++count == number )
break;
}
}
if( !obj )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( obj->wear_loc == WEAR_NONE )
/* Items in inventory are harder */
percent = ( int )( percent * .8 );
else
percent = ( int )( percent * .3 );
}
if( ( !IS_NPC( victim )
&& ( !xIS_SET( victim->act, PLR_OUTLAW )
|| ch->level - victim->level < 5 ) )
|| percent < number_percent( ) )
{
/*
* Failure.
*/
send_to_char( "Oops.\n\r", ch );
act( "$n tried to steal from you.\n\r", ch, NULL, victim, TO_VICT );
act( "$n tried to steal from $N.\n\r", ch, NULL, victim, TO_NOTVICT );
sprintf( buf, "%s is a bloody thief!", ch->name );
do_shout( victim, buf );
if( IS_NPC( victim ) || is_clan_enemy( ch, victim )
|| is_clan_enemy( victim, ch ) ) /* may not be commutative */
{
multi_hit( victim, ch, TYPE_UNDEFINED );
}
else
{
send_to_char(
"You can't PK! You lose 1000 exps.\n\r", ch );
gain_exp( ch, -100000 );
log_string( buf );
if( !xIS_SET( ch->act, PLR_OUTLAW ) )
{
xSET_BIT( ch->act, PLR_OUTLAW );
send_to_char( "*** You are now an OUTLAW!! ***\n\r", ch );
save_char_obj( ch );
}
}
return;
}
if( !str_prefix( arg1, "coins" )
|| !str_cmp( arg1, "gold" ) )
{
int amount;
amount = victim->gold * number_range( 1, 10 ) / 100;
if( amount <= 0 )
{
send_to_char( "You couldn't get any gold.\n\r", ch );
return;
}
ch->gold += amount;
victim->gold -= amount;
if( IS_NPC( victim ) )
victim->in_room->area->economy -= amount;
charprintf( ch, "Bingo! You got %d gold coins.\n\r", amount );
return;
}
if( !can_drop_obj( ch, obj )
|| IS_SET( obj->extra_flags, ITEM_INVENTORY )
|| obj->level > ch->level + 3 )
{
send_to_char( "You can't pry it away.\n\r", ch );
return;
}
if( ch->carry_number >= can_carry_n( ch ) )
{
send_to_char( "You have your hands full.\n\r", ch );
return;
}
if( ch->carry_weight + get_obj_weight( obj ) > can_carry_w( ch ) )
{
send_to_char( "You can't carry that much weight.\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "Very daring, and you got it!\n\r", ch );
unequip_char( victim, obj );
}
obj_from_char( obj );
obj_to_char( obj, ch );
send_to_char( "Ok.\n\r", ch );
return;
}
/*
* Shopping commands.
*/
CHAR_DATA *find_keeper( CHAR_DATA *ch, char *argument )
{
CHAR_DATA *keeper;
SHOP_DATA *pShop;
char buf[MAX_STRING_LENGTH];
pShop = NULL;
for( keeper = ch->in_room->people; keeper; keeper = keeper->next_in_room )
{
if( IS_NPC( keeper ) && ( pShop = keeper->pIndexData->pShop )
&& ( argument[0] == '\0' || is_char_name( keeper, argument ) ) )
break;
}
if( !keeper || !pShop || IS_AFFECTED( keeper, AFF_CHARM ) )
{
send_to_char( "You can't do that here.\n\r", ch );
return NULL;
}
/*
* Undesirables.
*/
if( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_OUTLAW ) )
{
do_say( keeper, "OUTLAWs are not welcome!" );
sprintf( buf, "%s the OUTLAW is over here!", ch->name );
do_shout( keeper, buf );
return NULL;
}
/*
* Shop hours.
*/
if( pShop->open_hour > pShop->close_hour )
{
if( ch->in_room->area->plane->time.hour < pShop->open_hour
&& ch->in_room->area->plane->time.hour > pShop->close_hour )
{
do_say( keeper, "Sorry, come back later." );
return NULL;
}
}
else
{
if( ch->in_room->area->plane->time.hour < pShop->open_hour )
{
do_say( keeper, "Sorry, come back later." );
return NULL;
}
if( ch->in_room->area->plane->time.hour > pShop->close_hour )
{
do_say( keeper, "Sorry, come back tomorrow." );
return NULL;
}
}
/*
* Invisible or hidden people.
*/
if( !can_see( keeper, ch ) )
{
do_say( keeper, "I don't trade with folks I can't see." );
return NULL;
}
return keeper;
}
CHAR_DATA *find_smith( CHAR_DATA *ch, const char *argument )
{
CHAR_DATA *smith;
SHOP_DATA *pShop;
char buf[MAX_STRING_LENGTH];
pShop = NULL;
for( smith = ch->in_room->people; smith; smith = smith->next_in_room )
{
if( IS_NPC( smith ) && ( pShop = smith->pIndexData->pShop )
&& xIS_SET( smith->act, ACT_SMITH )
&& ( argument[0] == '\0' || is_char_name( smith, argument ) ) )
break;
}
if( !smith || !pShop || IS_AFFECTED( smith, AFF_CHARM ) )
{
send_to_char( "You can't do that here.\n\r", ch );
return NULL;
}
/*
* Undesirables.
*/
if( !IS_NPC( ch ) && xIS_SET( ch->act, PLR_OUTLAW ) )
{
do_say( smith, "OUTLAWs are not welcome!" );
sprintf( buf, "%s the OUTLAW is over here!", ch->name );
do_shout( smith, buf );
return NULL;
}
/*
* Shop hours.
*/
if( pShop->open_hour > pShop->close_hour )
{
if( ch->in_room->area->plane->time.hour < pShop->open_hour
&& ch->in_room->area->plane->time.hour > pShop->close_hour )
{
do_say( smith, "I start work later, see you then." );
return NULL;
}
}
else
{
if( ch->in_room->area->plane->time.hour < pShop->open_hour )
{
do_say( smith, "I start work later, see you then." );
return NULL;
}
if( ch->in_room->area->plane->time.hour > pShop->close_hour )
{
do_say( smith, "It's too late to work, come back tomorrow." );
return NULL;
}
}
/*
* Invisible or hidden people.
*/
if( !can_see( smith, ch ) )
{
do_say( smith, "Who said that?" );
return NULL;
}
return smith;
}
int get_cost( CHAR_DATA *keeper, CHAR_DATA *customer, OBJ_DATA *obj, bool fBuy )
{
SHOP_DATA *pShop;
int cost;
int margin;
if( !obj || ( IS_SET( obj->extra_flags, ITEM_INVENTORY ) && !fBuy )
|| !( pShop = keeper->pIndexData->pShop ) )
return 0;
if( fBuy )
{
margin = pShop->profit_buy - 100;
if( customer && !IS_NPC( customer ) )
{
margin *= UMIN( 100, 100 - get_success( customer, gsn_haggle, 300 ) * 2 / 3 );
margin /= 100;
}
margin += 100;
if( obj->item_type == ITEM_TREASURE )
cost = obj->value[0] * margin / 100;
else
cost = obj->cost * margin / 100;
}
else
{
OBJ_DATA *obj2;
int itype;
/* Questmasters don't buy stuff */
if( xIS_SET( keeper->act, ACT_QUESTMASTER ) )
return -1;
margin = pShop->profit_sell - 100;
if( customer && !IS_NPC( customer ) )
{
margin *= UMIN( 100, 100 - get_success( customer, gsn_haggle, 300 ) * 2 / 3 );
margin /= 100;
}
margin += 100;
cost = 0;
for( itype = 0; itype < MAX_TRADE; itype++ )
{
if( obj->item_type == pShop->buy_type[itype] )
{
if( obj->item_type == ITEM_TREASURE )
cost = obj->value[0] * margin / 100;
else
cost = obj->cost * margin / 100;
break;
}
}
for( obj2 = keeper->carrying; obj2; obj2 = obj2->next_content )
{
if( obj->pIndexData == obj2->pIndexData )
cost /= 2;
}
}
if( obj->item_type == ITEM_STAFF || obj->item_type == ITEM_WAND )
cost = cost * obj->value[2] / obj->value[1];
return cost;
}
/*
* Multiple object buy modifications by Erwin Andreasen
* Obtained from Canth's snippets page at:
* http://www.xs4all.nl/~phule/snippets/snippets.html
*/
void do_buy( CHAR_DATA *ch, const char *argument )
{
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
char arg3[MAX_INPUT_LENGTH];
argument = one_argument( argument, arg );
argument = one_argument( argument, arg2 );
one_argument( argument, arg3 );
if( arg[0] == '\0' )
{
send_to_char( "Buy what?\n\r", ch );
return;
}
if( IS_SET( ch->in_room->room_flags, ROOM_PET_SHOP ) )
{
CHAR_DATA *pet;
ROOM_INDEX_DATA *pRoomIndexNext;
ROOM_INDEX_DATA *in_room;
char buf[MAX_STRING_LENGTH];
if( IS_NPC( ch ) )
return;
pRoomIndexNext = get_room_index( ch->in_room->vnum + 1 );
if( !pRoomIndexNext )
{
bug( "Do_buy: bad pet shop at vnum %d.", ch->in_room->vnum );
send_to_char( "Sorry, you can't buy that here.\n\r", ch );
return;
}
in_room = ch->in_room;
ch->in_room = pRoomIndexNext;
pet = get_char_room( ch, arg );
ch->in_room = in_room;
if( !pet || !xIS_SET( pet->act, ACT_PET ) )
{
send_to_char( "Sorry, you can't buy that here.\n\r", ch );
return;
}
if( xIS_SET( ch->act, PLR_BOUGHT_PET ) )
{
send_to_char( "You already bought one pet this level.\n\r", ch );
return;
}
if( ch->gold < 10 * pet->level * pet->level )
{
send_to_char( "You can't afford it.\n\r", ch );
return;
}
if( ch->level < pet->level )
{
send_to_char( "You're not ready for this pet.\n\r", ch );
return;
}
ch->gold -= 10 * pet->level * pet->level;
ch->in_room->area->economy += 10 * pet->level * pet->level;
pet = create_mobile( pet->pIndexData );
xSET_BIT( ch->act, PLR_BOUGHT_PET );
xSET_BIT( pet->act, ACT_PET );
xSET_BIT( pet->affected_by, AFF_CHARM );
one_argument( argument, arg );
if( arg[0] != '\0' )
{
sprintf( buf, "%s %s", pet->name, arg );
free_string( pet->name );
pet->name = str_dup( buf );
}
sprintf( buf, "%sA neck tag says 'I belong to %s'.\n\r",
pet->description, ch->name );
free_string( pet->description );
pet->description = str_dup( buf );
char_to_room( pet, ch->in_room );
add_follower( pet, ch );
send_to_char( "Enjoy your pet.\n\r", ch );
act( "$n bought $N as a pet.", ch, NULL, pet, TO_ROOM );
return;
}
else
{
OBJ_DATA *obj;
CHAR_DATA *keeper;
int cost;
int item_count = 1; /* buy only one by default */
int *gold;
if( is_number_special( arg ) )
{
item_count = atoi_special( arg );
strcpy( arg, arg2 );
strcpy( arg2, arg3 );
}
if( !( keeper = find_keeper( ch, arg2 ) ) )
return;
if( xIS_SET( keeper->act, ACT_QUESTMASTER ) )
{
if( IS_NPC( ch ) )
return;
gold = &ch->pcdata->quest->score;
}
else
gold = &ch->gold;
obj = get_obj_carry( keeper, arg );
cost = get_cost( keeper, ch, obj, TRUE );
if( cost <= 0 || !can_see_obj( ch, obj ) )
{
act( "&B$n tells you 'I don't sell that -- try 'list''.",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( item_count < 1 )
{
send_to_char( "Buy how many? Number must be more than 0.\n\r",
ch );
return;
}
if( *gold < ( cost * item_count ) )
{
if( item_count == 1 )
{
act( "&B$n tells you 'You can't afford to buy $p'.",
keeper, obj, ch, TO_VICT );
ch->reply = keeper;
return;
}
else
{
char buf[MAX_STRING_LENGTH];
if( ( *gold / cost ) > 0 )
sprintf( buf,
"$n tells you, 'You can only afford %d of those!'",
( *gold / cost ) );
else
sprintf( buf, "$n tells you, 'You can't even afford 1'." );
act( buf, keeper, obj, ch, TO_VICT );
ch->reply = keeper;
return;
}
}
if( obj->level > ch->level + 3 )
{
act( "$n tells you 'You can't use $p yet'.",
keeper, obj, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( ch->carry_number + ( item_count * get_obj_number( obj ) ) >
can_carry_n( ch ) )
{
send_to_char( "You can't carry that many items.\n\r", ch );
return;
}
if( ch->carry_weight + ( item_count * get_obj_weight( obj ) ) >
can_carry_w( ch ) )
{
send_to_char( "You can't carry that much weight.\n\r", ch );
return;
}
if( ( item_count > 1 )
&& !IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
{
act( "$n tells you, 'Sorry - $p is something I have only one of'",
keeper, obj, ch, TO_CHAR );
ch->reply = keeper;
return;
}
{
char buf[MAX_STRING_LENGTH];
if( item_count == 1 )
{
sprintf( buf, "&gYou buy $p for &y%s&g %s.",
int_to_str_special( cost ),
xIS_SET( keeper->act, ACT_QUESTMASTER )
? "quest points" : "gold" );
act( buf, ch, obj, NULL, TO_CHAR );
act( "&g$n buys $p.", ch, obj, NULL, TO_ROOM );
}
else
{
sprintf( buf, "$n buys %d * $p.", item_count );
act( buf, ch, obj, NULL, TO_ROOM );
sprintf( buf, "You buy %d * $p @ %s %s each.", item_count,
int_to_str_special( cost ),
xIS_SET( keeper->act, ACT_QUESTMASTER )
? "quest points" : "gold");
act( buf, ch, obj, NULL, TO_CHAR );
}
}
*gold -= cost * item_count;
if( !xIS_SET( keeper->act, ACT_QUESTMASTER ) )
ch->in_room->area->economy += cost * item_count;
if( IS_SET( obj->extra_flags, ITEM_INVENTORY ) )
for( ; item_count > 0; item_count-- )
{
OBJ_DATA *sell, *content;
sell = create_object( obj->pIndexData, obj->level );
obj_to_char( sell, ch );
for( content = obj->contains; content;
content = content->next_content )
if( !content->deleted )
obj_to_obj( create_object( content->pIndexData, content->level ), sell );
}
else
{
obj_from_char( obj );
obj_to_char( obj, ch );
}
return;
}
}
void do_list( CHAR_DATA *ch, const char *argument )
{
BUFFER *outbuf = buffer_new( MAX_STRING_LENGTH );
if( IS_SET( ch->in_room->room_flags, ROOM_PET_SHOP ) )
{
CHAR_DATA *pet;
ROOM_INDEX_DATA *pRoomIndexNext;
bool found;
pRoomIndexNext = get_room_index( ch->in_room->vnum + 1 );
if( !pRoomIndexNext )
{
bug( "Do_list: bad pet shop at vnum %d.", ch->in_room->vnum );
send_to_char( "You can't do that here.\n\r", ch );
return;
}
found = FALSE;
for( pet = pRoomIndexNext->people; pet; pet = pet->next_in_room )
{
if( IS_NPC( pet ) && xIS_SET( pet->act, ACT_PET ) )
{
if( !found )
{
found = TRUE;
buffer_strcat( outbuf, "&bPets for sale:\n\r" );
}
bprintf( outbuf, "&b[&m%2d&b] &y%8d&b - &c%s&n\n\r",
pet->level,
10 * pet->level * pet->level,
pet->short_descr );
}
}
if( !found )
send_to_char( "Sorry, we're out of pets right now.\n\r", ch );
{
char * p;
p = outbuf->data;
while( ( p = strstr( p, "&x" ) ) )
*(p + 1) = 'c';
}
send_to_char( outbuf->data, ch );
buffer_free( outbuf );
return;
}
else
{
OBJ_DATA *obj;
CHAR_DATA *keeper;
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int cost;
bool found;
argument = one_argument( argument, arg );
one_argument( argument, arg2 );
if( !( keeper = find_keeper( ch, arg2 ) ) )
return;
found = FALSE;
for( obj = keeper->carrying; obj; obj = obj->next_content )
{
if( obj->wear_loc != WEAR_NONE
|| ( cost = get_cost( keeper, NULL, obj, TRUE ) ) < 0 )
continue;
if( can_see_obj( ch, obj )
&& ( arg[0] == '\0'
|| !str_cmp( arg, "all" )
|| is_obj_name( obj, arg ) ) )
{
if( !found )
{
found = TRUE;
buffer_strcat( outbuf, "&b[&mLvl &rPrice&b]&y Item\n\r" );
}
bprintf( outbuf, "&b[&m%3d &r%5s&b]&y %s.&n\n\r",
obj->level, int_to_str_special( cost ),
capitalize( obj->short_descr ) );
}
}
if( !found )
{
if( arg[0] == '\0' )
send_to_char( "You can't buy anything here.\n\r", ch );
else
send_to_char( "You can't buy that here.\n\r", ch );
return;
}
{
char * p;
p = outbuf->data;
while( ( p = strstr( p, "&x" ) ) )
*(p + 1) = 'y';
}
send_to_char( outbuf->data, ch );
buffer_free( outbuf );
return;
}
}
void do_sell( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj, *invobj;
CHAR_DATA *keeper;
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int cost;
argument = one_argument( argument, arg );
one_argument( argument, arg2 );
if( arg[0] == '\0' )
{
send_to_char( "Sell what?\n\r", ch );
return;
}
if( !( keeper = find_keeper( ch, arg2 ) ) )
return;
if( !( obj = get_obj_carry( ch, arg ) ) )
{
act( "&B$n tells you 'You don't have that item'.",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( !can_see_obj( keeper, obj ) )
{
act( "&B$n tells you 'I can't see that item'.",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( ( cost = get_cost( keeper, ch, obj, FALSE ) ) <= 0
|| obj->level > LEVEL_HERO )
{
act( "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT );
return;
}
if( IS_SET( obj->extra_flags, ITEM_POISONED ) )
{
act( "&B$n tells you 'I won't buy that! It's poisoned!'",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( IS_SET( obj->extra_flags, ITEM_OWNER ) )
{
act( "&B$n tells you 'That item would be of no use to me'",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
sprintf( buf, "&gYou sell $p for &y%s&g gold piece%s.",
int_to_str_special( cost ), cost == 1 ? "" : "s" );
act( buf, ch, obj, NULL, TO_CHAR );
act( "&g$n sells $p.", ch, obj, NULL, TO_ROOM );
ch->gold += cost;
ch->in_room->area->economy -= cost;
if( obj->item_type == ITEM_TRASH )
{
extract_obj( obj );
}
else
{
int count = 0;
obj_from_char( obj );
for( invobj = keeper->carrying; invobj; invobj = invobj->next_content )
{
if( invobj->pIndexData == obj->pIndexData )
++count;
}
if( count >= 3 )
extract_obj( obj );
else
obj_to_char( obj, keeper );
}
return;
}
void do_value( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
CHAR_DATA *keeper;
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_LENGTH];
char arg2[MAX_INPUT_LENGTH];
int cost;
argument = one_argument( argument, arg );
one_argument( argument, arg2 );
if( arg[0] == '\0' )
{
send_to_char( "Value what?\n\r", ch );
return;
}
if( !( keeper = find_keeper( ch, arg2 ) ) )
return;
if( !( obj = get_obj_carry( ch, arg ) ) )
{
act( "&B$n tells you 'You don't have that item'.",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( !can_see_obj( keeper, obj ) )
{
act( "&B$n tells you 'You are offering me an imaginary object!?!?'.",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( ( cost = get_cost( keeper, ch, obj, FALSE ) ) <= 0 )
{
act( "$n looks uninterested in $p.", keeper, obj, ch, TO_VICT );
return;
}
if( IS_SET( obj->extra_flags, ITEM_POISONED ) )
{
act( "&B$n tells you 'I won't buy that! It's poisoned!'",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
if( IS_SET( obj->extra_flags, ITEM_OWNER ) )
{
act( "&B$n tells you 'That would be of no use to me'",
keeper, NULL, ch, TO_VICT );
ch->reply = keeper;
return;
}
sprintf( buf, "&B$n tells you 'I'll give you %d gold coins for $p'.", cost );
act( buf, keeper, obj, ch, TO_VICT );
ch->reply = keeper;
return;
}
/*
* Poison weapon by Thelonius for EnvyMud
*/
void do_poison_weapon( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
OBJ_DATA *pobj;
OBJ_DATA *wobj;
char arg[MAX_INPUT_LENGTH];
int timer;
/*
* Don't allow mobs or unskilled pcs to do this
*/
if( IS_NPC( ch ) || ( !IS_NPC( ch )
&& !can_use( ch, gsn_poison_weapon ) ) )
{
send_to_char( "What do you think you are, a thief?\n\r", ch );
return;
}
one_argument( argument, arg );
if( arg[0] == '\0' )
{
send_to_char( "What are you trying to poison?\n\r", ch );
return;
}
if( ch->fighting )
{
send_to_char( "While you're fighting? Nice try.\n\r", ch );
return;
}
if( !( obj = get_obj_carry( ch, arg ) ) )
{
send_to_char( "You do not have that weapon.\n\r", ch );
return;
}
if( obj->item_type != ITEM_WEAPON )
{
send_to_char( "That item is not a weapon.\n\r", ch );
return;
}
if( IS_OBJ_STAT( obj, ITEM_POISONED ) )
{
send_to_char( "That weapon is already poisoned.\n\r", ch );
return;
}
/*
* Now we have a valid weapon...check to see if we have the powder.
*/
for( pobj = ch->carrying; pobj; pobj = pobj->next_content )
{
if( pobj->pIndexData->vnum == OBJ_VNUM_BLACK_POWDER )
break;
}
if( !pobj )
{
send_to_char( "You do not have the black poison powder.\n\r", ch );
return;
}
/*
* Okay, we have the powder...do we have water?
*/
for( wobj = ch->carrying; wobj; wobj = wobj->next_content )
{
if( wobj->item_type == ITEM_DRINK_CON
&& wobj->value[1] > 0
&& wobj->value[2] == 0 )
break;
}
if( !wobj )
{
send_to_char( "You have no water to mix with the powder.\n\r", ch );
return;
}
/*
* Great, we have the ingredients...but is the thief smart enough?
*/
if( !IS_NPC( ch ) && get_curr_wis( ch ) < 19 )
{
send_to_char( "You can't quite remember what to do...\n\r", ch );
return;
}
/*
* And does the thief have steady enough hands?
*/
if( !IS_NPC( ch )
&& ( get_curr_dex( ch ) < 20
|| ch->pcdata->condition[COND_DRUNK] > 0 ) )
{
send_to_char(
"Your hands aren't steady enough to properly mix the poison.\n\r",
ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_poison_weapon].beats );
/*
* Check the skill percentage
*/
if( !IS_NPC( ch )
&& number_percent( ) > ch->pcdata->learned[gsn_poison_weapon] )
{
send_to_char( "You failed and spill some on yourself. Ouch!\n\r",
ch );
damage( ch, ch, ch->level, gsn_poison_weapon, WEAR_NONE );
act( "$n spills the poison all over!", ch, NULL, NULL, TO_ROOM );
extract_obj( pobj );
extract_obj( wobj );
return;
}
/*
* Well, I'm tired of waiting. Are you?
*/
act( "You mix $p in $P, creating a deadly poison!",
ch, pobj, wobj, TO_CHAR );
act( "$n mixes $p in $P, creating a deadly poison!",
ch, pobj, wobj, TO_ROOM );
act( "You pour the poison over $p, which glistens wickedly!",
ch, obj, NULL, TO_CHAR );
act( "$n pours the poison over $p, which glistens wickedly!",
ch, obj, NULL, TO_ROOM );
SET_BIT( obj->extra_flags, ITEM_POISONED );
obj->cost *= ch->level;
/*
* Set an object timer. Don't want proliferation of poisoned weapons
*/
timer = 10 + ch->level;
if( IS_OBJ_STAT( obj, ITEM_BLESS ) )
timer *= 2;
if( IS_OBJ_STAT( obj, ITEM_MAGIC ) )
timer *= 2;
set_timer_tick( obj, timer );
/*
* WHAT? All of that, just for that one bit? How lame. ; )
*/
act( "The remainder of the poison eats through $p.",
ch, wobj, NULL, TO_CHAR );
act( "The remainder of the poison eats through $p.",
ch, wobj, NULL, TO_ROOM );
extract_obj( pobj );
extract_obj( wobj );
return;
}
/*
* Contributed by BoneCrusher of EnvyMud.
*/
void do_donate( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *container;
OBJ_DATA *obj;
OBJ_DATA *obj_next;
if( argument [0] == '\0' )
{
send_to_char( "Donate what?\n\r", ch );
return;
}
if( ( container = get_obj_world( ch, "donation" ) ) == NULL )
{
send_to_char( "The donation pit is missing from the world.\n\r", ch );
return;
}
if( str_cmp( argument, "all" ) && str_prefix( "all.", argument ) )
{
if( ( obj = get_obj_carry( ch, argument ) ) == NULL )
{
send_to_char( "You do not have that item.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( get_obj_weight( obj ) + get_obj_weight( container )
> container->value[0] )
{
send_to_char( "It won't fit.\n\r", ch );
return;
}
if( obj->item_type == ITEM_TRASH
|| obj->item_type == ITEM_FOOD
|| obj->item_type == ITEM_KEY
|| obj->item_type == ITEM_PILL )
{
act( "You send $p flying to the $P.", ch, obj, container,
TO_CHAR );
extract_obj( obj );
return;
}
obj_from_char( obj );
obj_to_obj( obj, container );
act( "$n sends $p flying to the $P.", ch, obj, container, TO_ROOM );
act( "You send $p flying to the $P.", ch, obj, container, TO_CHAR );
send_to_room( "A loud clank is heard from the pit!",
container->in_room );
}
else
{
for( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( ( argument[3] == '\0' || is_obj_name( obj, &argument[4] ) )
&& can_see_obj( ch, obj )
&& obj->wear_loc == WEAR_NONE
&& obj != container
&& can_drop_obj( ch, obj )
&& get_obj_weight( obj ) + get_obj_weight( container )
<= container->value[0] )
{
if( obj->item_type == ITEM_TRASH
|| obj->item_type == ITEM_FOOD
|| obj->item_type == ITEM_KEY
|| obj->item_type == ITEM_PILL )
{
act( "You send $p flying to the $P.", ch, obj, container,
TO_CHAR );
extract_obj( obj );
continue;
}
obj_from_char( obj );
obj_to_obj( obj, container );
act( "$n sends $p flying to the $P.", ch, obj, container,
TO_ROOM );
act( "You send $p flying to the $P.", ch, obj, container,
TO_CHAR );
send_to_room( "A loud clank is heard from the pit!",
container->in_room );
}
}
}
return;
}
void do_carve( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *cor = get_obj_here( ch, argument );
OBJ_DATA *content, *next;
char buf[100];
if( IS_NPC( ch ) || !can_use( ch, gsn_carve ) )
{
send_to_char( "Maybe you should learn how first.", ch );
return;
}
if( !cor || cor->item_type != ITEM_CORPSE_NPC )
{
send_to_char( "You can't carve that.\n\r", ch );
return;
}
if( ( !( content = get_eq_char( ch, WEAR_WIELD_R ) )
|| content->value[3] != 1 )
&& ( !( content = get_eq_char( ch, WEAR_WIELD_DOUBLE ) )
|| content->value[3] != 1 ) )
{
send_to_char( "You need to wield a slicing weapon.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_carve].beats );
for( content = cor->contains; content && content != cor; content = next )
{
next = content->next_content;
obj_from_obj( content );
obj_to_room( content, ch->in_room );
}
if( get_success( ch, gsn_carve, 85 ) )
{
if( number_bits( 2 ) == 0 )
{
act( "$n wildy savages $p, sending chunks flying!",
ch, cor, NULL, TO_ROOM );
send_to_char( "You attack the corpse and "
"large meaty chunks fly about the room!\n\r", ch );
}
else
{
act( "$n carves $p into nice steaks.", ch, cor, NULL, TO_ROOM );
send_to_char( "You carve it up neatly into good meat.\n\r", ch );
}
content = create_object( get_obj_index( OBJ_VNUM_MUSHROOM ), cor->level );
free_string( content->name );
sprintf( buf, "steaks %s", race_table[cor->value[0]].name );
content->name = str_dup( buf );
free_string( content->short_descr );
sprintf( buf, "some %s steaks", race_table[cor->value[0]].name );
content->short_descr = str_dup( capitalize( buf ) );
free_string( content->description );
sprintf( buf, "A pile of %s steaks look very tasty.",
race_table[cor->value[0]].name );
content->description = str_dup( capitalize( buf ) );
obj_to_room( content, ch->in_room );
set_timer_tick( content, dice( 5, 6 ) );
content->value[0] = number_range( cor->level, cor->level * 2 );
}
else
{
act( "$n carves $P into a horrible mess.", ch, cor, NULL, TO_ROOM );
send_to_char( "You try to carve it but mess up.\n\r", ch );
}
free_string( cor->name );
cor->name = str_dup( "mess rotten" );
free_string( cor->short_descr );
cor->short_descr = str_dup( "a rotten mess" );
free_string( cor->description );
cor->description = str_dup( "A mangled heap sits here smelling slightly." );
cor->item_type = ITEM_TRASH;
REMOVE_BIT( cor->wear_flags, ITEM_TAKE );
cor->extra_flags = 0;
set_timer_tick( cor, dice( 5, 6 ) );
return;
}
#define NOT_ALLOWED "destroy cursed remove hex"
void do_engrave( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
AFFECT_DATA *paf, *oaf;
char arg1[MAX_INPUT_LENGTH];
int sn, level, chance, i, cost[MAGIC_MAX + 1];
if( IS_NPC( ch ) || !can_use( ch, gsn_engrave ) )
{
send_to_char( "You lack the skills and initiative.\n\r", ch );
return;
}
argument = one_argument( argument, arg1 );
if( argument[0] == '\0' || arg1[0] == '\0' )
{
send_to_char( "Engrave what item with which spell?\n\r", ch );
return;
}
obj = get_obj_carry( ch, arg1 );
if( !obj || obj->wear_loc != WEAR_NONE )
{
send_to_char( "You aren't carrying that item.\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_RUNED ) ||
( obj->item_type != ITEM_ARMOUR && obj->item_type != ITEM_WEAPON ) )
{
send_to_char( "You can't engrave on that item.\n\r", ch );
return;
}
sn = skill_lookup( argument );
if( sn <= 0 || !can_use( ch, sn )
|| ( skill_table[sn].target != TAR_CHAR_OFFENSIVE
&& skill_table[sn].target != TAR_CHAR_DEFENSIVE
&& skill_table[sn].target != TAR_CHAR_SELF )
|| !str_infix( skill_table[sn].name, NOT_ALLOWED ) )
{
send_to_char( "You can't engrave that spell.\n\r", ch );
return;
}
if( ( skill_table[sn].target == TAR_CHAR_OFFENSIVE
&& obj->item_type != ITEM_WEAPON ) ||
skill_table[sn].spell_fun == spell_null )
{
send_to_char( "Such a thing is not possible.\n\r", ch );
return;
}
/* how many levels has this person had the skill */
level = skill_table[sn].skill_level[ch->class];
for( i = 0; i < NUM_MULTI_CLASS && level > ch->level; ++i )
{
if( ch->pcdata->multi_class[i] >= CLASS_ADEPT
&& skill_table[sn].skill_level[i] < level )
level = skill_table[sn].skill_level[i];
}
level = ch->level - level;
for( i = 0; i < NUM_MULTI_CLASS && level > ch->level; ++i )
{
if( ch->pcdata->multi_class[i] == CLASS_ASPIRING
&& level > ch->sublevel - skill_table[sn].skill_level[i] )
level = ch->sublevel - skill_table[sn].skill_level[i];
}
if( ++level <= 0 )
{
send_to_char( "You have no chance of doing that.\n\r", ch );
return;
}
/* mana cost */
for( i = 0; i < MAGIC_MAX; ++i )
{
cost[i] = 3 * mana_cost( ch, sn, i );
/* chance += cost[i]; */
if( !IS_NPC( ch ) && ch->mana[i] < cost[i] )
{
send_to_char( "You don't have enough mana.\n\r", ch );
return;
}
}
cost[MAGIC_MAX] = 3 * mana_cost( ch, sn, MAGIC_MAX );
if( total_mana( ch->mana ) - total_mana( cost ) < cost[MAGIC_MAX] )
{
send_to_char( "You don't have enough mana.\n\r", ch );
return;
}
for( i = 0; i < MAGIC_MAX; ++i )
ch->mana[i] -= cost[i];
take_generic_mana( ch, cost[MAGIC_MAX] );
/* chance of success */
chance = get_success( ch, gsn_engrave, 250 );
chance += get_success( ch, sn, 250 );
chance += ch->level - obj->level;
chance = UMAX( 1, 195 - number_range( 0, chance ) );
SET_BIT( obj->extra_flags, ITEM_RUNED );
obj->level += UMIN( ch->level - obj->level, 1 );
if( chance < number_fuzzy( level ) || IS_IMMORTAL( ch ) )
{
ch->pcdata->learned[sn] = UMAX( 0, ch->pcdata->learned[sn]
- class_table[ch->class].skill_adept );
if( skill_table[sn].target == TAR_CHAR_OFFENSIVE
|| !str_cmp( skill_table[sn].name, "dispel magic" ) )
{
obj->value[0] = sn;
}
else
{
affect_strip( ch, sn );
( *skill_table[sn].spell_fun )
( sn, ch->level, ch, (void *)ch );
for( paf = ch->affected; paf; paf = paf->next )
{
if( paf->type != sn )
continue;
oaf = alloc_perm( sizeof( *oaf ) );
oaf->type = sn;
oaf->duration = -1;
oaf->location = paf->location;
oaf->modifier = paf->modifier;
vcopy( oaf->bitvector, paf->bitvector );
oaf->next = obj->affected;
obj->affected = oaf;
}
affect_strip( ch, sn );
}
}
act( "$n begins to engrave a spell on $p.", ch, obj, NULL, TO_ROOM );
act( "You begin to engrave a spell on $p.", ch, obj, NULL, TO_CHAR );
WAIT_STATE( ch, skill_table[gsn_engrave].beats );
return;
}
#undef NOT_ALLOWED
void do_modify_armour( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
if( IS_NPC( ch ) || !can_use( ch, gsn_modify_armour ) )
{
send_to_char( "Learn how to do this first.\n\r", ch );
return;
}
if( argument[0] == '\0' || !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "Modify which?\n\r", ch );
return;
}
if( obj->item_type != ITEM_ARMOUR || obj->value[1] == -1 )
{
send_to_char( "You can't modify that.\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "Take it off first please.\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
{
send_to_char( "That item is far to brittle to modify.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[gsn_modify_armour].beats );
if( number_range( 0, get_success( ch, gsn_modify_armour, 250 ) * 2 ) <= 1 )
/* change constants to your discretion */
{
send_to_char( "You try as hard as you can but you stuff up.\n\r", ch );
extract_obj( obj );
return;
}
/* modify, at the moment there is a maximum size
shift of 2 places allthough that can be changed if you like */
if( obj->value[1] < get_size( ch ) - 10 )
{
act( "You work $p larger so it fits you better.",
ch, obj, NULL, TO_CHAR );
act( "$n works $p larger so it fits $m better.",
ch, obj, NULL, TO_ROOM );
obj->value[1] = UMIN( race_table[ch->race].size, obj->value[1] + 20 );
}
else if( obj->value[1] > get_size( ch ) + 10 )
{
act( "You work $p smaller so it fits you better.",
ch, obj, NULL, TO_CHAR );
act( "$n works $p smaller so it fits $m better.",
ch, obj, NULL, TO_ROOM );
obj->value[1] = UMAX( race_table[ch->race].size, obj->value[1] - 20 );
}
else
{
send_to_char( "No modifications were really necessary.\n\r", ch );
obj->value[1] = race_table[ch->race].size;
}
if( number_bits( 4 ) == 0 && !get_success( ch, gsn_modify_armour, 30 )
&& !IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
{
act( "&r$p has become more fragile!", ch, obj, NULL, TO_CHAR );
SET_BIT( obj->extra_flags, ITEM_FRAGILE );
}
if( number_bits( 2 ) == 0 )
mod_item_condition( ch, obj, 1 );
/* armour class is lowered slightly by the modification */
if( ch->pcdata->learned[gsn_modify_armour] < 110 )
{
obj->value[0] *= ( ch->pcdata->learned[gsn_modify_armour] - 10 );
obj->value[0] /= ( obj->level >= ch->level )
? ( 100 + obj->level - ch->level )
: 100;
}
return;
}
void do_lighten( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int chance;
if( IS_NPC( ch ) || !can_use( ch, gsn_lighten ) )
{
send_to_char( "Learn how to do this first.\n\r", ch );
return;
}
if( argument[0] == '\0' || !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "Modify which?\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "Take it off first please.\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
{
send_to_char( "That item is far to brittle to modify.\n\r", ch );
return;
}
act( "$n begin$% work on $p, making it lighter.", ch, obj, NULL, TO_ALL );
WAIT_STATE( ch, skill_table[gsn_lighten].beats );
if( number_range( 0, get_success( ch, gsn_lighten, 250 ) * 4 ) <= 1 )
/* change constants to your discretion */
{
act( "$n remove$% too much material and $p crumbles.",
ch, obj, NULL, TO_ALL );
extract_obj( obj );
return;
}
chance = obj->weight * 2 + ch->pcdata->learned[gsn_lighten];
chance += ch->level - obj->level + obj->condition / 10;
chance = dice( 2, chance ) / 2;
if( number_bits( 3 ) == 0 && chance < 250
&& !IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
{
act( "&r$p has become more fragile!", ch, obj, NULL, TO_CHAR );
SET_BIT( obj->extra_flags, ITEM_FRAGILE );
}
if( chance <= 180 )
{
mod_item_condition( ch, obj, 1 );
if( obj->deleted )
return;
}
if( chance <= 100 || obj->weight <= 1 )
{
send_to_char( "You find it impossible to lighten the item without ruining it further.\n\r", ch );
return;
}
chance = UMIN( chance - 100, 250 );
chance /= 50;
obj->weight *= 10;
for( ; chance > 0; --chance )
obj->weight = obj->weight * 4 / 5;
obj->weight += 4;
obj->weight /= 10;
act( "You work $p so it becomes lighter.", ch, obj, NULL, TO_CHAR );
act( "$n works $p so it becomes lighter.", ch, obj, NULL, TO_ROOM );
return;
}
void do_sharpen( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
OBJ_DATA *stone;
int chance;
if( IS_NPC( ch ) || !can_use( ch, gsn_sharpen_weapon ) )
{
send_to_char( "Learn how to do this first.\n\r", ch );
return;
}
if( argument[0] == '\0' || !( obj = get_obj_carry( ch, argument ) ) )
{
send_to_char( "Sharpen which?\n\r", ch );
return;
}
if( ( !( stone = get_eq_char( ch, WEAR_HOLD_L ) )
|| stone->pIndexData->vnum != OBJ_VNUM_WHETSTONE )
&& ( !( stone = get_eq_char( ch, WEAR_HOLD_R ) )
|| stone->pIndexData->vnum != OBJ_VNUM_WHETSTONE ) )
{
send_to_char( "You must be using a whetstone first.\n\r", ch );
return;
}
if( obj->item_type != ITEM_WEAPON )
{
send_to_char( "You can't sharpen that.\n\r", ch );
return;
}
if( obj->wear_loc != WEAR_NONE )
{
send_to_char( "Take it off first please.\n\r", ch );
return;
}
if( obj->value[1] + 6 + obj->level / 40 >= obj->value[2] )
{
send_to_char( "That no longer needs any more sharpening.\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
{
send_to_char( "That weapon is far too brittle to sharpen.\n\r", ch );
return;
}
act( "$n begins to sharpen $p.", ch, obj, NULL, TO_ROOM );
stone->value[0] += dice( 1, 6 );
if( stone->value[0] > 50 )
{
act( "$P has worn down to a useless sliver.",
ch, NULL, stone, TO_CHAR );
act( "$P has worn down to a useless sliver.",
ch, NULL, stone, TO_ROOM );
extract_obj( stone );
}
WAIT_STATE( ch, skill_table[gsn_sharpen_weapon].beats );
chance = number_range( 0, get_success( ch, gsn_sharpen_weapon, 250 ) );
chance += UMIN( 25, ch->level - obj->level );
if( IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
chance = number_range( 0, chance );
if( chance < 1 )
{
send_to_char( "You fumble and the weapon shatters.\n\r", ch );
act( "$p is destroyed!", ch, obj, NULL, TO_ROOM );
extract_obj( obj );
return;
}
if( number_bits( 4 ) == 0 )
{
mod_item_condition( ch, obj, 1 );
if( obj->deleted )
return;
}
if( number_bits( 5 ) == 0 && chance < 60
&& !IS_SET( obj->extra_flags, ITEM_FRAGILE ) )
{
act( "&r$p has become more fragile!", ch, obj, NULL, TO_CHAR );
SET_BIT( obj->extra_flags, ITEM_FRAGILE );
}
if( chance < 20 )
{
send_to_char( "Nothing much happens.\n\r", ch );
return;
}
SET_BIT( obj->extra_flags, ITEM_SHARP );
if( number_percent( ) == 99 )
{
act( "You give $p a deadly sharp edge!", ch, obj, NULL, TO_CHAR );
act( "$n gives $p a deadly sharp edge!", ch, obj, NULL, TO_ROOM );
obj->value[2] += number_fuzzy( 1 ) + ch->level / 50;
}
else
{
act( "You hone the edge on $p.", ch, obj, NULL, TO_CHAR );
act( "$n hones the edge on $p.", ch, obj, NULL, TO_ROOM );
}
obj->value[1] = UMIN( obj->value[2] - 6 - obj->level / 40,
obj->value[1] + 2 + ch->level / 50
+ ( obj->value[2] - obj->value[1] ) / 10 );
return;
}
void do_call( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj, *in_obj;
if( is_name( "mortician", ch->name ) )
{
obj = get_obj_world( ch, argument );
if( !obj )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( obj->carried_by == ch )
{
send_to_char( "You have it.\n\r", ch );
return;
}
if( obj->in_room )
obj_from_room( obj );
else if( obj->carried_by )
{
if( obj->wear_loc != WEAR_NONE )
remove_obj( obj->carried_by, obj->wear_loc, TRUE );
obj_from_char( obj );
}
else if( obj->in_obj )
{
for( in_obj = obj->in_obj; in_obj; in_obj = in_obj->in_obj )
;
if( in_obj->carried_by != ch )
obj_from_obj( obj );
}
obj_to_room( obj, ch->in_room );
strip_events( &obj->events, evn_imp_grab );
act( "$n utters the words 'Ereh Yesproc'.", ch, obj, NULL, TO_ROOM );
act( "The $p appears on the ground!", ch, obj, NULL, TO_ROOM );
act( "You call for the $p, and it is dumped on the ground at your feet.", ch, obj, NULL, TO_CHAR );
return;
}
if( IS_NPC( ch ) )
return;
if( !( *argument ) )
{
send_to_char( "You have to specify an item.\n\r", ch );
return;
}
if( str_cmp( argument, "all" ) )
{
obj = get_obj_world( ch, argument );
if( !obj )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( !is_owner( ch, obj ) )
{
send_to_char( "You can't call something you don't own.\n\r", ch );
return;
}
if( obj->carried_by == ch )
{
send_to_char( "You have it.\n\r", ch );
return;
}
if( obj->in_room )
obj_from_room( obj );
else if( obj->carried_by )
{
if( obj->wear_loc != WEAR_NONE )
remove_obj( obj->carried_by, obj->wear_loc, TRUE );
obj_from_char( obj );
}
else if( obj->in_obj )
{
for( in_obj = obj->in_obj; in_obj && in_obj->in_obj;
in_obj = in_obj->in_obj )
;
if( in_obj->carried_by != ch )
obj_from_obj( obj );
else
{
send_to_char( "It's in the bag.\n\r", ch );
return;
}
}
obj_to_char( obj, ch );
act( "$n calls and $p appears in $s hands.", ch, obj, NULL, TO_ROOM );
act( "$p materialises in your hands.", ch, obj, NULL, TO_CHAR );
return;
}
/* call all */
for( obj = object_list; obj; obj = obj->next )
{
if( obj->deleted || obj->carried_by == ch )
continue;
if( IS_SET( obj->extra_flags, ITEM_OWNER )
&& is_owner( ch, obj ) )
{
if( obj->in_room )
obj_from_room( obj );
else if( obj->carried_by )
{
if( obj->wear_loc != WEAR_NONE )
remove_obj( obj->carried_by, obj->wear_loc, TRUE );
obj_from_char( obj );
}
else if( obj->in_obj )
{
in_obj = obj->in_obj;
while( in_obj && in_obj->in_obj )
in_obj = in_obj->in_obj;
if( in_obj->carried_by != ch )
obj_from_obj( obj );
else
continue;
}
obj_to_char( obj, ch );
act( "$n calls and $p appears in $s hands.", ch, obj, NULL, TO_ROOM );
act( "$p materialises in your hands.", ch, obj, NULL, TO_CHAR );
}
}
return;
}
void do_bury( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
if( IS_NPC( ch ) || !can_use( ch, gsn_bury_item ) )
{
send_to_char( "You must learn how first.\n\r", ch );
return;
}
if( ch->in_room->sector_type == SECT_AIR
|| ch->in_room->sector_type == SECT_SPACE )
{
send_to_char( "Bury in WHAT? You should smoke less of the weed man!\n\r",
ch );
return;
}
if( ch->in_room->sector_type == SECT_WATER_SWIM
|| ch->in_room->sector_type == SECT_WATER_NOSWIM
|| ch->in_room->sector_type == SECT_UNDERWATER )
{
send_to_char( "You are in water, do you think you can dig at that?\n\r",
ch );
return;
}
obj = get_obj_carry( ch, argument );
if( !obj )
{
send_to_char( "Bury what exactly?\n\r", ch );
return;
}
if( IS_SET( obj->extra_flags, ITEM_BURIED ) )
{
send_to_char( "It seems to be pretty well covered as it is.\n\r", ch );
return;
}
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
if( get_success( ch, gsn_bury_item, 100 ) == 0 )
{
send_to_char( "You failed to cover the item properly.\n\r", ch );
return;
}
SET_BIT( obj->extra_flags, ITEM_BURIED );
if( obj->carried_by )
obj_from_char( obj );
if( obj->in_obj ) /* just in case */
obj_from_obj( obj );
if( !obj->in_room )
{
obj_to_room( obj, ch->in_room );
strip_events( &obj->events, evn_imp_grab );
}
act( "$n buries $p in the dirt.", ch, obj, NULL, TO_ROOM );
send_to_char( "Ok.\n\r", ch );
return;
}
void do_dig( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
CHAR_DATA *mob;
static const char* const dig_messsage[SECT_MAX][2] = {
{ "You start to break some floor boards when you dig.",
"$n starts to break some floor boards as $e starts digging."
},
{ "You lift a few cobble stones and digging into the packed earth beneath.",
"$n is making a mess of the street with $s digging."
},
{ "You make a nice hole while digging up a lot of dirt.",
"$n digs a hole and goes about $s business."
},
{ "You seem to be hitting alot of roots when you dig.",
"$n look like $e is trying to dig up a tree!"
},
{ "You dig up more clay than dirt here.",
"$n seems to be digging up alot of clay."
},
{ "You start to chip away at the rock here.",
"$n bangs away at the side of the mountain."
},
{ "You can't dig in the water!",
NULL
},
{ "You can't dig in the water!",
NULL
},
{ "You can't dig in the water!",
NULL
},
{ "You can't dig up air!",
NULL
},
{ "You start shovelling piles of sand.",
"$n begins to shovel piles of sand."
},
{ "You can't dig through a vacuum!",
NULL
},
{ "You dig a hole slowly as it continually fills with muddy water.",
"$n begins the futile task of digging a hole in the soggy ground.",
}
};
if( IS_NPC( ch ) )
{
send_to_char( "You are unable to do this.\n\r", ch );
return;
}
if( dig_messsage[ch->in_room->sector_type][0] != NULL )
act( dig_messsage[ch->in_room->sector_type][0],
ch, NULL, NULL, TO_CHAR );
if( dig_messsage[ch->in_room->sector_type][1] != NULL )
act( dig_messsage[ch->in_room->sector_type][1],
ch, NULL, NULL, TO_ROOM );
else
return;
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
/*
* Dig for an object.
*/
for( obj = ch->in_room->contents; obj; obj = obj->next_content )
{
if( !obj->deleted && IS_SET( obj->extra_flags, ITEM_BURIED )
&& ch->pcdata->learned[gsn_bury_item] + 50 > number_bits( 8 ) )
break;
}
if( obj )
{
REMOVE_BIT( obj->extra_flags, ITEM_BURIED );
act( "$n dig$% $p up from the ground.", ch, obj, NULL, TO_ALL );
if( IS_SET( obj->wear_flags, ITEM_TAKE ) )
{
obj_from_room( obj );
obj_to_char( obj, ch );
}
return;
}
/*
* Dig for a mob.
*/
for( mob = ch->in_room->people; mob; mob = mob->next_in_room )
{
if( !mob->deleted && IS_NPC( mob )
&& xIS_SET( mob->act, ACT_BURIED ) && number_bits( 3 ) < 6 )
break;
}
if( mob )
{
act( "$n reveal$% $N!", ch, NULL, mob, TO_ALL );
xREMOVE_BIT( mob->act, ACT_BURIED );
if( !xIS_SET( mob->act, ACT_WIMPY ) && !is_safe( mob, ch ) )
{
act( "&r$N is not happy, $E lunges at $n!", ch, NULL, mob, TO_ALL );
multi_hit( mob, ch, TYPE_UNDEFINED );
}
return;
}
if( number_bits( 3 ) == 0 )
{
int race;
MOB_INDEX_DATA *pMob;
char buf[MAX_STRING_LENGTH];
switch( number_bits( 4 ) )
{
case 0: case 1: case 2:
case 3: case 4:
pMob = get_mob_index( MOB_VNUM_SKELETON );
break;
default:
pMob = get_mob_index( MOB_VNUM_ZOMBIE );
break;
case 12: case 13: case 14:
pMob = get_mob_index( MOB_VNUM_MUMMY );
break;
case 15:
pMob = get_mob_index( MOB_VNUM_LICH );
break;
}
pMob->level += (ch->level + ch->in_room->area->min) / 2 - 5;
mob = create_mobile( pMob );
pMob->level += 5 - (ch->level + ch->in_room->area->min) / 2;
mob->gold = 0;
race = number_range( 0, MAX_RACE - 1 );
mob->resil_mod = ( race_table[race].resil - 1000 ) / 2;
sprintf( buf, mob->name, race_table[race].name );
free_string( mob->name );
mob->name = str_dup( buf );
sprintf( buf, mob->short_descr, race_table[race].name );
free_string( mob->short_descr );
mob->short_descr = str_dup( buf );
sprintf( buf, mob->long_descr, race_table[race].name );
free_string( mob->long_descr );
mob->long_descr = str_dup( buf );
char_to_room( mob, ch->in_room );
act( "Oh no, you have disturbed $N's rest!",
ch, NULL, mob, TO_CHAR );
act( "$n rises from the ground and attacks!",
mob, NULL, NULL, TO_ROOM );
multi_hit( mob, ch, TYPE_UNDEFINED );
return;
}
send_to_char( "You dig but come up with nothing.\n\r", ch );
return;
}
void do_prepare( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *seeds;
char buf[MAX_INPUT_LENGTH];
char arg1[MAX_INPUT_LENGTH]; /* spell1 name */
int timer;
argument = one_argument( argument, arg1 );
if( !can_use( ch, gsn_herbalism ) )
{
send_to_char( "You can't do that.\n\r", ch );
return;
}
if( !( *argument ) || !arg1[0] )
{
send_to_char( "Usage: prepare <spell-name> [spell-name]\n\r", ch );
return;
}
seeds = get_eq_char( ch, WEAR_HOLD_L );
if( !seeds || seeds->pIndexData->vnum != OBJ_VNUM_HERBS )
{
if( !( seeds = get_eq_char( ch, WEAR_HOLD_R ) )
|| seeds->pIndexData->vnum != OBJ_VNUM_HERBS )
{
send_to_char( "Sorry you aren't holding any seeds to plant.\n\r",
ch );
return;
}
}
/* get the spells */
seeds->value[1] = skill_lookup( arg1 );
if( argument && *argument )
seeds->value[2] = skill_lookup( argument );
else
seeds->value[2] = -1;
if( seeds->value[1] <= 0 || ( *argument && seeds->value[2] < 0 ) )
{
send_to_char( "You have chosen a spell that doesn't exist.\n\r", ch );
seeds->value[1] = -1;
seeds->value[2] = -1;
return;
}
if( !can_use( ch, seeds->value[1] )
|| !can_use( ch, seeds->value[2] ) )
{
send_to_char( "You cannot prepare a spell that you dont know.\n\r",
ch );
seeds->value[1] = -1;
seeds->value[2] = -1;
return;
}
/* chance of losing a spell from the pill */
if( !get_success( ch, gsn_herbalism, 100 ) )
{
if( argument && *argument )
{
seeds->value[1] = seeds->value[2];
seeds->value[2] = -1;
}
else
seeds->value[1] = -1;
}
if( !get_success( ch, gsn_herbalism, 100 ) )
seeds->value[2] = -1;
/* chance of adding poison to the pill */
if( !get_success( ch, gsn_herbalism, 100 ) )
{
if( seeds->value[1] <= 0 )
seeds->value[1] = gsn_poison;
else if( seeds->value[2] <= 0 )
seeds->value[2] = gsn_poison;
else if( seeds->value[3] <= 0 )
seeds->value[3] = gsn_poison;
}
/* set all other values for the new/changed item */
REMOVE_BIT( seeds->wear_flags, ITEM_TAKE );
seeds->value[0] = number_fuzzy( ( seeds->level + ch->level ) / 2 );
/* seeds->item_type = ITEM_PLANT; */
timer = 200 - get_success( ch, gsn_herbalism, 250 );
if( number_bits( 8 ) > timer && number_bits( 3 ) == 0 )
{
timer = number_range( 10, timer * 2 );
create_obj_event( seeds, evn_plant_die, timer );
}
else
{
timer = number_range( timer * 2, timer * 3 );
create_obj_event( seeds, evn_plant_grow, timer );
}
sprintf( buf, "plant %s", seeds->name );
free_string( seeds->name );
seeds->name = str_dup( buf );
sprintf( buf, "a plant grown from %s", seeds->short_descr );
free_string( seeds->short_descr );
seeds->short_descr = str_dup( buf );
strcpy( buf, "A plant is here, growing rapidly." );
free_string( seeds->description );
seeds->description = str_dup( buf );
if( seeds->carried_by )
obj_from_char( seeds );
else if( seeds->in_room )
obj_from_room( seeds );
obj_to_room( seeds, ch->in_room );
strip_events( &seeds->events, evn_imp_grab );
act( "$n plants some seeds.", ch, NULL, NULL, TO_ROOM );
send_to_char( "You prepare the seeds and plant them.\n\r", ch );
return;
}
void do_harvest( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *tree;
int num, i, skill;
OBJ_DATA *pill;
if( !can_use( ch, gsn_herbalism ) )
{
send_to_char( "You have little knowledge of herbalism.\n\r", ch );
return;
}
if( !( *argument ) )
{
send_to_char( "Usage: harvest <plant>\n\r", ch );
return;
}
tree = get_obj_here( ch, argument );
if( !tree )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( tree->item_type != ITEM_PLANT )
{
send_to_char( "It isn't yet ready for harvest.\n\r", ch );
return;
}
num = UMIN( 25 + number_percent( ), 100 )
+ UMIN( 10, ch->level - tree->level );
skill = get_success( ch, gsn_herbalism, 150 );
num = skill / num;
if( num == 0 )
{
send_to_char( "You totally ruin the harvest and gain nothing.\n\r", ch );
extract_obj( tree );
return;
}
for( i = 0; i < num; ++i )
{
pill = create_object( get_obj_index( OBJ_VNUM_MAGIC_PILL ), ch->level - 5 );
pill->value[0] = tree->value[0];
pill->value[1] = tree->value[1];
pill->value[2] = tree->value[2];
pill->value[3] = tree->value[3];
if( pill->value[0] > 0 )
SET_BIT( pill->extra_flags, ITEM_GLOW );
if( number_percent( ) > skill )
SET_BIT( pill->extra_flags, ITEM_NODROP );
obj_to_char( pill, ch );
}
act( "$n harvests $p for magical pills.", ch, tree, NULL, TO_ROOM );
act( "You harvest $p and gain some pills.", ch, tree, NULL, TO_CHAR );
extract_obj( tree );
return;
}
void do_appraise( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
CHAR_DATA *smith;
char arg[MAX_INPUT_LENGTH];
int cost;
if( argument[0] =='\0' )
{
send_to_char( "Appraise what?\n\r", ch );
return;
}
argument = one_argument( argument, arg );
if( !( smith = find_smith( ch, argument ) ) )
return;
if( !( obj = get_obj_here( ch, arg ) ) )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( obj->condition >= 1000 )
{
send_to_char( "That item is in perfect condition.\n\r", ch );
return;
}
if( IS_OBJ_STAT( obj, ITEM_FRAGILE ) )
{
send_to_char( "That item is far too fragile to repair.\n\r", ch );
return;
}
if( !can_see_obj( smith, obj ) )
{
act( "&B$n tells you 'I can't see that item'.",
smith, NULL, ch, TO_VICT );
ch->reply = smith;
return;
}
if( ( cost = get_cost( smith, ch, obj, TRUE ) ) <= 0 )
{
act( "&B$n tells you 'I don't know how to repair $p'.",
smith, obj, ch, TO_VICT );
return;
}
cost = cost * ( 1000 - obj->condition ) / 1000 + obj->level;
sprintf( arg, "&B$n tells you '$p would cost &y%s&B gold piece%s to smith'.",
int_to_str_special( cost ), cost == 1 ? "" : "s" );
act( arg, smith, obj, ch, TO_VICT );
return;
}
void do_smith( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj, *obj_next;
CHAR_DATA *smith;
char arg[MAX_INPUT_LENGTH];
int cost;
if( argument[0] =='\0' )
{
send_to_char( "Smith what?\n\r", ch );
return;
}
argument = one_argument( argument, arg );
if( !( smith = find_smith( ch, argument ) ) )
return;
if( !str_cmp( arg, "all" ) || !str_prefix( arg, "all." ) )
{
for( obj = ch->carrying; obj; obj = obj_next )
{
obj_next = obj->next_content;
if( obj->deleted || obj->condition >= 1000
|| IS_OBJ_STAT( obj, ITEM_FRAGILE )
|| ( arg[3] == '.' && !is_obj_name( obj, &arg[4] ) )
|| !can_drop_obj( ch, obj )
|| !can_see_obj( smith, obj ) )
continue;
if( ( cost = get_cost( smith, ch, obj, TRUE ) ) <= 0 )
continue;
cost = cost * ( 1000 - obj->condition ) / 1000 + obj->level;
if( cost > ch->gold )
{
act( "&B$n tells you 'You can't afford to repair any more'.",
smith, obj, ch, TO_VICT );
return;
}
sprintf( arg, "&gYou repair $p for &y%s&g gold piece%s.",
int_to_str_special( cost ), cost == 1 ? "" : "s" );
act( arg, ch, obj, NULL, TO_CHAR );
ch->gold -= cost;
ch->in_room->area->economy += cost;
obj->condition = 1000;
if( xIS_SET( obj->pIndexData->progtypes, REPAIR_PROG ) )
oprog_percent_check( ch, obj, smith, REPAIR_PROG );
}
send_to_char( "All your gear is now in top condition.\n\r", ch );
}
else
{
if( !( obj = get_obj_here( ch, arg ) ) )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( obj->condition >= 1000 )
{
send_to_char( "That item is in perfect condition.\n\r", ch );
return;
}
if( IS_OBJ_STAT( obj, ITEM_FRAGILE ) )
{
send_to_char( "That item is far too fragile to repair.\n\r", ch );
return;
}
if( !can_drop_obj( ch, obj ) )
{
send_to_char( "You can't let go of it.\n\r", ch );
return;
}
if( !can_see_obj( smith, obj ) )
{
act( "&B$n tells you 'I can't see that item'.",
smith, NULL, ch, TO_VICT );
ch->reply = smith;
return;
}
if( ( cost = get_cost( smith, ch, obj, TRUE ) ) <= 0 )
{
act( "&B$n tells you 'I don't know how to repair $p'.",
smith, obj, ch, TO_VICT );
return;
}
cost = cost * ( 1000 - obj->condition ) / 1000;
cost += obj->level * UMAX( 100, 1000 - obj->pIndexData->material )
/ 100;
if( cost > ch->gold )
{
act( "&B$n tells you 'You can't afford my fee, sorry'.",
smith, obj, ch, TO_VICT );
return;
}
sprintf( arg, "&gYou repair $p for &y%s&g gold piece%s.",
int_to_str_special( cost ), cost == 1 ? "" : "s" );
act( arg, ch, obj, NULL, TO_CHAR );
ch->gold -= cost;
ch->in_room->area->economy += cost;
obj->condition = 1000;
if( xIS_SET( obj->pIndexData->progtypes, REPAIR_PROG ) )
oprog_percent_check( ch, obj, smith, REPAIR_PROG );
}
return;
}
void do_repair( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj, *mat;
char arg[MAX_INPUT_LENGTH];
if( !can_use( ch, gsn_repair ) )
{
send_to_char( "Learn how first.\n\r", ch );
return;
}
argument = one_argument( argument, arg );
obj = get_obj_here( ch, arg );
mat = get_obj_here( ch, argument );
if( !obj || !mat )
{
send_to_char( "You can't find it.\n\r", ch );
return;
}
if( obj->pIndexData->material != mat->pIndexData->material )
{
send_to_char( "You can't use that to repair with.\n\r", ch );
return;
}
if( IS_OBJ_STAT( obj, ITEM_FRAGILE ) )
{
send_to_char( "That item is far too fragile to repair.\n\r", ch );
return;
}
extract_obj( mat );
if( !get_success( ch, gsn_repair, 100 ) )
{
act( "$n attempts to mend $p.", ch, obj, NULL, TO_ROOM );
send_to_char( "You stuff up.\n\r", ch );
if( get_success( ch, gsn_repair, 80 ) )
return;
act( "$p is destroyed.", ch, obj, NULL, TO_ROOM );
act( "$p is destroyed.", ch, obj, NULL, TO_CHAR );
extract_obj( obj );
return;
}
if( number_bits( 7 ) == 0 )
{
act( "Your attempts at repair also make $p more fragile.",
ch, obj, NULL, TO_CHAR );
SET_BIT( obj->extra_flags, ITEM_FRAGILE );
}
obj->condition = 1000;
act( "$n repairs $p.", ch, obj, NULL, TO_ROOM );
act( "You repair $p.", ch, obj, NULL, TO_CHAR );
WAIT_STATE( ch, skill_table[gsn_repair].beats );
if( xIS_SET( obj->pIndexData->progtypes, REPAIR_PROG ) )
oprog_percent_check( ch, obj, NULL, REPAIR_PROG );
return;
}
void do_forage( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *obj;
int vnum;
WAIT_STATE( ch, 2 * PULSE_VIOLENCE );
if( !IS_SET( ch->in_room->room_flags, ROOM_FORAGE )
|| !get_success( ch, gsn_forage, 75 ) )
{
send_to_char( "You look around, but you see nothing edible.\n\r", ch );
return;
}
vnum = OBJ_VNUM_FORAGE_FIRST + ch->in_room->sector_type;
vnum = URANGE( OBJ_VNUM_FORAGE_FIRST, vnum, OBJ_VNUM_FORAGE_LAST );
obj = create_object( get_obj_index( vnum ), ch->level );
obj->cost = 0;
obj_to_char( obj, ch );
act( "You forage for a while and come up with $P.",
ch, NULL, obj, TO_CHAR );
WAIT_STATE( ch, PULSE_VIOLENCE * 3 );
return;
}
void do_embalm( CHAR_DATA *ch, const char *argument )
{
OBJ_DATA *cor;
OBJ_DATA *bandages;
int sn;
if( IS_NPC( ch ) || !can_use( ch, ( sn = skill_lookup( "embalm" ) ) ) )
{
send_to_char( "Learn how to do this first.\n\r", ch );
return;
}
if( argument[0] == '\0' || !( cor = get_obj_here( ch, argument ) ) )
{
send_to_char( "Embalm which?\n\r", ch );
return;
}
if( cor->item_type != ITEM_CORPSE_NPC
&& cor->item_type != ITEM_CORPSE_PC )
{
send_to_char( "You can only embalm corpses.\n\r", ch );
return;
}
if( cor->weight != 100 )
{
send_to_char( "This corpse cannot be embalmed.\n\r", ch );
return;
}
if( !( bandages = has_key( ch, OBJ_VNUM_BANDAGES ) ) )
{
send_to_char( "You must have some bandages first.\n\r", ch );
return;
}
WAIT_STATE( ch, skill_table[sn].beats );
obj_from_char( bandages );
extract_obj( bandages );
act( "$n embalm$% $p.", ch, cor, NULL, TO_ALL );
if( cor->carried_by ) /* should be carried by "ch" */
{
obj_from_char( cor );
cor->weight -= UMIN( 100, get_success( ch, sn, 100 ) );
obj_to_char( cor, ch );
}
else
cor->weight -= get_success( ch, sn, 100 );
if( get_time_left( cor->events, evn_obj_decay ) >= 0 )
{
if( cor->item_type == ITEM_CORPSE_PC )
strip_events( &cor->events, evn_obj_decay );
else
set_timer_tick( cor, UMIN( 20, ch->level ) + dice( 4, 20 ) );
}
return;
}