/**************************************************************************** * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame | \\._.// * * -----------------------------------------------------------| (0...0) * * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by Derek Snider | ).:.( * * -----------------------------------------------------------| {o o} * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, | / ' ' \ * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh, Nivek, |~'~.VxvxV.~'~* * Tricops and Fireblade | * * ------------------------------------------------------------------------ * * Merc 2.1 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. * * ------------------------------------------------------------------------ * * Object manipulation module * ****************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <string.h> #include <time.h> #include "mud.h" /* * External functions */ bool check_social args( ( CHAR_DATA *ch, char *command, char *argument ) ); void show_list_to_char args( ( OBJ_DATA *list, CHAR_DATA *ch, bool fShort, bool fShowNothing ) ); void write_corpses args( ( CHAR_DATA *ch, char *name, OBJ_DATA *objrem ) ); /* * Local functions. */ void get_obj args( ( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container ) ); OBJ_DATA* recursive_note_find args( ( OBJ_DATA *obj, char* argument) ); /* * how resistant an object is to damage -Thoric */ sh_int get_obj_resistance( OBJ_DATA *obj ) { sh_int resist; resist = number_fuzzy(MAX_ITEM_IMPACT); /* magical items are more resistant */ if ( IS_OBJ_STAT( obj, ITEM_MAGIC ) ) resist += number_fuzzy(15); /* metal objects are definately stronger */ if ( IS_OBJ_STAT( obj, ITEM_METAL ) ) resist += number_fuzzy(10); /* organic objects are most likely weaker */ if ( IS_OBJ_STAT( obj, ITEM_ORGANIC ) ) resist -= number_fuzzy(10); /* blessed objects should have a little bonus */ if ( IS_OBJ_STAT( obj, ITEM_BLESS ) ) resist += number_fuzzy(10); /* lets make store inventory pretty tough */ if ( IS_OBJ_STAT( obj, ITEM_INVENTORY ) ) resist += 20; return URANGE(10, resist, 99); } void get_obj( CHAR_DATA *ch, OBJ_DATA *obj, OBJ_DATA *container ) { int weight; if ( IS_OBJ_STAT(obj, ITEM_NO_TAKE) && (IS_NPC(ch) || !IS_SET(ch->pcdata->permissions, PERMIT_BUILD))) { send_to_char( "You can't take that.\n\r", ch ); return; } if ( IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) && !can_take_proto( ch ) ) { send_to_char( "A godly force prevents you from getting close to it.\n\r", ch ); return; } if ( ch->carry_number + get_obj_number( obj ) > can_carry_n( ch ) ) { act( AT_PLAIN, "$d: you can't carry that many items.", ch, NULL, obj->name, TO_CHAR ); return; } if ( IS_OBJ_STAT(obj, ITEM_COVERING) ) weight = obj->weight; else weight = get_obj_weight( obj ); if ( ch->carry_weight + weight > can_carry_w( ch ) ) { act( AT_PLAIN, "$d: you can't carry that much weight.", ch, NULL, obj->name, TO_CHAR ); return; } if ( obj->item_type == ITEM_VEHICLE) { CHAR_DATA *rch; for (rch = ch->in_room->first_person;rch;rch = rch->next_in_room) { if (rch->in_obj == obj) { send_to_char("Not while somebody is in it!\n\r", ch); return; } } } /* Make it so players can pick up corpses and eat 'em! -- Scion */ if ( obj->item_type == ITEM_CORPSE_NPC ) { dump_container(obj); act(AT_PLAIN, "You shake all the loose items and nasty crunchy bits off the corpse.", ch, NULL, NULL, TO_CHAR); act(AT_PLAIN, "$n shakes all the loose items off the corpse.", ch, NULL, NULL, TO_ROOM); } if ( container ) { if ( container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING) ) { act( AT_ACTION, "You remove $p from $P", ch, obj, container, TO_CHAR ); act( AT_ACTION, "$n removes $p from $P", ch, obj, container, TO_ROOM ); } else { act( AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "You get $p from beneath $P." : "You get $p from $P.", ch, obj, container, TO_CHAR ); act( AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "$n gets $p from beneath $P." : "$n gets $p from $P.", ch, obj, container, TO_ROOM ); } if ( !IS_NPC( ch ) && str_cmp( container->name+7, ch->name ) ) container->value[5]++; obj_from_obj( obj ); } else { act( AT_ACTION, "You get $p.", ch, obj, container, TO_CHAR ); act( AT_ACTION, "$n gets $p.", ch, obj, container, TO_ROOM ); obj_from_room( obj ); } if (IS_OBJ_STAT(obj, ITEM_ARTIFACT)) obj->timer = 0; if ( obj->item_type != ITEM_CONTAINER ) check_for_trap( ch, obj, TRAP_GET ); if ( char_died(ch) ) return; if ( obj->item_type == ITEM_MONEY ) { int gp; gp = obj->value[0]; ch_printf( ch, "There were &C%d mithril, ", (int)gp/1000000 ); gp = gp % 1000000; ch_printf( ch, "&Y%d gold, ", (int)gp/10000 ); gp = gp % 10000; ch_printf( ch, "&W%d silver, ", (int)gp/100 ); gp = gp % 100; ch_printf( ch, "and &O%d copper coins.\n\r", gp); ch->gold += obj->value[0]; extract_obj( obj ); } else { obj = obj_to_char( obj, ch ); } if ( char_died(ch) || obj_extracted(obj) ) return; oprog_get_trigger(ch, obj); return; } void do_get( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; OBJ_DATA *obj; OBJ_DATA *obj_next; OBJ_DATA *container; sh_int number; bool found; argument = one_argument( argument, arg1 ); if ( is_number(arg1) ) { number = atoi(arg1); if ( number < 1 ) { send_to_char( "That was easy...\n\r", ch ); return; } if ( (ch->carry_number + number) > can_carry_n(ch) ) { send_to_char( "You can't carry that many.\n\r", ch ); return; } argument = one_argument( argument, arg1 ); } else number = 0; argument = one_argument( argument, arg2 ); /* munch optional words */ if ( !str_cmp( arg2, "from" ) && argument[0] != '\0' ) argument = one_argument( argument, arg2 ); /* Get type. */ if ( arg1[0] == '\0' ) { send_to_char( "Get what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( arg2[0] == '\0' ) { if ( number <= 1 && str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) ) { /* 'get obj' */ if (ch->in_room->pShop) { send_to_char("You can't get items without buying them when you are in a shop.\n\r", ch); return; } if (ch->in_obj) obj = get_obj_list(ch, arg1, ch->in_obj->first_content); else obj = get_obj_list( ch, arg1, ch->in_room->first_content ); if ( !obj ) { act( AT_PLAIN, "There is no $T you can reach from here.", ch, NULL, arg1, TO_CHAR ); return; } if (IS_NPC(ch) && (obj->item_type == ITEM_CORPSE_NPC || obj->item_type == ITEM_TREASURE)) return; if (obj->item_type == ITEM_FURNITURE && count_users(obj) > 0) { send_to_char("Not when someone's on it!\n\r", ch); return; } if (IS_AFFECTED(ch, AFF_HAS_ARTI) && IS_OBJ_STAT(obj, ITEM_ARTIFACT)) { act(AT_ACTION, "$p evades your grasp.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$p evades $n's grasp.", ch, obj, NULL, TO_ROOM); return; } if (IS_AFFECTED(ch, AFF_ETHEREAL)) { act(AT_ACTION, "Your hand passes through $p.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$n's hand passes through $p.", ch, obj, NULL, TO_ROOM); return; } /* lets not make magic items hovering in nofloor rooms ungettable -keo */ if (IS_AFFECTED(ch, AFF_FLYING) && (!IS_OBJ_STAT(obj, ITEM_HOVER)) ) { if (ch->curr_talent[TAL_MOTION] < 10) { send_to_char("You can't reach anything on the ground from up here.", ch); return; } } /* sticky floor, chance of sticking -keo */ if (!IS_OBJ_STAT(obj, ITEM_NO_TAKE) && IS_SET(ch->in_room->room_flags, ROOM_STICKY) && (!IS_OBJ_STAT(obj, ITEM_HOVER))) { STRFREE(ch->last_taken); ch->last_taken = STRALLOC("trying to pry an item off the sticky floor"); WAIT_STATE(ch, PULSE_VIOLENCE); if (number_range(1,100) > get_curr_str(ch)) { act(AT_ACTION, "$p is stuck to the floor, and you don't manage to pry it loose.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$n tries to lift $p, but it is stuck to the floor.", ch, obj, NULL, TO_ROOM); return; } else { act(AT_ACTION, "$p is stuck to the floor, but you manage to pry it loose.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$n pries $p off the sticky floor.", ch, obj, NULL, TO_ROOM); } } separate_obj(obj); get_obj( ch, obj, obj->in_obj ); if ( char_died(ch) ) return; if ( IS_SET( sysdata.save_flags, SV_GET ) ) save_char_obj( ch ); } else { sh_int cnt = 0; bool fAll; char *chk; if ( IS_SET( ch->in_room->room_flags, ROOM_DONATION ) ) { send_to_char( "The gods frown upon such a display of greed!\n\r", ch ); return; } if (IS_AFFECTED(ch, AFF_FLYING)) { send_to_char("You can't reach anything on the ground from up here.\r\n", ch); return; } if ( !str_cmp(arg1, "all") ) fAll = TRUE; else fAll = FALSE; if ( number > 1 ) chk = arg1; else chk = &arg1[4]; /* 'get all' or 'get all.obj' */ if (ch->in_room->pShop) { send_to_char("You can't get items without buying them when you are in a shop.\n\r", ch); return; } found = FALSE; for ( obj = ch->in_room->last_content; obj; obj = obj_next ) { obj_next = obj->prev_content; if ( ( fAll || nifty_is_name_prefix( chk, obj->name) ) && !IS_OBJ_STAT(obj, ITEM_ARTIFACT) && !IS_AFFECTED(ch, AFF_ETHEREAL) && can_see_obj( ch, obj ) ) { found = TRUE; if ( number && (cnt + obj->count) > number ) split_obj( obj, number - cnt ); cnt += obj->count; get_obj( ch, obj, NULL ); if ( char_died(ch) || ch->carry_number >= can_carry_n( ch ) || ch->carry_weight >= can_carry_w( ch ) || (number && cnt >= number) ) { if ( IS_SET(sysdata.save_flags, SV_GET) && !char_died(ch) ) save_char_obj(ch); return; } } } if ( !found ) { if ( fAll ) send_to_char( "You see nothing here.\n\r", ch ); else act( AT_PLAIN, "You see no $T here.", ch, NULL, chk, TO_CHAR ); } else if ( IS_SET( sysdata.save_flags, SV_GET ) ) save_char_obj( ch ); } } 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 ) ) == NULL ) { act( AT_PLAIN, "You see no $T here.", ch, NULL, arg2, TO_CHAR ); return; } switch ( container->item_type ) { default: if ( !IS_OBJ_STAT( container, ITEM_COVERING ) ) { send_to_char( "That's not a container.\n\r", ch ); return; } if ( ch->carry_weight + container->weight > can_carry_w( ch ) ) { send_to_char( "It's too heavy for you to lift.\n\r", ch ); return; } break; case ITEM_CONTAINER: case ITEM_CORPSE_NPC: case ITEM_KEYRING: case ITEM_QUIVER: case ITEM_FURNITURE: case ITEM_VEHICLE: break; case ITEM_CORPSE_PC: { char name[MAX_INPUT_LENGTH]; CHAR_DATA *gch; char *pd; if ( IS_NPC(ch) ) { send_to_char( "You can't do that.\n\r", ch ); return; } pd = container->short_descr; pd = one_argument( pd, name ); pd = one_argument( pd, name ); pd = one_argument( pd, name ); pd = one_argument( pd, name ); if ( str_cmp( name, ch->name ) ) { bool fGroup; fGroup = FALSE; for ( gch = first_char; gch; gch = gch->next ) { if ( !IS_NPC(gch) && is_same_group( ch, gch ) && !str_cmp( name, gch->name ) ) { fGroup = TRUE; break; } } } } } if ( !IS_OBJ_STAT(container, ITEM_COVERING ) && IS_SET(container->value[1], CONT_CLOSED) && container->item_type != ITEM_CORPSE_NPC && container->item_type != ITEM_CORPSE_PC) { act( AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR ); return; } if ( number <= 1 && str_cmp( arg1, "all" ) && str_prefix( "all.", arg1 ) ) { /* 'get obj container' */ obj = get_obj_list( ch, arg1, container->first_content ); if ( !obj ) { act( AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ? "You see nothing like that beneath the $T." : "You see nothing like that in the $T.", ch, NULL, arg2, TO_CHAR ); return; } if (container->carried_by != ch && (IS_AFFECTED(ch, AFF_FLYING)) ) { if (ch->curr_talent[TAL_MOTION] < 20) { send_to_char("You can't reach anything on the ground from up here.\n\r", ch); return; /* check if they can apport -keo */ } else if (number_percent() > ch->curr_talent[TAL_MOTION]) { act(AT_MAGIC, "$p shakes a little.", ch, obj, NULL, TO_ROOM); act(AT_MAGIC, "You attempt to lift $p but fail.", ch, obj, NULL, TO_CHAR); return; } else { act(AT_MAGIC, "$p suddenly flies up toward $n.", ch, obj, NULL, TO_ROOM); act(AT_MAGIC, "You lift $p and bring it toward you.", ch, obj, NULL, TO_CHAR); learn_talent(ch, TAL_MOTION); mana_from_char(ch, 25); } } if (IS_AFFECTED(ch, AFF_HAS_ARTI) && IS_OBJ_STAT(obj, ITEM_ARTIFACT)) { act(AT_ACTION, "$p evades your grasp.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$p evades $n's grasp.", ch, obj, NULL, TO_ROOM); return; } if (IS_AFFECTED(ch, AFF_ETHEREAL)) { act(AT_ACTION, "Your hand passes through $p.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$n's hand passes through $p.", ch, obj, NULL, TO_ROOM); return; } separate_obj(obj); get_obj( ch, obj, container ); check_for_trap( ch, container, TRAP_GET ); if ( char_died(ch) ) return; if ( IS_SET( sysdata.save_flags, SV_GET ) ) save_char_obj( ch ); } else { int cnt = 0; bool fAll; char *chk; /* 'get all container' or 'get all.obj container' */ if (IS_AFFECTED(ch, AFF_FLYING) && !IS_OBJ_STAT( container, ITEM_MAGIC) ) { send_to_char("You can't reach items on the ground from up here.\n\r", ch); return; } if (container->item_type == ITEM_CORPSE_PC && !nifty_is_name(ch->name, container->name) ) { send_to_char("Your adrenaline is pumping too hard to do that!\n\r", ch); return; } if ( !str_cmp(arg1, "all") ) fAll = TRUE; else fAll = FALSE; if ( number > 1 ) chk = arg1; else chk = &arg1[4]; found = FALSE; for ( obj = container->first_content; obj; obj = obj_next ) { obj_next = obj->next_content; if ( ( fAll || nifty_is_name_prefix( chk, obj->name ) ) && !IS_OBJ_STAT(obj, ITEM_ARTIFACT) && !IS_AFFECTED(ch, AFF_ETHEREAL) && can_see_obj( ch, obj ) ) { found = TRUE; if ( number && (cnt + obj->count) > number ) split_obj( obj, number - cnt ); cnt += obj->count; get_obj( ch, obj, container ); if ( char_died(ch) || ch->carry_number >= can_carry_n( ch ) || ch->carry_weight >= can_carry_w( ch ) || (number && cnt >= number) ) return; } } if ( !found ) { if ( fAll ) { if ( container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING) ) act( AT_PLAIN, "The $T holds no keys.", ch, NULL, arg2, TO_CHAR ); else act( AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ? "You see nothing beneath the $T." : "You see nothing in the $T.", ch, NULL, arg2, TO_CHAR ); } else { if ( container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING) ) act( AT_PLAIN, "The $T does not hold that key.", ch, NULL, arg2, TO_CHAR ); else act( AT_PLAIN, IS_OBJ_STAT(container, ITEM_COVERING) ? "You see nothing like that beneath the $T." : "You see nothing like that in the $T.", ch, NULL, arg2, TO_CHAR ); } } else check_for_trap( ch, container, TRAP_GET ); if ( char_died(ch) ) return; /* Oops no wonder corpses were duping oopsie did I do that * --Shaddai */ if ( container->item_type == ITEM_CORPSE_PC ) write_corpses( NULL, container->short_descr+14, NULL ); if ( found && IS_SET( sysdata.save_flags, SV_GET ) ) save_char_obj( ch ); } } return; } void do_put( CHAR_DATA *ch, char *argument ) { char arg1[MAX_INPUT_LENGTH]; char arg2[MAX_INPUT_LENGTH]; OBJ_DATA *container; OBJ_DATA *obj; OBJ_DATA *obj_next; sh_int count; int number; bool save_char = FALSE; argument = one_argument( argument, arg1 ); if ( is_number(arg1) ) { number = atoi(arg1); if ( number < 1 ) { send_to_char( "That was easy...\n\r", ch ); return; } argument = one_argument( argument, arg1 ); } else number = 0; argument = one_argument( argument, arg2 ); /* munch optional words */ if ( (!str_cmp(arg2, "into") || !str_cmp(arg2, "inside") || !str_cmp(arg2, "in") || !str_cmp(arg2, "under") || !str_cmp(arg2, "onto") || !str_cmp(arg2, "on")) && argument[0] != '\0' ) argument = one_argument( argument, arg2 ); if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Put what in what?\n\r", ch ); return; } if ( ms_find_obj(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)) == NULL ) { act( AT_PLAIN, "You see no $T here.", ch, NULL, arg2, TO_CHAR ); return; } if ( !container->carried_by && IS_SET(sysdata.save_flags, SV_PUT) ) save_char = TRUE; if ( IS_OBJ_STAT(container, ITEM_COVERING) ) { if ( ch->carry_weight + container->weight > can_carry_w(ch) ) { send_to_char( "It's too heavy for you to lift.\n\r", ch ); return; } } else { /* lets burn flammables -keo */ if ( container->item_type == ITEM_FIRE ) { if ( (obj=get_obj_carry(ch, arg1)) == NULL ) { send_to_char( "You do not have that item.\n\r", ch ); return; } if (!IS_OBJ_STAT(obj, ITEM_FLAMMABLE) || IS_OBJ_STAT(obj, ITEM_ARTIFACT)) { act(AT_FIRE, "$p won't catch fire.", ch,obj, NULL,TO_CHAR); return; } act(AT_FIRE, "You put $p on $P, and it catches fire and burns.", ch, obj, container, TO_CHAR); act(AT_FIRE, "$n puts $p on $P, and it catches fire and burns.", ch, obj, container, TO_ROOM); if (container->timer > 0) container->timer += obj->weight*3; obj_from_char(obj); extract_obj(obj); return; } if ( container->item_type != ITEM_CONTAINER && container->item_type != ITEM_FURNITURE && container->item_type != ITEM_KEYRING && container->item_type != ITEM_VEHICLE && container->item_type != ITEM_QUIVER ) { send_to_char( "That's not a container.\n\r", ch ); return; } if ( IS_SET(container->value[1], CONT_CLOSED) && container->item_type != ITEM_CORPSE_NPC && container->item_type != ITEM_CORPSE_PC) { act( AT_PLAIN, "The $d is closed.", ch, NULL, container->name, TO_CHAR ); return; } } if ( number <= 1 && str_cmp(arg1, "all") && str_prefix("all.", arg1) ) { /* 'put obj container' */ if ( (obj=get_obj_carry(ch, arg1)) == NULL ) { 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 (IS_OBJ_STAT(obj, ITEM_ARTIFACT)) { act(AT_ACTION, "$p squirms refusing to let you put it in the container.", ch, obj, NULL, TO_CHAR); act(AT_ACTION, "$p squirms as $n tries to put it in a container.", ch, obj, NULL, TO_ROOM); return; } if ( container->item_type == ITEM_KEYRING && obj->item_type != ITEM_KEY ) { send_to_char( "That's not a key.\n\r", ch ); return; } if ( container->item_type == ITEM_QUIVER && obj->item_type != ITEM_PROJECTILE ) { send_to_char( "That's not a projectile.\n\r", ch ); return; } if ( (IS_OBJ_STAT(container, ITEM_COVERING) && (get_obj_weight(obj) * obj->count) > ((get_real_obj_weight(container) * container->count))) ) { send_to_char( "It won't fit under there.\n\r", ch ); return; } /* note use of get_real_obj_weight */ else if ( (get_real_obj_weight(obj) * obj->count) > ((container->item_type==ITEM_CONTAINER ? container->value[0] - get_real_obj_weight(container) : get_real_obj_weight(container)) * container->count)) { send_to_char( "It won't fit.\n\r", ch ); return; } separate_obj(obj); separate_obj(container); obj_from_char( obj ); /* basketball? -keo */ if (container->carried_by != ch && (IS_AFFECTED(ch, AFF_FLYING)) ) { act(AT_PLAIN, "You throw the $t at the $T.", ch, myobj(obj), myobj(container), TO_CHAR); act(AT_PLAIN, "$n throws $p at the $T.", ch, obj, myobj(container), TO_ROOM); if ( (number_range(0,5)*100) < container->value[0] ) { act(AT_PLAIN, "Score! The $t lands in the $T.", ch, myobj(obj), myobj(container), TO_CHAR); act(AT_PLAIN, "$n scores! The $t lands in the $T.", ch, myobj(obj), myobj(container), TO_ROOM); obj = obj_to_obj( obj, container ); return; } else { act(AT_PLAIN, "You missed! The $t lands on the ground.", ch, myobj(obj), NULL, TO_CHAR); act(AT_PLAIN, "$n misses! The $t lands on the ground.", ch, myobj(obj), NULL, TO_ROOM); obj_to_room(obj, ch->in_room); separate_obj(obj); damage_obj(obj); return; } } obj = obj_to_obj( obj, container ); count = obj->count; obj->count = 1; if ( container->item_type == ITEM_KEYRING && !IS_OBJ_STAT(container, ITEM_COVERING) ) { act( AT_ACTION, "$n slips $p onto $P.", ch, obj, container, TO_ROOM ); act( AT_ACTION, "You slip $p onto $P.", ch, obj, container, TO_CHAR ); } else { act( AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "$n hides $p beneath $P." : "$n puts $p in $P.", ch, obj, container, TO_ROOM ); act( AT_ACTION, IS_OBJ_STAT(container, ITEM_COVERING) ? "You hide $p beneath $P." : "You put $p in $P.", ch, obj, container, TO_CHAR ); } obj->count = count; if ( save_char ) save_char_obj(ch); } else { bool found = FALSE; int cnt = 0; bool fAll; char *chk; if ( !str_cmp(arg1, "all") ) fAll = TRUE; else fAll = FALSE; if ( number > 1 ) chk = arg1; else chk = &arg1[4]; if (container->carried_by != ch && (IS_AFFECTED(ch, AFF_FLYING)) ) { send_to_char("From up here? Do it one at a time!", ch); return; } separate_obj(container); /* 'put all container' or 'put all.obj container' */ for ( obj = ch->first_carrying; obj; obj = obj_next ) { obj_next = obj->next_content; if ( ( fAll || nifty_is_name_prefix( chk, obj->name ) ) && can_see_obj( ch, obj ) && obj->wear_loc == WEAR_NONE && obj != ch->main_hand && obj != ch->off_hand && obj != container && !IS_OBJ_STAT(obj, ITEM_ARTIFACT) && can_drop_obj( ch, obj ) && (container->item_type != ITEM_KEYRING || obj->item_type == ITEM_KEY) && (container->item_type != ITEM_QUIVER || obj->item_type == ITEM_PROJECTILE) && get_obj_weight( obj ) + get_real_obj_weight( container ) <= container->value[0] ) { if ( number && (cnt + obj->count) > number ) split_obj(obj, number - cnt); cnt += obj->count; obj_from_char(obj); if ( container->item_type == ITEM_KEYRING ) { act( AT_ACTION, "$n slips $p onto $P.", ch, obj, container, TO_ROOM ); act( AT_ACTION, "You slip $p onto $P.", ch, obj, container, TO_CHAR ); } else { act( AT_ACTION, "$n puts $p in $P.", ch, obj, container, TO_ROOM ); act( AT_ACTION, "You put $p in $P.", ch, obj, container, TO_CHAR ); } obj = obj_to_obj( obj, container ); found = TRUE; if ( number && cnt >= number ) break; } } /* * Don't bother to save anything if nothing was dropped -Thoric */ if ( !found ) { if ( fAll ) act( AT_PLAIN, "You are not carrying anything that would fit.", ch, NULL, NULL, TO_CHAR ); else act( AT_PLAIN, "You are not carrying any $T.", ch, NULL, chk, TO_CHAR ); return; } if ( save_char ) save_char_obj(ch); } return; } void do_drop( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj; OBJ_DATA *obj_next; bool found; int number; if (ch->in_room->pShop) { send_to_char("You can't drop items without selling them when you are in a shop.\n\r", ch); return; } argument = one_argument( argument, arg ); if ( is_number(arg) ) { number = atoi(arg); if ( number < 1 ) { send_to_char( "That was easy...\n\r", ch ); return; } argument = one_argument( argument, arg ); } else number = 0; if ( arg[0] == '\0' ) { send_to_char( "Drop what?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( xIS_SET( ch->act, PLR_LITTERBUG ) ) { set_char_color( AT_YELLOW, ch ); send_to_char( "A godly force prevents you from dropping anything...\n\r", ch ); return; } if ( IS_SET( ch->in_room->room_flags, ROOM_NODROP ) && ch != supermob ) { set_char_color( AT_MAGIC, ch ); send_to_char( "A magical force stops you!\n\r", ch ); set_char_color( AT_TELL, ch ); send_to_char( "Someone tells you, 'No littering here!'\n\r", ch ); return; } if ( number > 0 ) { /* 'drop NNNN coins' */ if (!str_cmp(arg, "mithril") || !str_cmp(arg, "gold") || !str_cmp(arg, "silver") || !str_cmp(arg, "copper") || !str_cmp(arg, "coins")) { if (!str_cmp(arg, "mithril")) number *= 1000000; else if (!str_cmp(arg, "gold")) number *= 10000; else if (!str_cmp(arg, "silver")) number *= 100; if (number < 0) { send_to_char("And just how do you propose to do that?\n\r", ch); return; } if ( ch->gold < number ) { send_to_char( "You haven't got that many coins.\n\r", ch ); return; } ch->gold -= number; for ( obj = ch->in_room->first_content; obj; obj = obj_next ) { obj_next = obj->next_content; switch ( obj->pIndexData->vnum ) { case OBJ_VNUM_MONEY_ONE: number += 1; extract_obj( obj ); break; case OBJ_VNUM_MONEY_SOME: number += obj->value[0]; extract_obj( obj ); break; } } act( AT_ACTION, "$n drops some coins.", ch, NULL, NULL, TO_ROOM ); if (ch->in_obj) obj_to_obj( create_money( number ), ch->in_obj); else obj_to_room( create_money( number ), ch->in_room ); send_to_char( "You drop some coins.\n\r", ch ); if ( IS_SET( sysdata.save_flags, SV_DROP ) ) save_char_obj( ch ); return; } } if ( number <= 1 && str_cmp( arg, "all" ) && str_prefix( "all.", arg ) ) { /* 'drop obj' */ if ( ( obj = get_obj_carry( ch, arg ) ) == 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; } separate_obj( obj ); act( AT_ACTION, "$n drops $p.", ch, obj, NULL, TO_ROOM ); act( AT_ACTION, "You drop the $t.", ch, myobj(obj), NULL, TO_CHAR); obj_from_char( obj ); if (ch->in_obj) obj = obj_to_obj( obj, ch->in_obj ); else obj = obj_to_room( obj, ch->in_room ); oprog_drop_trigger ( ch, obj ); /* mudprogs */ if (IS_OBJ_STAT(obj, ITEM_ARTIFACT) ) obj->timer = 30; if (IS_OBJ_STAT(obj, ITEM_DREAMWORLD) ) { act( AT_ACTION, "The $t ripples and vanishes.", ch, myobj(obj), NULL, TO_CHAR); act( AT_ACTION, "$p ripples and vanishes.", ch, obj, NULL, TO_ROOM); extract_obj(obj); } if( char_died(ch) || obj_extracted(obj) ) return; } else { int cnt = 0; char *chk; bool fAll; if ( !str_cmp(arg, "all") ) fAll = TRUE; else fAll = FALSE; if ( number > 1 ) chk = arg; else chk = &arg[4]; /* 'drop all' or 'drop all.obj' */ if ( IS_SET( ch->in_room->room_flags, ROOM_NODROPALL ) ) { send_to_char( "You can't seem to do that here...\n\r", ch ); return; } found = FALSE; for ( obj = ch->first_carrying; obj; obj = obj_next ) { obj_next = obj->next_content; if ( (fAll || nifty_is_name_prefix( chk, obj->name ) ) && can_see_obj( ch, obj ) && obj->wear_loc == WEAR_NONE && can_drop_obj( ch, obj ) ) { found = TRUE; if ( HAS_PROG(obj->pIndexData, DROP_PROG) && obj->count > 1 ) { ++cnt; separate_obj( obj ); obj_from_char( obj ); if ( !obj_next ) obj_next = ch->first_carrying; } else { if ( number && (cnt + obj->count) > number ) split_obj( obj, number - cnt ); cnt += obj->count; obj_from_char( obj ); } act( AT_ACTION, "$n drops $p.", ch, obj, NULL, TO_ROOM ); act( AT_ACTION, "You drop the $t.", ch, myobj(obj), NULL, TO_CHAR ); if (ch->in_obj) obj = obj_to_obj( obj, ch->in_obj ); else obj = obj_to_room( obj, ch->in_room ); if (IS_OBJ_STAT(obj, ITEM_ARTIFACT) ) obj->timer = 30; if (IS_OBJ_STAT(obj, ITEM_DREAMWORLD) ) { act( AT_ACTION, "The $t ripples and vanishes.", ch, myobj(obj), NULL, TO_CHAR); act( AT_ACTION, "$p ripples and vanishes.", ch, obj, NULL, TO_ROOM); extract_obj(obj); } oprog_drop_trigger( ch, obj ); /* mudprogs */ if ( char_died(ch) ) return; if ( number && cnt >= number ) break; } } if ( !found ) { if ( fAll ) act( AT_PLAIN, "You are not carrying anything.", ch, NULL, NULL, TO_CHAR ); else act( AT_PLAIN, "You are not carrying any $T.", ch, NULL, chk, TO_CHAR ); } } if ( IS_SET( sysdata.save_flags, SV_DROP ) ) save_char_obj( ch ); /* duping protector */ return; } void do_give( CHAR_DATA *ch, char *argument ) { char arg1 [MAX_INPUT_LENGTH]; char arg2 [MAX_INPUT_LENGTH]; char buf [MAX_INPUT_LENGTH]; CHAR_DATA *victim; OBJ_DATA *obj; argument = one_argument( argument, arg1 ); argument = one_argument( argument, arg2 ); if ( !str_cmp( arg2, "to" ) && argument[0] != '\0' ) argument = one_argument( argument, arg2 ); if ( arg1[0] == '\0' || arg2[0] == '\0' ) { send_to_char( "Give what to whom?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; if ( is_number( arg1 ) ) { /* 'give NNNN coins victim' */ int amount; int gp; char buf2[MAX_STRING_LENGTH]; amount = atoi(arg1); if ( amount <= 0 ) { send_to_char( "Well, that was easy!\n\r", ch ); return; } if (!str_cmp(arg2, "mithril")) amount *= 1000000; else if (!str_cmp(arg2, "gold")) amount *= 10000; else if (!str_cmp(arg2, "silver")) amount *= 100; else if (!str_cmp(arg2, "copper") || !str_cmp(arg2, "coins")) amount *= 1; else { send_to_char("You can't do that.\n\r", ch); return; } argument = one_argument( argument, arg2 ); if ( !str_cmp( arg2, "to" ) && argument[0] != '\0' ) argument = 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 ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if (amount < 0) { send_to_char("And just how do you propose to do that?\n\r", ch); return; } if ( ch->gold < amount ) { send_to_char( "Very generous of you, but you haven't got that many coins.\n\r", ch ); return; } if (!IS_SAME_PLANE(ch, victim)) { send_to_char("Your hands pass right through them!", ch); return; } ch->gold -= amount; victim->gold += amount; strcpy(buf, "$n gives you "); gp = amount; sprintf( buf2, "&C%d mithril, ", (int)gp/1000000 ); strcat(buf, buf2); gp = gp % 1000000; sprintf( buf2, "&Y%d gold, ", (int)gp/10000 ); strcat(buf, buf2); gp = gp % 10000; sprintf( buf2, "&W%d silver, ", (int)gp/100 ); strcat(buf, buf2); gp = gp % 100; sprintf( buf2, "and &O%d copper coins.\n\r", gp); strcat(buf, buf2); act( AT_ACTION, buf, ch, NULL, victim, TO_VICT ); act( AT_ACTION, "$n gives $N some coins.", ch, NULL, victim, TO_NOTVICT ); act( AT_ACTION, "You give $N some coins.", ch, NULL, victim, TO_CHAR ); send_to_char( "OK.\n\r", ch ); mprog_bribe_trigger( victim, ch, amount ); if ( IS_SET( sysdata.save_flags, SV_GIVE ) && !char_died(ch) ) save_char_obj(ch); if ( IS_SET( sysdata.save_flags, SV_RECEIVE ) && !char_died(victim) ) save_char_obj(victim); return; } if ( ( obj = get_obj_carry( ch, arg1 ) ) == NULL ) { 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 ) ) == NULL ) { send_to_char( "They aren't here.\n\r", ch ); return; } if (!IS_SAME_PLANE(ch, victim)) { send_to_char("Your hands pass right through them!", ch); return; } if (IS_AFFECTED(victim, AFF_HAS_ARTI) && IS_OBJ_STAT(obj, ITEM_ARTIFACT)) { act(AT_ACTION, "$p evades $n's grasp.", victim, obj, NULL, TO_ROOM); act(AT_ACTION, "$n tries to give you $p but it evades your grasp.", ch, obj, victim, TO_VICT); return; } if (IS_AFFECTED(ch, AFF_ETHEREAL)) { act(AT_ACTION, "$n tries to give you $p but your hand passes through it.", victim, obj, ch, TO_VICT); act(AT_ACTION, "$n's hand passes through $p.", victim, obj, NULL, TO_ROOM); return; } if ( victim->carry_number + (get_obj_number(obj)/obj->count) > can_carry_n( victim ) ) { act( AT_PLAIN, "$N has $S hands full.", ch, NULL, victim, TO_CHAR ); return; } if ( victim->carry_weight + (get_obj_weight(obj)/obj->count) > can_carry_w( victim ) ) { act( AT_PLAIN, "$N can't carry that much weight.", ch, NULL, victim, TO_CHAR ); return; } if ( !can_see_obj( victim, obj ) ) { act( AT_PLAIN, "$N can't see it.", ch, NULL, victim, TO_CHAR ); return; } if (IS_OBJ_STAT( obj, ITEM_PROTOTYPE ) && !can_take_proto( victim ) ) { act( AT_PLAIN, "You cannot give that to $N!", ch, NULL, victim, TO_CHAR ); return; } separate_obj(obj); obj_from_char(obj); act(AT_ACTION, "$n gives $p to $N.", ch, obj, victim, TO_NOTVICT); act(AT_ACTION, "$n gives you $p.", ch, obj, victim, TO_VICT ); act(AT_ACTION, "You give $p to $N.", ch, obj, victim, TO_CHAR ); obj = obj_to_char(obj, victim); mprog_give_trigger(victim, ch, obj); if ( IS_SET(sysdata.save_flags, SV_GIVE) && !char_died(ch) ) save_char_obj(ch); if ( IS_SET(sysdata.save_flags, SV_RECEIVE) && !char_died(victim) ) save_char_obj(victim); return; } /* * Damage an object. -Thoric * Affect player's AC if necessary. * Make object into scraps if necessary. * Send message about damaged object. */ obj_ret damage_obj( OBJ_DATA *obj ) { CHAR_DATA *ch; obj_ret objcode; int chance = 50; ch = obj->carried_by; objcode = rNONE; separate_obj( obj ); if (ch && !IS_NPC(ch) && !IS_SET(ch->pcdata->flags, PCFLAG_GAG)) act( AT_OBJECT, "($p gets damaged)", ch, obj, NULL, TO_CHAR ); else if ( obj->in_room && ( ch = obj->in_room->first_person ) != NULL ) { act( AT_OBJECT, "($p gets damaged)", ch, obj, NULL, TO_ROOM ); act( AT_OBJECT, "($p gets damaged)", ch, obj, NULL, TO_CHAR ); ch = NULL; } if (IS_OBJ_STAT(obj, ITEM_METAL)) chance += 20; if (IS_OBJ_STAT(obj, ITEM_ORGANIC)) chance -= 20; if (IS_OBJ_STAT(obj, ITEM_BLESS)) chance += 20; if (number_range(0, 100) >= chance) return rNONE; obj->condition -= number_range(1, 10); if (obj->condition <= 0) { make_scraps(obj); return rOBJ_SCRAPPED; } return objcode; } /* * See if char could be capable of dual-wielding -Thoric */ bool could_dual( CHAR_DATA *ch ) { return TRUE; } /* * See if char can dual wield at this time -Thoric */ bool can_dual( CHAR_DATA *ch ) { OBJ_DATA *obj; if ( !could_dual(ch) ) return FALSE; if ((obj = get_eq_char( ch, WEAR_HAND)) && get_eq_char( ch, WEAR_HAND2) ) { send_to_char( "You are already holding two items!\n\r", ch ); return FALSE; } if ( xIS_SET(obj->extra_flags, ITEM_TWO_HANDED)) { send_to_char("You cannot dual wield with a two-handed weapon!\n\r", ch); return FALSE; } if ( get_eq_char( ch, WEAR_SHIELD ) ) { send_to_char( "You cannot dual wield while holding a shield!\n\r", ch ); return FALSE; } return TRUE; } /* * Check to see if there is room to wear another object on this location * (Layered clothing support) */ bool can_layer( CHAR_DATA *ch, OBJ_DATA *obj, sh_int wear_loc ) { OBJ_DATA *otmp; sh_int bitlayers = 0; sh_int objlayers = obj->pIndexData->layers; for ( otmp = ch->first_carrying; otmp; otmp = otmp->next_content ) if ( otmp->wear_loc == wear_loc ) { if ( !otmp->pIndexData->layers ) return FALSE; else bitlayers |= otmp->pIndexData->layers; } if ( (bitlayers && !objlayers) || bitlayers > objlayers ) return FALSE; if ( !bitlayers || ((bitlayers & ~objlayers) == bitlayers) ) return TRUE; return FALSE; } void do_bury( CHAR_DATA *ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; OBJ_DATA *obj; bool shovel; sh_int move; one_argument( argument, arg ); if ( arg[0] == '\0' ) { send_to_char( "What do you wish to bury?\n\r", ch ); return; } if ( ms_find_obj(ch) ) return; shovel = FALSE; for ( obj = ch->first_carrying; obj; obj = obj->next_content ) if ( obj->item_type == ITEM_SHOVEL ) { shovel = TRUE; break; } obj = get_obj_list_rev( ch, arg, ch->in_room->last_content ); if ( !obj ) { send_to_char( "You can't find it.\n\r", ch ); return; } separate_obj(obj); switch( ch->in_room->sector_type ) { case SECT_CITY: case SECT_INSIDE: send_to_char( "The floor is too hard to dig through.\n\r", ch ); return; case SECT_WATER_SWIM: case SECT_WATER_NOSWIM: case SECT_UNDERWATER: send_to_char( "You cannot bury something here.\n\r", ch ); return; case SECT_AIR: send_to_char( "What? In the air?!\n\r", ch ); return; } if ( obj->weight > (UMAX(5, (can_carry_w(ch) / 10))) && !shovel ) { send_to_char( "You'd need a shovel to bury something that big.\n\r", ch ); return; } move = (obj->weight * 50 * (shovel ? 1 : 5)) / UMAX(1, can_carry_w(ch)); move = URANGE( 2, move, 1000 ); if ( move > ch->move ) { send_to_char( "You don't have the energy to bury something of that size.\n\r", ch ); return; } ch->move -= move; act( AT_ACTION, "You solemnly bury $p...", ch, obj, NULL, TO_CHAR ); act( AT_ACTION, "$n solemnly buries $p...", ch, obj, NULL, TO_ROOM ); xSET_BIT( obj->extra_flags, ITEM_BURIED ); WAIT_STATE( ch, URANGE( 10, move / 2, 100 ) ); return; } void do_brandish( CHAR_DATA *ch, char *argument ) { CHAR_DATA *vch; CHAR_DATA *vch_next; OBJ_DATA *staff; ch_ret retcode; int sn; if ( ( staff = get_eq_char( ch, WEAR_HAND ) ) == NULL ) { send_to_char( "You hold nothing in your hand.\n\r", ch ); return; } if ( staff->item_type != ITEM_STAFF ) { send_to_char( "You can brandish only with a staff.\n\r", ch ); return; } if ( ( sn = staff->value[3] ) < 0 || sn >= top_sn || skill_table[sn]->spell_fun == NULL ) { bug( "Do_brandish: bad sn %d on object vnum %d.", sn, staff->pIndexData->vnum ); return; } WAIT_STATE( ch, 2 * PULSE_VIOLENCE ); if ( staff->value[2] > 0 ) { if ( !oprog_use_trigger( ch, staff, NULL, NULL, NULL ) ) { act( AT_MAGIC, "$n brandishes $p.", ch, staff, NULL, TO_ROOM ); act( AT_MAGIC, "You brandish $p.", ch, staff, NULL, TO_CHAR ); } for ( vch = ch->in_room->first_person; vch; vch = vch_next ) { vch_next = vch->next_in_room; if ( !IS_NPC( vch ) && xIS_SET( vch->act, PLR_WIZINVIS )) continue; else switch ( skill_table[sn]->target ) { default: bug( "Do_brandish: bad target for sn %d.", sn ); return; case TAR_IGNORE: if ( vch != ch ) continue; break; case TAR_CHAR_OFFENSIVE: if ( IS_NPC(ch) ? IS_NPC(vch) : !IS_NPC(vch) ) continue; break; case TAR_CHAR_DEFENSIVE: if ( IS_NPC(ch) ? !IS_NPC(vch) : IS_NPC(vch) ) continue; break; case TAR_CHAR_SELF: if ( vch != ch ) continue; break; } retcode = obj_cast_spell( staff->value[3], staff->value[0], ch, vch, NULL ); if ( retcode == rCHAR_DIED || retcode == rBOTH_DIED ) { bug( "do_brandish: char died", 0 ); return; } } } if ( --staff->value[2] <= 0 ) { act( AT_MAGIC, "$p blazes bright and vanishes from $n's hands!", ch, staff, NULL, TO_ROOM ); act( AT_MAGIC, "$p blazes bright and is gone!", ch, staff, NULL, TO_CHAR ); if ( staff->serial == cur_obj ) global_objcode = rOBJ_USED; extract_obj( staff ); } return; } /* Make objects in rooms that are nofloor fall - Scryn 1/23/96 */ void obj_fall( OBJ_DATA *obj, bool through ) { EXIT_DATA *pexit; ROOM_INDEX_DATA *to_room; static int fall_count; char buf[MAX_STRING_LENGTH]; static bool is_falling; /* Stop loops from the call to obj_to_room() -- Altrag */ if ( !obj->in_room || is_falling ) return; if (fall_count > 80) { bug( "object falling in loop more than 80 times", 0 ); extract_obj(obj); fall_count = 0; return; } if ( IS_SET( obj->in_room->room_flags, ROOM_NOFLOOR ) && CAN_GO( obj, DIR_DOWN ) && !IS_OBJ_STAT( obj, ITEM_HOVER ) ) { pexit = get_exit( obj->in_room, DIR_DOWN ); to_room = pexit->to_room; if (through) fall_count++; else fall_count = 0; if (obj->in_room == to_room) { sprintf(buf, "Object falling into same room, room %d", to_room->vnum); bug( buf, 0 ); extract_obj( obj ); return; } if (obj->in_room->first_person) { act( AT_PLAIN, "$p falls far below.", obj->in_room->first_person, obj, NULL, TO_ROOM ); act( AT_PLAIN, "$p falls far below.", obj->in_room->first_person, obj, NULL, TO_CHAR ); } obj_from_room( obj ); is_falling = TRUE; obj = obj_to_room( obj, to_room ); is_falling = FALSE; if (obj->in_room->first_person) { act( AT_PLAIN, "$p falls from above.", obj->in_room->first_person, obj, NULL, TO_ROOM ); act( AT_PLAIN, "$p falls from above.", obj->in_room->first_person, obj, NULL, TO_CHAR ); } if (!IS_SET( obj->in_room->room_flags, ROOM_NOFLOOR ) && through ) { int dam = obj->weight*(fall_count/2); /* Damage players */ if ( obj->in_room->first_person && number_percent() > 15 ) { CHAR_DATA *rch; CHAR_DATA *vch = NULL; int chcnt = 0; for ( rch = obj->in_room->first_person; rch; rch = rch->next_in_room, chcnt++ ) if ( number_range( 0, chcnt ) == 0 ) vch = rch; act( AT_WHITE, "$p falls on $n!", vch, obj, NULL, TO_ROOM ); act( AT_WHITE, "$p falls on you!", vch, obj, NULL, TO_CHAR ); lose_hp(vch, dam); } /* Damage objects */ switch( obj->item_type ) { case ITEM_WEAPON: case ITEM_ARMOR: if ( (obj->value[0] - dam) <= 0 ) { if (obj->in_room->first_person) { act( AT_PLAIN, "$p is destroyed by the fall!", obj->in_room->first_person, obj, NULL, TO_ROOM ); act( AT_PLAIN, "$p is destroyed by the fall!", obj->in_room->first_person, obj, NULL, TO_CHAR ); } make_scraps(obj); } else obj->value[0] -= dam; break; default: if ( (dam*15) > get_obj_resistance(obj) ) { if (obj->in_room->first_person) { act( AT_PLAIN, "$p is destroyed by the fall!", obj->in_room->first_person, obj, NULL, TO_ROOM ); act( AT_PLAIN, "$p is destroyed by the fall!", obj->in_room->first_person, obj, NULL, TO_CHAR ); } make_scraps(obj); } break; } } obj_fall( obj, TRUE ); } return; } /* Scryn, by request of Darkur, 12/04/98 */ /* Reworked recursive_note_find to fix crash bug when the note was left * blank. 7/6/98 -- Shaddai */ void do_findnote( CHAR_DATA *ch, char *argument ) { OBJ_DATA* obj; if ( IS_NPC(ch) ) { send_to_char( "Huh?\n\r", ch ); return; } if( argument[0] == '\0' ) { send_to_char( "You must specify at least one keyword.\n\r", ch); return; } obj = recursive_note_find(ch->first_carrying, argument); if(obj) { if(obj->in_obj) { obj_from_obj(obj); obj = obj_to_char(obj, ch); } } else send_to_char("Note not found.\n\r", ch); return; } OBJ_DATA* recursive_note_find( OBJ_DATA *obj, char *argument ) { OBJ_DATA* returned_obj; bool match = TRUE; char* argcopy; char* subject; char arg[MAX_INPUT_LENGTH]; char subj[MAX_STRING_LENGTH]; if(!obj) return NULL; switch(obj->item_type) { case ITEM_PAPER: if ((subject = get_extra_descr( "_subject_", obj->first_extradesc))==NULL) break; sprintf(subj, "%s", strlower(subject) ); subject = strlower(subj); argcopy = argument; while(match) { argcopy = one_argument(argcopy, arg); if(arg[0] == '\0') break; if(!strstr(subject, arg)) match = FALSE; } if(match) return obj; break; case ITEM_CONTAINER: case ITEM_CORPSE_NPC: case ITEM_CORPSE_PC: if(obj->first_content) { returned_obj = recursive_note_find(obj->first_content, argument); if(returned_obj) return returned_obj; } break; default: break; } return recursive_note_find(obj->next_content, argument); }