act.item.c
1 /* ************************************************************************ 2 * File: act.item.c Part of CircleMUD * 3 * Usage: object handling routines -- get/drop and container handling * 4 * * 5 * All rights reserved. See license.doc for complete information. * 6 * * 7 * Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University * 8 * CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991. * 9 ************************************************************************ */ 10 11 #include "conf.h" 12 #include "sysdep.h" 13 14 15 #include "structs.h" 16 #include "utils.h" 17 #include "comm.h" 18 #include "interpreter.h" 19 #include "handler.h" 20 #include "db.h" 21 #include "spells.h" 22 #include "constants.h" 23 24 /* extern variables */ 25 extern room_rnum donation_room_1; 26 #if 0 27 extern room_rnum donation_room_2; /* uncomment if needed! */ 28 extern room_rnum donation_room_3; /* uncomment if needed! */ 29 #endif 30 31 /* local functions */ 32 int can_take_obj(struct char_data *ch, struct obj_data *obj); 33 void get_check_money(struct char_data *ch, struct obj_data *obj); 34 int perform_get_from_room(struct char_data *ch, struct obj_data *obj); 35 void get_from_room(struct char_data *ch, char *arg, int amount); 36 void perform_give_gold(struct char_data *ch, struct char_data *vict, int amount); 37 void perform_give(struct char_data *ch, struct char_data *vict, struct obj_data *obj); 38 int perform_drop(struct char_data *ch, struct obj_data *obj, byte mode, const char *sname, room_rnum RDR); 39 void perform_drop_gold(struct char_data *ch, int amount, byte mode, room_rnum RDR); 40 struct char_data *give_find_vict(struct char_data *ch, char *arg); 41 void weight_change_object(struct obj_data *obj, int weight); 42 void perform_put(struct char_data *ch, struct obj_data *obj, struct obj_data *cont); 43 void name_from_drinkcon(struct obj_data *obj); 44 void get_from_container(struct char_data *ch, struct obj_data *cont, char *arg, int mode, int amount); 45 void name_to_drinkcon(struct obj_data *obj, int type); 46 void wear_message(struct char_data *ch, struct obj_data *obj, int where); 47 void perform_wear(struct char_data *ch, struct obj_data *obj, int where); 48 int find_eq_pos(struct char_data *ch, struct obj_data *obj, char *arg); 49 void perform_get_from_container(struct char_data *ch, struct obj_data *obj, struct obj_data *cont, int mode); 50 void perform_remove(struct char_data *ch, int pos); 51 ACMD(do_remove); 52 ACMD(do_put); 53 ACMD(do_get); 54 ACMD(do_drop); 55 ACMD(do_give); 56 ACMD(do_drink); 57 ACMD(do_eat); 58 ACMD(do_pour); 59 ACMD(do_wear); 60 ACMD(do_wield); 61 ACMD(do_grab); 62 63 64 void perform_put(struct char_data *ch, struct obj_data *obj, 65 struct obj_data *cont) 66 { 67 if (GET_OBJ_WEIGHT(cont) + GET_OBJ_WEIGHT(obj) > GET_OBJ_VAL(cont, 0)) 68 act("$p won't fit in $P.", FALSE, ch, obj, cont, TO_CHAR); 69 else if (OBJ_FLAGGED(obj, ITEM_NODROP) && IN_ROOM(cont) != NOWHERE) 70 act("You can't get $p out of your hand.", FALSE, ch, obj, NULL, TO_CHAR); 71 else { 72 obj_from_char(obj); 73 obj_to_obj(obj, cont); 74 75 act("$n puts $p in $P.", TRUE, ch, obj, cont, TO_ROOM); 76 77 /* Yes, I realize this is strange until we have auto-equip on rent. -gg */ 78 if (OBJ_FLAGGED(obj, ITEM_NODROP) && !OBJ_FLAGGED(cont, ITEM_NODROP)) { 79 SET_BIT(GET_OBJ_EXTRA(cont), ITEM_NODROP); 80 act("You get a strange feeling as you put $p in $P.", FALSE, 81 ch, obj, cont, TO_CHAR); 82 } else 83 act("You put $p in $P.", FALSE, ch, obj, cont, TO_CHAR); 84 } 85 } 86 87 88 /* The following put modes are supported by the code below: 89 90 1) put <object> <container> 91 2) put all.<object> <container> 92 3) put all <container> 93 94 <container> must be in inventory or on ground. 95 all objects to be put into container must be in inventory. 96 */ 97 98 ACMD(do_put) 99 { 100 char arg1[MAX_INPUT_LENGTH]; 101 char arg2[MAX_INPUT_LENGTH]; 102 char arg3[MAX_INPUT_LENGTH]; 103 struct obj_data *obj, *next_obj, *cont; 104 struct char_data *tmp_char; 105 int obj_dotmode, cont_dotmode, found = 0, howmany = 1; 106 char *theobj, *thecont; 107 108 one_argument(two_arguments(argument, arg1, arg2), arg3); /* three_arguments */ 109 110 if (*arg3 && is_number(arg1)) { 111 howmany = atoi(arg1); 112 theobj = arg2; 113 thecont = arg3; 114 } else { 115 theobj = arg1; 116 thecont = arg2; 117 } 118 obj_dotmode = find_all_dots(theobj); 119 cont_dotmode = find_all_dots(thecont); 120 121 if (!*theobj) 122 send_to_char(ch, "Put what in what?\r\n"); 123 else if (cont_dotmode != FIND_INDIV) 124 send_to_char(ch, "You can only put things into one container at a time.\r\n"); 125 else if (!*thecont) { 126 send_to_char(ch, "What do you want to put %s in?\r\n", obj_dotmode == FIND_INDIV ? "it" : "them"); 127 } else { 128 generic_find(thecont, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &tmp_char, &cont); 129 if (!cont) 130 send_to_char(ch, "You don't see %s %s here.\r\n", AN(thecont), thecont); 131 else if (GET_OBJ_TYPE(cont) != ITEM_CONTAINER) 132 act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR); 133 else if (OBJVAL_FLAGGED(cont, CONT_CLOSED)) 134 send_to_char(ch, "You'd better open it first!\r\n"); 135 else { 136 if (obj_dotmode == FIND_INDIV) { /* put <obj> <container> */ 137 if (!(obj = get_obj_in_list_vis(ch, theobj, NULL, ch->carrying))) 138 send_to_char(ch, "You aren't carrying %s %s.\r\n", AN(theobj), theobj); 139 else if (obj == cont && howmany == 1) 140 send_to_char(ch, "You attempt to fold it into itself, but fail.\r\n"); 141 else { 142 while (obj && howmany) { 143 next_obj = obj->next_content; 144 if (obj != cont) { 145 howmany--; 146 perform_put(ch, obj, cont); 147 } 148 obj = get_obj_in_list_vis(ch, theobj, NULL, next_obj); 149 } 150 } 151 } else { 152 for (obj = ch->carrying; obj; obj = next_obj) { 153 next_obj = obj->next_content; 154 if (obj != cont && CAN_SEE_OBJ(ch, obj) && 155 (obj_dotmode == FIND_ALL || isname(theobj, obj->name))) { 156 found = 1; 157 perform_put(ch, obj, cont); 158 } 159 } 160 if (!found) { 161 if (obj_dotmode == FIND_ALL) 162 send_to_char(ch, "You don't seem to have anything to put in it.\r\n"); 163 else 164 send_to_char(ch, "You don't seem to have any %ss.\r\n", theobj); 165 } 166 } 167 } 168 } 169 } 170 171 172 173 int can_take_obj(struct char_data *ch, struct obj_data *obj) 174 { 175 if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) { 176 act("$p: you can't carry that many items.", FALSE, ch, obj, 0, TO_CHAR); 177 return (0); 178 } else if ((IS_CARRYING_W(ch) + GET_OBJ_WEIGHT(obj)) > CAN_CARRY_W(ch)) { 179 act("$p: you can't carry that much weight.", FALSE, ch, obj, 0, TO_CHAR); 180 return (0); 181 } else if (!(CAN_WEAR(obj, ITEM_WEAR_TAKE))) { 182 act("$p: you can't take that!", FALSE, ch, obj, 0, TO_CHAR); 183 return (0); 184 } 185 return (1); 186 } 187 188 189 void get_check_money(struct char_data *ch, struct obj_data *obj) 190 { 191 int value = GET_OBJ_VAL(obj, 0); 192 193 if (GET_OBJ_TYPE(obj) != ITEM_MONEY || value <= 0) 194 return; 195 196 extract_obj(obj); 197 198 GET_GOLD(ch) += value; 199 200 if (value == 1) 201 send_to_char(ch, "There was 1 coin.\r\n"); 202 else 203 send_to_char(ch, "There were %d coins.\r\n", value); 204 } 205 206 207 void perform_get_from_container(struct char_data *ch, struct obj_data *obj, 208 struct obj_data *cont, int mode) 209 { 210 if (mode == FIND_OBJ_INV || can_take_obj(ch, obj)) { 211 if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) 212 act("$p: you can't hold any more items.", FALSE, ch, obj, 0, TO_CHAR); 213 else { 214 obj_from_obj(obj); 215 obj_to_char(obj, ch); 216 act("You get $p from $P.", FALSE, ch, obj, cont, TO_CHAR); 217 act("$n gets $p from $P.", TRUE, ch, obj, cont, TO_ROOM); 218 get_check_money(ch, obj); 219 } 220 } 221 } 222 223 224 void get_from_container(struct char_data *ch, struct obj_data *cont, 225 char *arg, int mode, int howmany) 226 { 227 struct obj_data *obj, *next_obj; 228 int obj_dotmode, found = 0; 229 230 obj_dotmode = find_all_dots(arg); 231 232 if (OBJVAL_FLAGGED(cont, CONT_CLOSED)) 233 act("$p is closed.", FALSE, ch, cont, 0, TO_CHAR); 234 else if (obj_dotmode == FIND_INDIV) { 235 if (!(obj = get_obj_in_list_vis(ch, arg, NULL, cont->contains))) { 236 char buf[MAX_STRING_LENGTH]; 237 238 snprintf(buf, sizeof(buf), "There doesn't seem to be %s %s in $p.", AN(arg), arg); 239 act(buf, FALSE, ch, cont, 0, TO_CHAR); 240 } else { 241 struct obj_data *obj_next; 242 while (obj && howmany--) { 243 obj_next = obj->next_content; 244 perform_get_from_container(ch, obj, cont, mode); 245 obj = get_obj_in_list_vis(ch, arg, NULL, obj_next); 246 } 247 } 248 } else { 249 if (obj_dotmode == FIND_ALLDOT && !*arg) { 250 send_to_char(ch, "Get all of what?\r\n"); 251 return; 252 } 253 for (obj = cont->contains; obj; obj = next_obj) { 254 next_obj = obj->next_content; 255 if (CAN_SEE_OBJ(ch, obj) && 256 (obj_dotmode == FIND_ALL || isname(arg, obj->name))) { 257 found = 1; 258 perform_get_from_container(ch, obj, cont, mode); 259 } 260 } 261 if (!found) { 262 if (obj_dotmode == FIND_ALL) 263 act("$p seems to be empty.", FALSE, ch, cont, 0, TO_CHAR); 264 else { 265 char buf[MAX_STRING_LENGTH]; 266 267 snprintf(buf, sizeof(buf), "You can't seem to find any %ss in $p.", arg); 268 act(buf, FALSE, ch, cont, 0, TO_CHAR); 269 } 270 } 271 } 272 } 273 274 275 int perform_get_from_room(struct char_data *ch, struct obj_data *obj) 276 { 277 if (can_take_obj(ch, obj)) { 278 obj_from_room(obj); 279 obj_to_char(obj, ch); 280 act("You get $p.", FALSE, ch, obj, 0, TO_CHAR); 281 act("$n gets $p.", TRUE, ch, obj, 0, TO_ROOM); 282 get_check_money(ch, obj); 283 return (1); 284 } 285 return (0); 286 } 287 288 289 void get_from_room(struct char_data *ch, char *arg, int howmany) 290 { 291 struct obj_data *obj, *next_obj; 292 int dotmode, found = 0; 293 294 dotmode = find_all_dots(arg); 295 296 if (dotmode == FIND_INDIV) { 297 if (!(obj = get_obj_in_list_vis(ch, arg, NULL, world[IN_ROOM(ch)].contents))) 298 send_to_char(ch, "You don't see %s %s here.\r\n", AN(arg), arg); 299 else { 300 struct obj_data *obj_next; 301 while(obj && howmany--) { 302 obj_next = obj->next_content; 303 perform_get_from_room(ch, obj); 304 obj = get_obj_in_list_vis(ch, arg, NULL, obj_next); 305 } 306 } 307 } else { 308 if (dotmode == FIND_ALLDOT && !*arg) { 309 send_to_char(ch, "Get all of what?\r\n"); 310 return; 311 } 312 for (obj = world[IN_ROOM(ch)].contents; obj; obj = next_obj) { 313 next_obj = obj->next_content; 314 if (CAN_SEE_OBJ(ch, obj) && 315 (dotmode == FIND_ALL || isname(arg, obj->name))) { 316 found = 1; 317 perform_get_from_room(ch, obj); 318 } 319 } 320 if (!found) { 321 if (dotmode == FIND_ALL) 322 send_to_char(ch, "There doesn't seem to be anything here.\r\n"); 323 else 324 send_to_char(ch, "You don't see any %ss here.\r\n", arg); 325 } 326 } 327 } 328 329 330 331 ACMD(do_get) 332 { 333 char arg1[MAX_INPUT_LENGTH]; 334 char arg2[MAX_INPUT_LENGTH]; 335 char arg3[MAX_INPUT_LENGTH]; 336 337 int cont_dotmode, found = 0, mode; 338 struct obj_data *cont; 339 struct char_data *tmp_char; 340 341 one_argument(two_arguments(argument, arg1, arg2), arg3); /* three_arguments */ 342 343 if (!*arg1) 344 send_to_char(ch, "Get what?\r\n"); 345 else if (!*arg2) 346 get_from_room(ch, arg1, 1); 347 else if (is_number(arg1) && !*arg3) 348 get_from_room(ch, arg2, atoi(arg1)); 349 else { 350 int amount = 1; 351 if (is_number(arg1)) { 352 amount = atoi(arg1); 353 strcpy(arg1, arg2); /* strcpy: OK (sizeof: arg1 == arg2) */ 354 strcpy(arg2, arg3); /* strcpy: OK (sizeof: arg2 == arg3) */ 355 } 356 cont_dotmode = find_all_dots(arg2); 357 if (cont_dotmode == FIND_INDIV) { 358 mode = generic_find(arg2, FIND_OBJ_INV | FIND_OBJ_ROOM, ch, &tmp_char, &cont); 359 if (!cont) 360 send_to_char(ch, "You don't have %s %s.\r\n", AN(arg2), arg2); 361 else if (GET_OBJ_TYPE(cont) != ITEM_CONTAINER) 362 act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR); 363 else 364 get_from_container(ch, cont, arg1, mode, amount); 365 } else { 366 if (cont_dotmode == FIND_ALLDOT && !*arg2) { 367 send_to_char(ch, "Get from all of what?\r\n"); 368 return; 369 } 370 for (cont = ch->carrying; cont; cont = cont->next_content) 371 if (CAN_SEE_OBJ(ch, cont) && 372 (cont_dotmode == FIND_ALL || isname(arg2, cont->name))) { 373 if (GET_OBJ_TYPE(cont) == ITEM_CONTAINER) { 374 found = 1; 375 get_from_container(ch, cont, arg1, FIND_OBJ_INV, amount); 376 } else if (cont_dotmode == FIND_ALLDOT) { 377 found = 1; 378 act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR); 379 } 380 } 381 for (cont = world[IN_ROOM(ch)].contents; cont; cont = cont->next_content) 382 if (CAN_SEE_OBJ(ch, cont) && 383 (cont_dotmode == FIND_ALL || isname(arg2, cont->name))) { 384 if (GET_OBJ_TYPE(cont) == ITEM_CONTAINER) { 385 get_from_container(ch, cont, arg1, FIND_OBJ_ROOM, amount); 386 found = 1; 387 } else if (cont_dotmode == FIND_ALLDOT) { 388 act("$p is not a container.", FALSE, ch, cont, 0, TO_CHAR); 389 found = 1; 390 } 391 } 392 if (!found) { 393 if (cont_dotmode == FIND_ALL) 394 send_to_char(ch, "You can't seem to find any containers.\r\n"); 395 else 396 send_to_char(ch, "You can't seem to find any %ss here.\r\n", arg2); 397 } 398 } 399 } 400 } 401 402 403 void perform_drop_gold(struct char_data *ch, int amount, 404 byte mode, room_rnum RDR) 405 { 406 struct obj_data *obj; 407 408 if (amount <= 0) 409 send_to_char(ch, "Heh heh heh.. we are jolly funny today, eh?\r\n"); 410 else if (GET_GOLD(ch) < amount) 411 send_to_char(ch, "You don't have that many coins!\r\n"); 412 else { 413 if (mode != SCMD_JUNK) { 414 WAIT_STATE(ch, PULSE_VIOLENCE); /* to prevent coin-bombing */ 415 obj = create_money(amount); 416 if (mode == SCMD_DONATE) { 417 send_to_char(ch, "You throw some gold into the air where it disappears in a puff of smoke!\r\n"); 418 act("$n throws some gold into the air where it disappears in a puff of smoke!", 419 FALSE, ch, 0, 0, TO_ROOM); 420 obj_to_room(obj, RDR); 421 act("$p suddenly appears in a puff of orange smoke!", 0, 0, obj, 0, TO_ROOM); 422 } else { 423 char buf[MAX_STRING_LENGTH]; 424 425 snprintf(buf, sizeof(buf), "$n drops %s.", money_desc(amount)); 426 act(buf, TRUE, ch, 0, 0, TO_ROOM); 427 428 send_to_char(ch, "You drop some gold.\r\n"); 429 obj_to_room(obj, IN_ROOM(ch)); 430 } 431 } else { 432 char buf[MAX_STRING_LENGTH]; 433 434 snprintf(buf, sizeof(buf), "$n drops %s which disappears in a puff of smoke!", money_desc(amount)); 435 act(buf, FALSE, ch, 0, 0, TO_ROOM); 436 437 send_to_char(ch, "You drop some gold which disappears in a puff of smoke!\r\n"); 438 } 439 GET_GOLD(ch) -= amount; 440 } 441 } 442 443 444 #define VANISH(mode) ((mode == SCMD_DONATE || mode == SCMD_JUNK) ? \ 445 " It vanishes in a puff of smoke!" : "") 446 447 int perform_drop(struct char_data *ch, struct obj_data *obj, 448 byte mode, const char *sname, room_rnum RDR) 449 { 450 char buf[MAX_STRING_LENGTH]; 451 int value; 452 453 if (OBJ_FLAGGED(obj, ITEM_NODROP)) { 454 snprintf(buf, sizeof(buf), "You can't %s $p, it must be CURSED!", sname); 455 act(buf, FALSE, ch, obj, 0, TO_CHAR); 456 return (0); 457 } 458 459 snprintf(buf, sizeof(buf), "You %s $p.%s", sname, VANISH(mode)); 460 act(buf, FALSE, ch, obj, 0, TO_CHAR); 461 462 snprintf(buf, sizeof(buf), "$n %ss $p.%s", sname, VANISH(mode)); 463 act(buf, TRUE, ch, obj, 0, TO_ROOM); 464 465 obj_from_char(obj); 466 467 if ((mode == SCMD_DONATE) && OBJ_FLAGGED(obj, ITEM_NODONATE)) 468 mode = SCMD_JUNK; 469 470 switch (mode) { 471 case SCMD_DROP: 472 obj_to_room(obj, IN_ROOM(ch)); 473 return (0); 474 case SCMD_DONATE: 475 obj_to_room(obj, RDR); 476 act("$p suddenly appears in a puff a smoke!", FALSE, 0, obj, 0, TO_ROOM); 477 return (0); 478 case SCMD_JUNK: 479 value = MAX(1, MIN(200, GET_OBJ_COST(obj) / 16)); 480 extract_obj(obj); 481 return (value); 482 default: 483 log("SYSERR: Incorrect argument %d passed to perform_drop.", mode); 484 break; 485 } 486 487 return (0); 488 } 489 490 491 492 ACMD(do_drop) 493 { 494 char arg[MAX_INPUT_LENGTH]; 495 struct obj_data *obj, *next_obj; 496 room_rnum RDR = 0; 497 byte mode = SCMD_DROP; 498 int dotmode, amount = 0, multi; 499 const char *sname; 500 501 switch (subcmd) { 502 case SCMD_JUNK: 503 sname = "junk"; 504 mode = SCMD_JUNK; 505 break; 506 case SCMD_DONATE: 507 sname = "donate"; 508 mode = SCMD_DONATE; 509 switch (rand_number(0, 2)) { 510 case 0: 511 mode = SCMD_JUNK; 512 break; 513 case 1: 514 case 2: 515 RDR = real_room(donation_room_1); 516 break; 517 /* case 3: RDR = real_room(donation_room_2); break; 518 case 4: RDR = real_room(donation_room_3); break; 519 */ 520 } 521 if (RDR == NOWHERE) { 522 send_to_char(ch, "Sorry, you can't donate anything right now.\r\n"); 523 return; 524 } 525 break; 526 default: 527 sname = "drop"; 528 break; 529 } 530 531 argument = one_argument(argument, arg); 532 533 if (!*arg) { 534 send_to_char(ch, "What do you want to %s?\r\n", sname); 535 return; 536 } else if (is_number(arg)) { 537 multi = atoi(arg); 538 one_argument(argument, arg); 539 if (!str_cmp("coins", arg) || !str_cmp("coin", arg)) 540 perform_drop_gold(ch, multi, mode, RDR); 541 else if (multi <= 0) 542 send_to_char(ch, "Yeah, that makes sense.\r\n"); 543 else if (!*arg) 544 send_to_char(ch, "What do you want to %s %d of?\r\n", sname, multi); 545 else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 546 send_to_char(ch, "You don't seem to have any %ss.\r\n", arg); 547 else { 548 do { 549 next_obj = get_obj_in_list_vis(ch, arg, NULL, obj->next_content); 550 amount += perform_drop(ch, obj, mode, sname, RDR); 551 obj = next_obj; 552 } while (obj && --multi); 553 } 554 } else { 555 dotmode = find_all_dots(arg); 556 557 /* Can't junk or donate all */ 558 if ((dotmode == FIND_ALL) && (subcmd == SCMD_JUNK || subcmd == SCMD_DONATE)) { 559 if (subcmd == SCMD_JUNK) 560 send_to_char(ch, "Go to the dump if you want to junk EVERYTHING!\r\n"); 561 else 562 send_to_char(ch, "Go do the donation room if you want to donate EVERYTHING!\r\n"); 563 return; 564 } 565 if (dotmode == FIND_ALL) { 566 if (!ch->carrying) 567 send_to_char(ch, "You don't seem to be carrying anything.\r\n"); 568 else 569 for (obj = ch->carrying; obj; obj = next_obj) { 570 next_obj = obj->next_content; 571 amount += perform_drop(ch, obj, mode, sname, RDR); 572 } 573 } else if (dotmode == FIND_ALLDOT) { 574 if (!*arg) { 575 send_to_char(ch, "What do you want to %s all of?\r\n", sname); 576 return; 577 } 578 if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 579 send_to_char(ch, "You don't seem to have any %ss.\r\n", arg); 580 581 while (obj) { 582 next_obj = get_obj_in_list_vis(ch, arg, NULL, obj->next_content); 583 amount += perform_drop(ch, obj, mode, sname, RDR); 584 obj = next_obj; 585 } 586 } else { 587 if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 588 send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg); 589 else 590 amount += perform_drop(ch, obj, mode, sname, RDR); 591 } 592 } 593 594 if (amount && (subcmd == SCMD_JUNK)) { 595 send_to_char(ch, "You have been rewarded by the gods!\r\n"); 596 act("$n has been rewarded by the gods!", TRUE, ch, 0, 0, TO_ROOM); 597 GET_GOLD(ch) += amount; 598 } 599 } 600 601 602 void perform_give(struct char_data *ch, struct char_data *vict, 603 struct obj_data *obj) 604 { 605 if (OBJ_FLAGGED(obj, ITEM_NODROP)) { 606 act("You can't let go of $p!! Yeech!", FALSE, ch, obj, 0, TO_CHAR); 607 return; 608 } 609 if (IS_CARRYING_N(vict) >= CAN_CARRY_N(vict)) { 610 act("$N seems to have $S hands full.", FALSE, ch, 0, vict, TO_CHAR); 611 return; 612 } 613 if (GET_OBJ_WEIGHT(obj) + IS_CARRYING_W(vict) > CAN_CARRY_W(vict)) { 614 act("$E can't carry that much weight.", FALSE, ch, 0, vict, TO_CHAR); 615 return; 616 } 617 obj_from_char(obj); 618 obj_to_char(obj, vict); 619 act("You give $p to $N.", FALSE, ch, obj, vict, TO_CHAR); 620 act("$n gives you $p.", FALSE, ch, obj, vict, TO_VICT); 621 act("$n gives $p to $N.", TRUE, ch, obj, vict, TO_NOTVICT); 622 } 623 624 /* utility function for give */ 625 struct char_data *give_find_vict(struct char_data *ch, char *arg) 626 { 627 struct char_data *vict; 628 629 skip_spaces(&arg); 630 if (!*arg) 631 send_to_char(ch, "To who?\r\n"); 632 else if (!(vict = get_char_vis(ch, arg, NULL, FIND_CHAR_ROOM))) 633 send_to_char(ch, "%s", NOPERSON); 634 else if (vict == ch) 635 send_to_char(ch, "What's the point of that?\r\n"); 636 else 637 return (vict); 638 639 return (NULL); 640 } 641 642 643 void perform_give_gold(struct char_data *ch, struct char_data *vict, 644 int amount) 645 { 646 char buf[MAX_STRING_LENGTH]; 647 648 if (amount <= 0) { 649 send_to_char(ch, "Heh heh heh ... we are jolly funny today, eh?\r\n"); 650 return; 651 } 652 if ((GET_GOLD(ch) < amount) && (IS_NPC(ch) || (GET_LEVEL(ch) < LVL_GOD))) { 653 send_to_char(ch, "You don't have that many coins!\r\n"); 654 return; 655 } 656 send_to_char(ch, "%s", OK); 657 658 snprintf(buf, sizeof(buf), "$n gives you %d gold coin%s.", amount, amount == 1 ? "" : "s"); 659 act(buf, FALSE, ch, 0, vict, TO_VICT); 660 661 snprintf(buf, sizeof(buf), "$n gives %s to $N.", money_desc(amount)); 662 act(buf, TRUE, ch, 0, vict, TO_NOTVICT); 663 664 if (IS_NPC(ch) || (GET_LEVEL(ch) < LVL_GOD)) 665 GET_GOLD(ch) -= amount; 666 GET_GOLD(vict) += amount; 667 } 668 669 670 ACMD(do_give) 671 { 672 char arg[MAX_STRING_LENGTH]; 673 int amount, dotmode; 674 struct char_data *vict; 675 struct obj_data *obj, *next_obj; 676 677 argument = one_argument(argument, arg); 678 679 if (!*arg) 680 send_to_char(ch, "Give what to who?\r\n"); 681 else if (is_number(arg)) { 682 amount = atoi(arg); 683 argument = one_argument(argument, arg); 684 if (!str_cmp("coins", arg) || !str_cmp("coin", arg)) { 685 one_argument(argument, arg); 686 if ((vict = give_find_vict(ch, arg)) != NULL) 687 perform_give_gold(ch, vict, amount); 688 return; 689 } else if (!*arg) /* Give multiple code. */ 690 send_to_char(ch, "What do you want to give %d of?\r\n", amount); 691 else if (!(vict = give_find_vict(ch, argument))) 692 return; 693 else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 694 send_to_char(ch, "You don't seem to have any %ss.\r\n", arg); 695 else { 696 while (obj && amount--) { 697 next_obj = get_obj_in_list_vis(ch, arg, NULL, obj->next_content); 698 perform_give(ch, vict, obj); 699 obj = next_obj; 700 } 701 } 702 } else { 703 char buf1[MAX_INPUT_LENGTH]; 704 705 one_argument(argument, buf1); 706 if (!(vict = give_find_vict(ch, buf1))) 707 return; 708 dotmode = find_all_dots(arg); 709 if (dotmode == FIND_INDIV) { 710 if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 711 send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg); 712 else 713 perform_give(ch, vict, obj); 714 } else { 715 if (dotmode == FIND_ALLDOT && !*arg) { 716 send_to_char(ch, "All of what?\r\n"); 717 return; 718 } 719 if (!ch->carrying) 720 send_to_char(ch, "You don't seem to be holding anything.\r\n"); 721 else 722 for (obj = ch->carrying; obj; obj = next_obj) { 723 next_obj = obj->next_content; 724 if (CAN_SEE_OBJ(ch, obj) && 725 ((dotmode == FIND_ALL || isname(arg, obj->name)))) 726 perform_give(ch, vict, obj); 727 } 728 } 729 } 730 } 731 732 733 734 void weight_change_object(struct obj_data *obj, int weight) 735 { 736 struct obj_data *tmp_obj; 737 struct char_data *tmp_ch; 738 739 if (IN_ROOM(obj) != NOWHERE) { 740 GET_OBJ_WEIGHT(obj) += weight; 741 } else if ((tmp_ch = obj->carried_by)) { 742 obj_from_char(obj); 743 GET_OBJ_WEIGHT(obj) += weight; 744 obj_to_char(obj, tmp_ch); 745 } else if ((tmp_obj = obj->in_obj)) { 746 obj_from_obj(obj); 747 GET_OBJ_WEIGHT(obj) += weight; 748 obj_to_obj(obj, tmp_obj); 749 } else { 750 log("SYSERR: Unknown attempt to subtract weight from an object."); 751 } 752 } 753 754 755 756 void name_from_drinkcon(struct obj_data *obj) 757 { 758 char *new_name, *cur_name, *next; 759 const char *liqname; 760 int liqlen, cpylen; 761 762 if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN)) 763 return; 764 765 liqname = drinknames[GET_OBJ_VAL(obj, 2)]; 766 if (!isname(liqname, obj->name)) { 767 log("SYSERR: Can't remove liquid '%s' from '%s' (%d) item.", liqname, obj->name, obj->item_number); 768 return; 769 } 770 771 liqlen = strlen(liqname); 772 CREATE(new_name, char, strlen(obj->name) - strlen(liqname)); /* +1 for NUL, -1 for space */ 773 774 for (cur_name = obj->name; cur_name; cur_name = next) { 775 if (*cur_name == ' ') 776 cur_name++; 777 778 if ((next = strchr(cur_name, ' '))) 779 cpylen = next - cur_name; 780 else 781 cpylen = strlen(cur_name); 782 783 if (!strn_cmp(cur_name, liqname, liqlen)) 784 continue; 785 786 if (*new_name) 787 strcat(new_name, " "); /* strcat: OK (size precalculated) */ 788 strncat(new_name, cur_name, cpylen); /* strncat: OK (size precalculated) */ 789 } 790 791 if (GET_OBJ_RNUM(obj) == NOTHING || obj->name != obj_proto[GET_OBJ_RNUM(obj)].name) 792 free(obj->name); 793 obj->name = new_name; 794 } 795 796 797 798 void name_to_drinkcon(struct obj_data *obj, int type) 799 { 800 char *new_name; 801 802 if (!obj || (GET_OBJ_TYPE(obj) != ITEM_DRINKCON && GET_OBJ_TYPE(obj) != ITEM_FOUNTAIN)) 803 return; 804 805 CREATE(new_name, char, strlen(obj->name) + strlen(drinknames[type]) + 2); 806 sprintf(new_name, "%s %s", obj->name, drinknames[type]); /* sprintf: OK */ 807 808 if (GET_OBJ_RNUM(obj) == NOTHING || obj->name != obj_proto[GET_OBJ_RNUM(obj)].name) 809 free(obj->name); 810 811 obj->name = new_name; 812 } 813 814 815 816 ACMD(do_drink) 817 { 818 char arg[MAX_INPUT_LENGTH]; 819 struct obj_data *temp; 820 struct affected_type af; 821 int amount, weight; 822 int on_ground = 0; 823 824 one_argument(argument, arg); 825 826 if (IS_NPC(ch)) /* Cannot use GET_COND() on mobs. */ 827 return; 828 829 if (!*arg) { 830 send_to_char(ch, "Drink from what?\r\n"); 831 return; 832 } 833 if (!(temp = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) { 834 if (!(temp = get_obj_in_list_vis(ch, arg, NULL, world[IN_ROOM(ch)].contents))) { 835 send_to_char(ch, "You can't find it!\r\n"); 836 return; 837 } else 838 on_ground = 1; 839 } 840 if ((GET_OBJ_TYPE(temp) != ITEM_DRINKCON) && 841 (GET_OBJ_TYPE(temp) != ITEM_FOUNTAIN)) { 842 send_to_char(ch, "You can't drink from that!\r\n"); 843 return; 844 } 845 if (on_ground && (GET_OBJ_TYPE(temp) == ITEM_DRINKCON)) { 846 send_to_char(ch, "You have to be holding that to drink from it.\r\n"); 847 return; 848 } 849 if ((GET_COND(ch, DRUNK) > 10) && (GET_COND(ch, THIRST) > 0)) { 850 /* The pig is drunk */ 851 send_to_char(ch, "You can't seem to get close enough to your mouth.\r\n"); 852 act("$n tries to drink but misses $s mouth!", TRUE, ch, 0, 0, TO_ROOM); 853 return; 854 } 855 if ((GET_COND(ch, FULL) > 20) && (GET_COND(ch, THIRST) > 0)) { 856 send_to_char(ch, "Your stomach can't contain anymore!\r\n"); 857 return; 858 } 859 if (!GET_OBJ_VAL(temp, 1)) { 860 send_to_char(ch, "It's empty.\r\n"); 861 return; 862 } 863 if (subcmd == SCMD_DRINK) { 864 char buf[MAX_STRING_LENGTH]; 865 866 snprintf(buf, sizeof(buf), "$n drinks %s from $p.", drinks[GET_OBJ_VAL(temp, 2)]); 867 act(buf, TRUE, ch, temp, 0, TO_ROOM); 868 869 send_to_char(ch, "You drink the %s.\r\n", drinks[GET_OBJ_VAL(temp, 2)]); 870 871 if (drink_aff[GET_OBJ_VAL(temp, 2)][DRUNK] > 0) 872 amount = (25 - GET_COND(ch, THIRST)) / drink_aff[GET_OBJ_VAL(temp, 2)][DRUNK]; 873 else 874 amount = rand_number(3, 10); 875 876 } else { 877 act("$n sips from $p.", TRUE, ch, temp, 0, TO_ROOM); 878 send_to_char(ch, "It tastes like %s.\r\n", drinks[GET_OBJ_VAL(temp, 2)]); 879 amount = 1; 880 } 881 882 amount = MIN(amount, GET_OBJ_VAL(temp, 1)); 883 884 /* You can't subtract more than the object weighs */ 885 weight = MIN(amount, GET_OBJ_WEIGHT(temp)); 886 887 weight_change_object(temp, -weight); /* Subtract amount */ 888 889 gain_condition(ch, DRUNK, drink_aff[GET_OBJ_VAL(temp, 2)][DRUNK] * amount / 4); 890 gain_condition(ch, FULL, drink_aff[GET_OBJ_VAL(temp, 2)][FULL] * amount / 4); 891 gain_condition(ch, THIRST, drink_aff[GET_OBJ_VAL(temp, 2)][THIRST] * amount / 4); 892 893 if (GET_COND(ch, DRUNK) > 10) 894 send_to_char(ch, "You feel drunk.\r\n"); 895 896 if (GET_COND(ch, THIRST) > 20) 897 send_to_char(ch, "You don't feel thirsty any more.\r\n"); 898 899 if (GET_COND(ch, FULL) > 20) 900 send_to_char(ch, "You are full.\r\n"); 901 902 if (GET_OBJ_VAL(temp, 3)) { /* The crap was poisoned ! */ 903 send_to_char(ch, "Oops, it tasted rather strange!\r\n"); 904 act("$n chokes and utters some strange sounds.", TRUE, ch, 0, 0, TO_ROOM); 905 906 af.type = SPELL_POISON; 907 af.duration = amount * 3; 908 af.modifier = 0; 909 af.location = APPLY_NONE; 910 af.bitvector = AFF_POISON; 911 affect_join(ch, &af, FALSE, FALSE, FALSE, FALSE); 912 } 913 /* empty the container, and no longer poison. */ 914 GET_OBJ_VAL(temp, 1) -= amount; 915 if (!GET_OBJ_VAL(temp, 1)) { /* The last bit */ 916 name_from_drinkcon(temp); 917 GET_OBJ_VAL(temp, 2) = 0; 918 GET_OBJ_VAL(temp, 3) = 0; 919 } 920 return; 921 } 922 923 924 925 ACMD(do_eat) 926 { 927 char arg[MAX_INPUT_LENGTH]; 928 struct obj_data *food; 929 struct affected_type af; 930 int amount; 931 932 one_argument(argument, arg); 933 934 if (IS_NPC(ch)) /* Cannot use GET_COND() on mobs. */ 935 return; 936 937 if (!*arg) { 938 send_to_char(ch, "Eat what?\r\n"); 939 return; 940 } 941 if (!(food = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) { 942 send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg); 943 return; 944 } 945 if (subcmd == SCMD_TASTE && ((GET_OBJ_TYPE(food) == ITEM_DRINKCON) || 946 (GET_OBJ_TYPE(food) == ITEM_FOUNTAIN))) { 947 do_drink(ch, argument, 0, SCMD_SIP); 948 return; 949 } 950 if ((GET_OBJ_TYPE(food) != ITEM_FOOD) && (GET_LEVEL(ch) < LVL_GOD)) { 951 send_to_char(ch, "You can't eat THAT!\r\n"); 952 return; 953 } 954 if (GET_COND(ch, FULL) > 20) {/* Stomach full */ 955 send_to_char(ch, "You are too full to eat more!\r\n"); 956 return; 957 } 958 if (subcmd == SCMD_EAT) { 959 act("You eat $p.", FALSE, ch, food, 0, TO_CHAR); 960 act("$n eats $p.", TRUE, ch, food, 0, TO_ROOM); 961 } else { 962 act("You nibble a little bit of $p.", FALSE, ch, food, 0, TO_CHAR); 963 act("$n tastes a little bit of $p.", TRUE, ch, food, 0, TO_ROOM); 964 } 965 966 amount = (subcmd == SCMD_EAT ? GET_OBJ_VAL(food, 0) : 1); 967 968 gain_condition(ch, FULL, amount); 969 970 if (GET_COND(ch, FULL) > 20) 971 send_to_char(ch, "You are full.\r\n"); 972 973 if (GET_OBJ_VAL(food, 3) && (GET_LEVEL(ch) < LVL_IMMORT)) { 974 /* The crap was poisoned ! */ 975 send_to_char(ch, "Oops, that tasted rather strange!\r\n"); 976 act("$n coughs and utters some strange sounds.", FALSE, ch, 0, 0, TO_ROOM); 977 978 af.type = SPELL_POISON; 979 af.duration = amount * 2; 980 af.modifier = 0; 981 af.location = APPLY_NONE; 982 af.bitvector = AFF_POISON; 983 affect_join(ch, &af, FALSE, FALSE, FALSE, FALSE); 984 } 985 if (subcmd == SCMD_EAT) 986 extract_obj(food); 987 else { 988 if (!(--GET_OBJ_VAL(food, 0))) { 989 send_to_char(ch, "There's nothing left now.\r\n"); 990 extract_obj(food); 991 } 992 } 993 } 994 995 996 ACMD(do_pour) 997 { 998 char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH]; 999 struct obj_data *from_obj = NULL, *to_obj = NULL; 1000 int amount; 1001 1002 two_arguments(argument, arg1, arg2); 1003 1004 if (subcmd == SCMD_POUR) { 1005 if (!*arg1) { /* No arguments */ 1006 send_to_char(ch, "From what do you want to pour?\r\n"); 1007 return; 1008 } 1009 if (!(from_obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying))) { 1010 send_to_char(ch, "You can't find it!\r\n"); 1011 return; 1012 } 1013 if (GET_OBJ_TYPE(from_obj) != ITEM_DRINKCON) { 1014 send_to_char(ch, "You can't pour from that!\r\n"); 1015 return; 1016 } 1017 } 1018 if (subcmd == SCMD_FILL) { 1019 if (!*arg1) { /* no arguments */ 1020 send_to_char(ch, "What do you want to fill? And what are you filling it from?\r\n"); 1021 return; 1022 } 1023 if (!(to_obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying))) { 1024 send_to_char(ch, "You can't find it!\r\n"); 1025 return; 1026 } 1027 if (GET_OBJ_TYPE(to_obj) != ITEM_DRINKCON) { 1028 act("You can't fill $p!", FALSE, ch, to_obj, 0, TO_CHAR); 1029 return; 1030 } 1031 if (!*arg2) { /* no 2nd argument */ 1032 act("What do you want to fill $p from?", FALSE, ch, to_obj, 0, TO_CHAR); 1033 return; 1034 } 1035 if (!(from_obj = get_obj_in_list_vis(ch, arg2, NULL, world[IN_ROOM(ch)].contents))) { 1036 send_to_char(ch, "There doesn't seem to be %s %s here.\r\n", AN(arg2), arg2); 1037 return; 1038 } 1039 if (GET_OBJ_TYPE(from_obj) != ITEM_FOUNTAIN) { 1040 act("You can't fill something from $p.", FALSE, ch, from_obj, 0, TO_CHAR); 1041 return; 1042 } 1043 } 1044 if (GET_OBJ_VAL(from_obj, 1) == 0) { 1045 act("The $p is empty.", FALSE, ch, from_obj, 0, TO_CHAR); 1046 return; 1047 } 1048 if (subcmd == SCMD_POUR) { /* pour */ 1049 if (!*arg2) { 1050 send_to_char(ch, "Where do you want it? Out or in what?\r\n"); 1051 return; 1052 } 1053 if (!str_cmp(arg2, "out")) { 1054 act("$n empties $p.", TRUE, ch, from_obj, 0, TO_ROOM); 1055 act("You empty $p.", FALSE, ch, from_obj, 0, TO_CHAR); 1056 1057 weight_change_object(from_obj, -GET_OBJ_VAL(from_obj, 1)); /* Empty */ 1058 1059 name_from_drinkcon(from_obj); 1060 GET_OBJ_VAL(from_obj, 1) = 0; 1061 GET_OBJ_VAL(from_obj, 2) = 0; 1062 GET_OBJ_VAL(from_obj, 3) = 0; 1063 1064 return; 1065 } 1066 if (!(to_obj = get_obj_in_list_vis(ch, arg2, NULL, ch->carrying))) { 1067 send_to_char(ch, "You can't find it!\r\n"); 1068 return; 1069 } 1070 if ((GET_OBJ_TYPE(to_obj) != ITEM_DRINKCON) && 1071 (GET_OBJ_TYPE(to_obj) != ITEM_FOUNTAIN)) { 1072 send_to_char(ch, "You can't pour anything into that.\r\n"); 1073 return; 1074 } 1075 } 1076 if (to_obj == from_obj) { 1077 send_to_char(ch, "A most unproductive effort.\r\n"); 1078 return; 1079 } 1080 if ((GET_OBJ_VAL(to_obj, 1) != 0) && 1081 (GET_OBJ_VAL(to_obj, 2) != GET_OBJ_VAL(from_obj, 2))) { 1082 send_to_char(ch, "There is already another liquid in it!\r\n"); 1083 return; 1084 } 1085 if (!(GET_OBJ_VAL(to_obj, 1) < GET_OBJ_VAL(to_obj, 0))) { 1086 send_to_char(ch, "There is no room for more.\r\n"); 1087 return; 1088 } 1089 if (subcmd == SCMD_POUR) 1090 send_to_char(ch, "You pour the %s into the %s.", drinks[GET_OBJ_VAL(from_obj, 2)], arg2); 1091 1092 if (subcmd == SCMD_FILL) { 1093 act("You gently fill $p from $P.", FALSE, ch, to_obj, from_obj, TO_CHAR); 1094 act("$n gently fills $p from $P.", TRUE, ch, to_obj, from_obj, TO_ROOM); 1095 } 1096 /* New alias */ 1097 if (GET_OBJ_VAL(to_obj, 1) == 0) 1098 name_to_drinkcon(to_obj, GET_OBJ_VAL(from_obj, 2)); 1099 1100 /* First same type liq. */ 1101 GET_OBJ_VAL(to_obj, 2) = GET_OBJ_VAL(from_obj, 2); 1102 1103 /* Then how much to pour */ 1104 GET_OBJ_VAL(from_obj, 1) -= (amount = 1105 (GET_OBJ_VAL(to_obj, 0) - GET_OBJ_VAL(to_obj, 1))); 1106 1107 GET_OBJ_VAL(to_obj, 1) = GET_OBJ_VAL(to_obj, 0); 1108 1109 if (GET_OBJ_VAL(from_obj, 1) < 0) { /* There was too little */ 1110 GET_OBJ_VAL(to_obj, 1) += GET_OBJ_VAL(from_obj, 1); 1111 amount += GET_OBJ_VAL(from_obj, 1); 1112 name_from_drinkcon(from_obj); 1113 GET_OBJ_VAL(from_obj, 1) = 0; 1114 GET_OBJ_VAL(from_obj, 2) = 0; 1115 GET_OBJ_VAL(from_obj, 3) = 0; 1116 } 1117 /* Then the poison boogie */ 1118 GET_OBJ_VAL(to_obj, 3) = 1119 (GET_OBJ_VAL(to_obj, 3) || GET_OBJ_VAL(from_obj, 3)); 1120 1121 /* And the weight boogie */ 1122 weight_change_object(from_obj, -amount); 1123 weight_change_object(to_obj, amount); /* Add weight */ 1124 } 1125 1126 1127 1128 void wear_message(struct char_data *ch, struct obj_data *obj, int where) 1129 { 1130 const char *wear_messages[][2] = { 1131 {"$n lights $p and holds it.", 1132 "You light $p and hold it."}, 1133 1134 {"$n slides $p on to $s right ring finger.", 1135 "You slide $p on to your right ring finger."}, 1136 1137 {"$n slides $p on to $s left ring finger.", 1138 "You slide $p on to your left ring finger."}, 1139 1140 {"$n wears $p around $s neck.", 1141 "You wear $p around your neck."}, 1142 1143 {"$n wears $p around $s neck.", 1144 "You wear $p around your neck."}, 1145 1146 {"$n wears $p on $s body.", 1147 "You wear $p on your body."}, 1148 1149 {"$n wears $p on $s head.", 1150 "You wear $p on your head."}, 1151 1152 {"$n puts $p on $s legs.", 1153 "You put $p on your legs."}, 1154 1155 {"$n wears $p on $s feet.", 1156 "You wear $p on your feet."}, 1157 1158 {"$n puts $p on $s hands.", 1159 "You put $p on your hands."}, 1160 1161 {"$n wears $p on $s arms.", 1162 "You wear $p on your arms."}, 1163 1164 {"$n straps $p around $s arm as a shield.", 1165 "You start to use $p as a shield."}, 1166 1167 {"$n wears $p about $s body.", 1168 "You wear $p around your body."}, 1169 1170 {"$n wears $p around $s waist.", 1171 "You wear $p around your waist."}, 1172 1173 {"$n puts $p on around $s right wrist.", 1174 "You put $p on around your right wrist."}, 1175 1176 {"$n puts $p on around $s left wrist.", 1177 "You put $p on around your left wrist."}, 1178 1179 {"$n wields $p.", 1180 "You wield $p."}, 1181 1182 {"$n grabs $p.", 1183 "You grab $p."} 1184 }; 1185 1186 act(wear_messages[where][0], TRUE, ch, obj, 0, TO_ROOM); 1187 act(wear_messages[where][1], FALSE, ch, obj, 0, TO_CHAR); 1188 } 1189 1190 1191 1192 void perform_wear(struct char_data *ch, struct obj_data *obj, int where) 1193 { 1194 /* 1195 * ITEM_WEAR_TAKE is used for objects that do not require special bits 1196 * to be put into that position (e.g. you can hold any object, not just 1197 * an object with a HOLD bit.) 1198 */ 1199 1200 int wear_bitvectors[] = { 1201 ITEM_WEAR_TAKE, ITEM_WEAR_FINGER, ITEM_WEAR_FINGER, ITEM_WEAR_NECK, 1202 ITEM_WEAR_NECK, ITEM_WEAR_BODY, ITEM_WEAR_HEAD, ITEM_WEAR_LEGS, 1203 ITEM_WEAR_FEET, ITEM_WEAR_HANDS, ITEM_WEAR_ARMS, ITEM_WEAR_SHIELD, 1204 ITEM_WEAR_ABOUT, ITEM_WEAR_WAIST, ITEM_WEAR_WRIST, ITEM_WEAR_WRIST, 1205 ITEM_WEAR_WIELD, ITEM_WEAR_TAKE 1206 }; 1207 1208 const char *already_wearing[] = { 1209 "You're already using a light.\r\n", 1210 "YOU SHOULD NEVER SEE THIS MESSAGE. PLEASE REPORT.\r\n", 1211 "You're already wearing something on both of your ring fingers.\r\n", 1212 "YOU SHOULD NEVER SEE THIS MESSAGE. PLEASE REPORT.\r\n", 1213 "You can't wear anything else around your neck.\r\n", 1214 "You're already wearing something on your body.\r\n", 1215 "You're already wearing something on your head.\r\n", 1216 "You're already wearing something on your legs.\r\n", 1217 "You're already wearing something on your feet.\r\n", 1218 "You're already wearing something on your hands.\r\n", 1219 "You're already wearing something on your arms.\r\n", 1220 "You're already using a shield.\r\n", 1221 "You're already wearing something about your body.\r\n", 1222 "You already have something around your waist.\r\n", 1223 "YOU SHOULD NEVER SEE THIS MESSAGE. PLEASE REPORT.\r\n", 1224 "You're already wearing something around both of your wrists.\r\n", 1225 "You're already wielding a weapon.\r\n", 1226 "You're already holding something.\r\n" 1227 }; 1228 1229 /* first, make sure that the wear position is valid. */ 1230 if (!CAN_WEAR(obj, wear_bitvectors[where])) { 1231 act("You can't wear $p there.", FALSE, ch, obj, 0, TO_CHAR); 1232 return; 1233 } 1234 /* for neck, finger, and wrist, try pos 2 if pos 1 is already full */ 1235 if ((where == WEAR_FINGER_R) || (where == WEAR_NECK_1) || (where == WEAR_WRIST_R)) 1236 if (GET_EQ(ch, where)) 1237 where++; 1238 1239 if (GET_EQ(ch, where)) { 1240 send_to_char(ch, "%s", already_wearing[where]); 1241 return; 1242 } 1243 wear_message(ch, obj, where); 1244 obj_from_char(obj); 1245 equip_char(ch, obj, where); 1246 } 1247 1248 1249 1250 int find_eq_pos(struct char_data *ch, struct obj_data *obj, char *arg) 1251 { 1252 int where = -1; 1253 1254 const char *keywords[] = { 1255 "!RESERVED!", 1256 "finger", 1257 "!RESERVED!", 1258 "neck", 1259 "!RESERVED!", 1260 "body", 1261 "head", 1262 "legs", 1263 "feet", 1264 "hands", 1265 "arms", 1266 "shield", 1267 "about", 1268 "waist", 1269 "wrist", 1270 "!RESERVED!", 1271 "!RESERVED!", 1272 "!RESERVED!", 1273 "\n" 1274 }; 1275 1276 if (!arg || !*arg) { 1277 if (CAN_WEAR(obj, ITEM_WEAR_FINGER)) where = WEAR_FINGER_R; 1278 if (CAN_WEAR(obj, ITEM_WEAR_NECK)) where = WEAR_NECK_1; 1279 if (CAN_WEAR(obj, ITEM_WEAR_BODY)) where = WEAR_BODY; 1280 if (CAN_WEAR(obj, ITEM_WEAR_HEAD)) where = WEAR_HEAD; 1281 if (CAN_WEAR(obj, ITEM_WEAR_LEGS)) where = WEAR_LEGS; 1282 if (CAN_WEAR(obj, ITEM_WEAR_FEET)) where = WEAR_FEET; 1283 if (CAN_WEAR(obj, ITEM_WEAR_HANDS)) where = WEAR_HANDS; 1284 if (CAN_WEAR(obj, ITEM_WEAR_ARMS)) where = WEAR_ARMS; 1285 if (CAN_WEAR(obj, ITEM_WEAR_SHIELD)) where = WEAR_SHIELD; 1286 if (CAN_WEAR(obj, ITEM_WEAR_ABOUT)) where = WEAR_ABOUT; 1287 if (CAN_WEAR(obj, ITEM_WEAR_WAIST)) where = WEAR_WAIST; 1288 if (CAN_WEAR(obj, ITEM_WEAR_WRIST)) where = WEAR_WRIST_R; 1289 } else if ((where = search_block(arg, keywords, FALSE)) < 0) 1290 send_to_char(ch, "'%s'? What part of your body is THAT?\r\n", arg); 1291 1292 return (where); 1293 } 1294 1295 1296 1297 ACMD(do_wear) 1298 { 1299 char arg1[MAX_INPUT_LENGTH]; 1300 char arg2[MAX_INPUT_LENGTH]; 1301 struct obj_data *obj, *next_obj; 1302 int where, dotmode, items_worn = 0; 1303 1304 two_arguments(argument, arg1, arg2); 1305 1306 if (!*arg1) { 1307 send_to_char(ch, "Wear what?\r\n"); 1308 return; 1309 } 1310 dotmode = find_all_dots(arg1); 1311 1312 if (*arg2 && (dotmode != FIND_INDIV)) { 1313 send_to_char(ch, "You can't specify the same body location for more than one item!\r\n"); 1314 return; 1315 } 1316 if (dotmode == FIND_ALL) { 1317 for (obj = ch->carrying; obj; obj = next_obj) { 1318 next_obj = obj->next_content; 1319 if (CAN_SEE_OBJ(ch, obj) && (where = find_eq_pos(ch, obj, 0)) >= 0) { 1320 items_worn++; 1321 perform_wear(ch, obj, where); 1322 } 1323 } 1324 if (!items_worn) 1325 send_to_char(ch, "You don't seem to have anything wearable.\r\n"); 1326 } else if (dotmode == FIND_ALLDOT) { 1327 if (!*arg1) { 1328 send_to_char(ch, "Wear all of what?\r\n"); 1329 return; 1330 } 1331 if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying))) 1332 send_to_char(ch, "You don't seem to have any %ss.\r\n", arg1); 1333 else 1334 while (obj) { 1335 next_obj = get_obj_in_list_vis(ch, arg1, NULL, obj->next_content); 1336 if ((where = find_eq_pos(ch, obj, 0)) >= 0) 1337 perform_wear(ch, obj, where); 1338 else 1339 act("You can't wear $p.", FALSE, ch, obj, 0, TO_CHAR); 1340 obj = next_obj; 1341 } 1342 } else { 1343 if (!(obj = get_obj_in_list_vis(ch, arg1, NULL, ch->carrying))) 1344 send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg1), arg1); 1345 else { 1346 if ((where = find_eq_pos(ch, obj, arg2)) >= 0) 1347 perform_wear(ch, obj, where); 1348 else if (!*arg2) 1349 act("You can't wear $p.", FALSE, ch, obj, 0, TO_CHAR); 1350 } 1351 } 1352 } 1353 1354 1355 1356 ACMD(do_wield) 1357 { 1358 char arg[MAX_INPUT_LENGTH]; 1359 struct obj_data *obj; 1360 1361 one_argument(argument, arg); 1362 1363 if (!*arg) 1364 send_to_char(ch, "Wield what?\r\n"); 1365 else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 1366 send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg); 1367 else { 1368 if (!CAN_WEAR(obj, ITEM_WEAR_WIELD)) 1369 send_to_char(ch, "You can't wield that.\r\n"); 1370 else if (GET_OBJ_WEIGHT(obj) > str_app[STRENGTH_APPLY_INDEX(ch)].wield_w) 1371 send_to_char(ch, "It's too heavy for you to use.\r\n"); 1372 else 1373 perform_wear(ch, obj, WEAR_WIELD); 1374 } 1375 } 1376 1377 1378 1379 ACMD(do_grab) 1380 { 1381 char arg[MAX_INPUT_LENGTH]; 1382 struct obj_data *obj; 1383 1384 one_argument(argument, arg); 1385 1386 if (!*arg) 1387 send_to_char(ch, "Hold what?\r\n"); 1388 else if (!(obj = get_obj_in_list_vis(ch, arg, NULL, ch->carrying))) 1389 send_to_char(ch, "You don't seem to have %s %s.\r\n", AN(arg), arg); 1390 else { 1391 if (GET_OBJ_TYPE(obj) == ITEM_LIGHT) 1392 perform_wear(ch, obj, WEAR_LIGHT); 1393 else { 1394 if (!CAN_WEAR(obj, ITEM_WEAR_HOLD) && GET_OBJ_TYPE(obj) != ITEM_WAND && 1395 GET_OBJ_TYPE(obj) != ITEM_STAFF && GET_OBJ_TYPE(obj) != ITEM_SCROLL && 1396 GET_OBJ_TYPE(obj) != ITEM_POTION) 1397 send_to_char(ch, "You can't hold that.\r\n"); 1398 else 1399 perform_wear(ch, obj, WEAR_HOLD); 1400 } 1401 } 1402 } 1403 1404 1405 1406 void perform_remove(struct char_data *ch, int pos) 1407 { 1408 struct obj_data *obj; 1409 1410 if (!(obj = GET_EQ(ch, pos))) 1411 log("SYSERR: perform_remove: bad pos %d passed.", pos); 1412 else if (OBJ_FLAGGED(obj, ITEM_NODROP)) 1413 act("You can't remove $p, it must be CURSED!", FALSE, ch, obj, 0, TO_CHAR); 1414 else if (IS_CARRYING_N(ch) >= CAN_CARRY_N(ch)) 1415 act("$p: you can't carry that many items!", FALSE, ch, obj, 0, TO_CHAR); 1416 else { 1417 obj_to_char(unequip_char(ch, pos), ch); 1418 act("You stop using $p.", FALSE, ch, obj, 0, TO_CHAR); 1419 act("$n stops using $p.", TRUE, ch, obj, 0, TO_ROOM); 1420 } 1421 } 1422 1423 1424 1425 ACMD(do_remove) 1426 { 1427 char arg[MAX_INPUT_LENGTH]; 1428 int i, dotmode, found; 1429 1430 one_argument(argument, arg); 1431 1432 if (!*arg) { 1433 send_to_char(ch, "Remove what?\r\n"); 1434 return; 1435 } 1436 dotmode = find_all_dots(arg); 1437 1438 if (dotmode == FIND_ALL) { 1439 found = 0; 1440 for (i = 0; i < NUM_WEARS; i++) 1441 if (GET_EQ(ch, i)) { 1442 perform_remove(ch, i); 1443 found = 1; 1444 } 1445 if (!found) 1446 send_to_char(ch, "You're not using anything.\r\n"); 1447 } else if (dotmode == FIND_ALLDOT) { 1448 if (!*arg) 1449 send_to_char(ch, "Remove all of what?\r\n"); 1450 else { 1451 found = 0; 1452 for (i = 0; i < NUM_WEARS; i++) 1453 if (GET_EQ(ch, i) && CAN_SEE_OBJ(ch, GET_EQ(ch, i)) && 1454 isname(arg, GET_EQ(ch, i)->name)) { 1455 perform_remove(ch, i); 1456 found = 1; 1457 } 1458 if (!found) 1459 send_to_char(ch, "You don't seem to be using any %ss.\r\n", arg); 1460 } 1461 } else { 1462 if ((i = get_obj_pos_in_equip_vis(ch, arg, NULL, ch->equipment)) < 0) 1463 send_to_char(ch, "You don't seem to be using %s %s.\r\n", AN(arg), arg); 1464 else 1465 perform_remove(ch, i); 1466 } 1467 }