1 | |
|
|
2 | /* |
|
|
3 | * static char *rcsid_c_object_c = |
|
|
4 | * "$Id: c_object.C,v 1.14 2006/09/10 15:59:57 root Exp $"; |
|
|
5 | */ |
|
|
6 | |
|
|
7 | /* |
1 | /* |
8 | CrossFire, A Multiplayer game for X-windows |
2 | CrossFire, A Multiplayer game for X-windows |
9 | |
3 | |
10 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
4 | Copyright (C) 2002 Mark Wedel & Crossfire Development Team |
11 | Copyright (C) 1992 Frank Tore Johansen |
5 | Copyright (C) 1992 Frank Tore Johansen |
… | |
… | |
22 | |
16 | |
23 | You should have received a copy of the GNU General Public License |
17 | You should have received a copy of the GNU General Public License |
24 | along with this program; if not, write to the Free Software |
18 | along with this program; if not, write to the Free Software |
25 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | |
20 | |
27 | The author can be reached via e-mail to crossfire-devel@real-time.com |
21 | The author can be reached via e-mail to <crossfire@schmorp.de> |
28 | |
22 | |
29 | Object (handling) commands |
23 | Object (handling) commands |
30 | */ |
24 | */ |
31 | |
25 | |
32 | #include <global.h> |
26 | #include <global.h> |
… | |
… | |
40 | |
34 | |
41 | /* |
35 | /* |
42 | * Object id parsing functions |
36 | * Object id parsing functions |
43 | */ |
37 | */ |
44 | |
38 | |
45 | #define OBLINKMALLOC(p) if(!((p)=(objectlink *)malloc(sizeof(objectlink))))\ |
|
|
46 | fatal(OUT_OF_MEMORY); |
|
|
47 | |
|
|
48 | #define ADD_ITEM(NEW,COUNT)\ |
39 | #define ADD_ITEM(NEW,COUNT)\ |
49 | if(!first) {\ |
40 | if(!first) {\ |
50 | OBLINKMALLOC(first);\ |
41 | first = new objectlink;\ |
51 | last=first;\ |
42 | last=first;\ |
52 | } else {\ |
43 | } else {\ |
53 | OBLINKMALLOC(last->next);\ |
44 | last->next = new objectlink;\ |
54 | last=last->next;\ |
45 | last=last->next;\ |
55 | }\ |
46 | }\ |
56 | last->next=NULL;\ |
47 | last->next=0;\ |
57 | last->ob=(NEW);\ |
48 | last->ob=(NEW);\ |
58 | last->id=(COUNT); |
49 | last->id=(COUNT); |
59 | |
50 | |
60 | /** |
51 | /** |
61 | * Search the inventory of 'pl' for what matches best with params. |
52 | * Search the inventory of 'pl' for what matches best with params. |
… | |
… | |
273 | if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && is_player_inv (tmp) != pl) |
264 | if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && is_player_inv (tmp) != pl) |
274 | { |
265 | { |
275 | new_draw_info (NDI_UNIQUE, 0, pl, "You are levitating, you can't reach the ground!"); |
266 | new_draw_info (NDI_UNIQUE, 0, pl, "You are levitating, you can't reach the ground!"); |
276 | return; |
267 | return; |
277 | } |
268 | } |
|
|
269 | |
278 | if (QUERY_FLAG (tmp, FLAG_NO_DROP)) |
270 | if (QUERY_FLAG (tmp, FLAG_NO_DROP)) |
279 | return; |
271 | return; |
|
|
272 | |
280 | if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) && !QUERY_FLAG (pl, FLAG_WAS_WIZ)) |
273 | if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) && !QUERY_FLAG (pl, FLAG_WAS_WIZ)) |
281 | { |
274 | { |
282 | new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff of smoke!"); |
275 | new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff of smoke!"); |
283 | new_draw_info (NDI_UNIQUE, 0, pl, "It must have been an illusion."); |
276 | new_draw_info (NDI_UNIQUE, 0, pl, "It must have been an illusion."); |
|
|
277 | |
284 | if (pl->type == PLAYER) |
278 | if (pl->type == PLAYER) |
285 | esrv_del_item (pl->contr, tmp->count); |
279 | esrv_del_item (pl->contr, tmp->count); |
286 | if (!QUERY_FLAG (tmp, FLAG_REMOVED)) |
280 | |
287 | remove_ob (tmp); |
281 | tmp->destroy (); |
288 | free_object (tmp); |
|
|
289 | return; |
282 | return; |
290 | } |
283 | } |
291 | |
284 | |
292 | if (nrof > tmp_nrof || nrof == 0) |
285 | if (nrof > tmp_nrof || nrof == 0) |
293 | nrof = tmp_nrof; |
286 | nrof = tmp_nrof; |
|
|
287 | |
294 | /* Figure out how much weight this object will add to the player */ |
288 | /* Figure out how much weight this object will add to the player */ |
295 | weight = tmp->weight * nrof; |
289 | weight = tmp->weight * nrof; |
296 | if (tmp->inv) |
290 | if (tmp->inv) |
297 | weight += tmp->carrying * (100 - tmp->stats.Str) / 100; |
291 | weight += tmp->carrying * (100 - tmp->stats.Str) / 100; |
|
|
292 | |
298 | if (pl->stats.Str <= MAX_STAT) |
293 | if (pl->stats.Str <= MAX_STAT) |
299 | effective_weight_limit = weight_limit[pl->stats.Str]; |
294 | effective_weight_limit = weight_limit[pl->stats.Str]; |
300 | else |
295 | else |
301 | effective_weight_limit = weight_limit[MAX_STAT]; |
296 | effective_weight_limit = weight_limit[MAX_STAT]; |
|
|
297 | |
302 | if ((pl->weight + pl->carrying + weight) > effective_weight_limit) |
298 | if ((pl->weight + pl->carrying + weight) > effective_weight_limit) |
303 | { |
299 | { |
304 | new_draw_info (0, 0, pl, "That item is too heavy for you to pick up."); |
300 | new_draw_info (0, 0, pl, "That item is too heavy for you to pick up."); |
305 | return; |
301 | return; |
306 | } |
302 | } |
|
|
303 | |
307 | if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) |
304 | if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) |
308 | SET_FLAG (tmp, FLAG_WAS_WIZ); |
305 | SET_FLAG (tmp, FLAG_WAS_WIZ); |
|
|
306 | |
309 | if (nrof != tmp_nrof) |
307 | if (nrof != tmp_nrof) |
310 | { |
308 | { |
311 | object *tmp2 = tmp; |
309 | object *tmp2 = tmp; |
312 | tag_t tmp2_tag = tmp2->count; |
|
|
313 | |
310 | |
314 | tmp = get_split_ob (tmp, nrof); |
311 | tmp = get_split_ob (tmp, nrof); |
315 | if (!tmp) |
312 | if (!tmp) |
316 | { |
313 | { |
317 | new_draw_info (NDI_UNIQUE, 0, pl, errmsg); |
314 | new_draw_info (NDI_UNIQUE, 0, pl, errmsg); |
318 | return; |
315 | return; |
319 | } |
316 | } |
|
|
317 | |
320 | /* Tell a client what happened rest of objects */ |
318 | /* Tell a client what happened rest of objects */ |
321 | if (pl->type == PLAYER) |
319 | if (pl->type == PLAYER) |
322 | { |
320 | { |
323 | if (was_destroyed (tmp2, tmp2_tag)) |
321 | if (tmp2->destroyed ()) |
324 | esrv_del_item (pl->contr, tmp2_tag); |
322 | esrv_del_item (pl->contr, tmp2->count); |
325 | else |
323 | else |
326 | esrv_send_item (pl, tmp2); |
324 | esrv_send_item (pl, tmp2); |
327 | } |
325 | } |
328 | } |
326 | } |
329 | else |
327 | else |
… | |
… | |
334 | */ |
332 | */ |
335 | if (!QUERY_FLAG (tmp, FLAG_REMOVED)) |
333 | if (!QUERY_FLAG (tmp, FLAG_REMOVED)) |
336 | { |
334 | { |
337 | if (tmp->env && pl->type == PLAYER) |
335 | if (tmp->env && pl->type == PLAYER) |
338 | esrv_del_item (pl->contr, tmp->count); |
336 | esrv_del_item (pl->contr, tmp->count); |
339 | remove_ob (tmp); /* Unlink it */ |
337 | tmp->remove (); /* Unlink it */ |
340 | } |
338 | } |
341 | } |
339 | } |
342 | if (QUERY_FLAG (tmp, FLAG_UNPAID)) |
340 | if (QUERY_FLAG (tmp, FLAG_UNPAID)) |
343 | (void) sprintf (buf, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP)); |
341 | (void) sprintf (buf, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP)); |
344 | else |
342 | else |
… | |
… | |
366 | /* Update the container the object was in */ |
364 | /* Update the container the object was in */ |
367 | if (env && env != pl && env != op) |
365 | if (env && env != pl && env != op) |
368 | esrv_update_item (UPD_WEIGHT, pl, env); |
366 | esrv_update_item (UPD_WEIGHT, pl, env); |
369 | } |
367 | } |
370 | |
368 | |
371 | |
369 | /* modified slightly to allow monsters use this -b.t. 5-31-95 */ |
372 | void |
370 | void |
373 | pick_up (object *op, object *alt) |
371 | pick_up (object *op, object *alt) |
374 | |
|
|
375 | /* modified slightly to allow monsters use this -b.t. 5-31-95 */ |
|
|
376 | { |
372 | { |
377 | int need_fix_tmp = 0; |
373 | int need_fix_tmp = 0; |
378 | object *tmp = NULL; |
374 | object *tmp = NULL; |
379 | mapstruct *tmp_map = NULL; |
375 | maptile *tmp_map = NULL; |
380 | int count; |
376 | int count; |
381 | tag_t tag; |
|
|
382 | |
377 | |
383 | /* Decide which object to pick. */ |
378 | /* Decide which object to pick. */ |
384 | if (alt) |
379 | if (alt) |
385 | { |
380 | { |
386 | if (!can_pick (op, alt)) |
381 | if (!can_pick (op, alt)) |
… | |
… | |
395 | if (op->below == NULL || !can_pick (op, op->below)) |
390 | if (op->below == NULL || !can_pick (op, op->below)) |
396 | { |
391 | { |
397 | new_draw_info (NDI_UNIQUE, 0, op, "There is nothing to pick up here."); |
392 | new_draw_info (NDI_UNIQUE, 0, op, "There is nothing to pick up here."); |
398 | goto leave; |
393 | goto leave; |
399 | } |
394 | } |
|
|
395 | |
400 | tmp = op->below; |
396 | tmp = op->below; |
401 | } |
397 | } |
402 | |
398 | |
403 | /* Try to catch it. */ |
399 | /* Try to catch it. */ |
404 | tmp_map = tmp->map; |
400 | tmp_map = tmp->map; |
… | |
… | |
437 | if (alt->type == CONTAINER && QUERY_FLAG (alt, FLAG_APPLIED) && sack_can_hold (NULL, alt, tmp, count)) |
433 | if (alt->type == CONTAINER && QUERY_FLAG (alt, FLAG_APPLIED) && sack_can_hold (NULL, alt, tmp, count)) |
438 | break; /* General container comes next */ |
434 | break; /* General container comes next */ |
439 | if (!alt) |
435 | if (!alt) |
440 | alt = op; /* No free containers */ |
436 | alt = op; /* No free containers */ |
441 | } |
437 | } |
|
|
438 | |
442 | if (tmp->env == alt) |
439 | if (tmp->env == alt) |
443 | { |
440 | { |
444 | /* here it could be possible to check rent, |
441 | /* here it could be possible to check rent, |
445 | * if someone wants to implement it |
442 | * if someone wants to implement it |
446 | */ |
443 | */ |
… | |
… | |
455 | { |
452 | { |
456 | new_draw_info (NDI_UNIQUE, 0, op, "This object cannot be put into containers!"); |
453 | new_draw_info (NDI_UNIQUE, 0, op, "This object cannot be put into containers!"); |
457 | goto leave; |
454 | goto leave; |
458 | } |
455 | } |
459 | |
456 | |
460 | tag = tmp->count; |
|
|
461 | pick_up_object (op, alt, tmp, count); |
457 | pick_up_object (op, alt, tmp, count); |
|
|
458 | |
462 | if (was_destroyed (tmp, tag) || tmp->env) |
459 | if (tmp->destroyed () || tmp->env) |
463 | need_fix_tmp = 0; |
460 | need_fix_tmp = 0; |
|
|
461 | |
464 | if (op->type == PLAYER) |
462 | if (op->type == PLAYER) |
465 | op->contr->count = 0; |
463 | op->contr->count = 0; |
|
|
464 | |
466 | goto leave; |
465 | goto leave; |
467 | |
466 | |
468 | leave: |
467 | leave: |
469 | if (need_fix_tmp) |
468 | if (need_fix_tmp) |
470 | fix_stopped_item (tmp, tmp_map, op); |
469 | fix_stopped_item (tmp, tmp_map, op); |
… | |
… | |
486 | else |
485 | else |
487 | { |
486 | { |
488 | tmp = op->above; |
487 | tmp = op->above; |
489 | if (tmp) |
488 | if (tmp) |
490 | while (tmp->above) |
489 | while (tmp->above) |
491 | { |
|
|
492 | tmp = tmp->above; |
490 | tmp = tmp->above; |
493 | } |
491 | |
494 | if (!tmp) |
492 | if (!tmp) |
495 | tmp = op->below; |
493 | tmp = op->below; |
496 | } |
494 | } |
497 | |
495 | |
498 | if (tmp == NULL) |
496 | if (tmp == NULL) |
… | |
… | |
560 | * so this function isn't named very good anymore. |
558 | * so this function isn't named very good anymore. |
561 | */ |
559 | */ |
562 | void |
560 | void |
563 | put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof) |
561 | put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof) |
564 | { |
562 | { |
565 | tag_t tmp_tag, tmp2_tag; |
|
|
566 | object *tmp2, *sack2; |
563 | object *tmp2, *sack2; |
567 | char buf[MAX_BUF]; |
564 | char buf[MAX_BUF]; |
568 | |
565 | |
569 | if (sack == tmp) |
566 | if (sack == tmp) |
570 | return; /* Can't put an object in itself */ |
567 | return; /* Can't put an object in itself */ |
|
|
568 | |
571 | if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) |
569 | if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) |
572 | { |
570 | { |
573 | new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack)); |
571 | new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack)); |
574 | return; |
572 | return; |
575 | } |
573 | } |
|
|
574 | |
576 | if (tmp->type == CONTAINER && tmp->inv) |
575 | if (tmp->type == CONTAINER && tmp->inv) |
577 | { |
576 | { |
578 | |
577 | |
579 | /* Eneq(@csd.uu.se): If the object to be dropped is a container |
578 | /* Eneq(@csd.uu.se): If the object to be dropped is a container |
580 | * we instead move the contents of that container into the active |
579 | * we instead move the contents of that container into the active |
581 | * container, this is only done if the object has something in it. |
580 | * container, this is only done if the object has something in it. |
582 | */ |
581 | */ |
583 | sack2 = tmp; |
582 | sack2 = tmp; |
584 | new_draw_info_format (NDI_UNIQUE, 0, op, "You move the items from %s into %s.", query_name (tmp), query_name (sack)); |
583 | new_draw_info_format (NDI_UNIQUE, 0, op, "You move the items from %s into %s.", query_name (tmp), query_name (sack)); |
|
|
584 | |
585 | for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) |
585 | for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) |
586 | { |
586 | { |
587 | tmp = tmp2->below; |
587 | tmp = tmp2->below; |
|
|
588 | |
588 | if ((sack->type == CONTAINER && sack_can_hold (op, op->container, tmp2, tmp2->nrof))) |
589 | if ((sack->type == CONTAINER && sack_can_hold (op, op->container, tmp2, tmp2->nrof))) |
589 | { |
590 | { |
590 | put_object_in_sack (op, sack, tmp2, 0); |
591 | put_object_in_sack (op, sack, tmp2, 0); |
591 | } |
592 | } |
592 | else |
593 | else |
… | |
… | |
594 | sprintf (buf, "Your %s fills up.", query_name (sack)); |
595 | sprintf (buf, "Your %s fills up.", query_name (sack)); |
595 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
596 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
596 | break; |
597 | break; |
597 | } |
598 | } |
598 | } |
599 | } |
|
|
600 | |
599 | esrv_update_item (UPD_WEIGHT, op, sack2); |
601 | esrv_update_item (UPD_WEIGHT, op, sack2); |
600 | return; |
602 | return; |
601 | } |
603 | } |
602 | |
604 | |
603 | /* Don't worry about this for containers - our caller should have |
605 | /* Don't worry about this for containers - our caller should have |
… | |
… | |
605 | */ |
607 | */ |
606 | if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof))) |
608 | if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof))) |
607 | return; |
609 | return; |
608 | |
610 | |
609 | if (QUERY_FLAG (tmp, FLAG_APPLIED)) |
611 | if (QUERY_FLAG (tmp, FLAG_APPLIED)) |
610 | { |
|
|
611 | if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) |
612 | if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) |
612 | return; |
613 | return; |
613 | } |
|
|
614 | |
614 | |
615 | /* we want to put some portion of the item into the container */ |
615 | /* we want to put some portion of the item into the container */ |
616 | if (nrof && tmp->nrof != nrof) |
616 | if (nrof && tmp->nrof != nrof) |
617 | { |
617 | { |
618 | object *tmp2 = tmp; |
618 | object *tmp2 = tmp; |
619 | |
619 | |
620 | tmp2_tag = tmp2->count; |
|
|
621 | tmp = get_split_ob (tmp, nrof); |
620 | tmp = get_split_ob (tmp, nrof); |
622 | |
621 | |
623 | if (!tmp) |
622 | if (!tmp) |
624 | { |
623 | { |
625 | new_draw_info (NDI_UNIQUE, 0, op, errmsg); |
624 | new_draw_info (NDI_UNIQUE, 0, op, errmsg); |
626 | return; |
625 | return; |
627 | } |
626 | } |
628 | /* Tell a client what happened other objects */ |
627 | /* Tell a client what happened other objects */ |
629 | if (was_destroyed (tmp2, tmp2_tag)) |
628 | if (tmp2->destroyed ()) |
630 | esrv_del_item (op->contr, tmp2_tag); |
629 | esrv_del_item (op->contr, tmp2->count); |
631 | else /* this can proably be replaced with an update */ |
630 | else /* this can proably be replaced with an update */ |
632 | esrv_send_item (op, tmp2); |
631 | esrv_send_item (op, tmp2); |
633 | } |
632 | } |
634 | else |
633 | else |
635 | remove_ob (tmp); |
634 | tmp->remove (); |
636 | |
635 | |
637 | new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack)); |
636 | new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack)); |
638 | tmp_tag = tmp->count; |
|
|
639 | tmp2 = insert_ob_in_ob (tmp, sack); |
637 | tmp2 = insert_ob_in_ob (tmp, sack); |
640 | fix_player (op); /* This is overkill, fix_player() is called somewhere */ |
638 | fix_player (op); /* This is overkill, fix_player() is called somewhere */ |
641 | /* in object.c */ |
639 | /* in object.c */ |
642 | |
640 | |
643 | /* If an object merged (and thus, different object), we need to |
641 | /* If an object merged (and thus, different object), we need to |
644 | * delete the original. |
642 | * delete the original. |
645 | */ |
643 | */ |
646 | if (tmp2 != tmp) |
644 | if (tmp2 != tmp) |
647 | esrv_del_item (op->contr, tmp_tag); |
645 | esrv_del_item (op->contr, tmp->count); |
648 | |
646 | |
649 | esrv_send_item (op, tmp2); |
647 | esrv_send_item (op, tmp2); |
650 | |
648 | |
651 | /* update the sacks weight */ |
649 | /* update the sacks weight */ |
652 | esrv_update_item (UPD_WEIGHT, op, sack); |
650 | esrv_update_item (UPD_WEIGHT, op, sack); |
… | |
… | |
669 | |
667 | |
670 | if (QUERY_FLAG (tmp, FLAG_APPLIED)) |
668 | if (QUERY_FLAG (tmp, FLAG_APPLIED)) |
671 | if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) |
669 | if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) |
672 | return; /* can't unapply it */ |
670 | return; /* can't unapply it */ |
673 | |
671 | |
674 | /* We are only dropping some of the items. We split the current objec |
672 | /* We are only dropping some of the items. We split the current object |
675 | * off |
673 | * off |
676 | */ |
674 | */ |
677 | if (nrof && tmp->nrof != nrof) |
675 | if (nrof && tmp->nrof != nrof) |
678 | { |
676 | { |
679 | object *tmp2 = tmp; |
677 | object *tmp2 = tmp; |
680 | tag_t tmp2_tag = tmp2->count; |
|
|
681 | |
678 | |
682 | tmp = get_split_ob (tmp, nrof); |
679 | tmp = get_split_ob (tmp, nrof); |
683 | if (!tmp) |
680 | if (!tmp) |
684 | { |
681 | { |
685 | new_draw_info (NDI_UNIQUE, 0, op, errmsg); |
682 | new_draw_info (NDI_UNIQUE, 0, op, errmsg); |
… | |
… | |
688 | /* Tell a client what happened rest of objects. tmp2 is now the |
685 | /* Tell a client what happened rest of objects. tmp2 is now the |
689 | * original object |
686 | * original object |
690 | */ |
687 | */ |
691 | if (op->type == PLAYER) |
688 | if (op->type == PLAYER) |
692 | { |
689 | { |
693 | if (was_destroyed (tmp2, tmp2_tag)) |
690 | if (tmp2->destroyed ()) |
694 | esrv_del_item (op->contr, tmp2_tag); |
691 | esrv_del_item (op->contr, tmp2->count); |
695 | else |
692 | else |
696 | esrv_send_item (op, tmp2); |
693 | esrv_send_item (op, tmp2); |
697 | } |
694 | } |
698 | } |
695 | } |
699 | else |
696 | else |
700 | remove_ob (tmp); |
697 | tmp->remove (); |
701 | |
698 | |
702 | if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op))) |
699 | if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op))) |
703 | return; |
700 | return; |
704 | |
701 | |
705 | if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) |
702 | if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) |
… | |
… | |
707 | sprintf (buf, "You drop the %s.", query_name (tmp)); |
704 | sprintf (buf, "You drop the %s.", query_name (tmp)); |
708 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
705 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
709 | new_draw_info (NDI_UNIQUE, 0, op, "The gods who lent it to you retrieves it."); |
706 | new_draw_info (NDI_UNIQUE, 0, op, "The gods who lent it to you retrieves it."); |
710 | if (op->type == PLAYER) |
707 | if (op->type == PLAYER) |
711 | esrv_del_item (op->contr, tmp->count); |
708 | esrv_del_item (op->contr, tmp->count); |
712 | free_object (tmp); |
709 | tmp->destroy (); |
713 | fix_player (op); |
710 | fix_player (op); |
714 | return; |
711 | return; |
715 | } |
712 | } |
716 | |
713 | |
717 | /* If SAVE_INTERVAL is commented out, we never want to save |
714 | /* If SAVE_INTERVAL is commented out, we never want to save |
… | |
… | |
773 | if (tmp->env && tmp->env->type != PLAYER) |
770 | if (tmp->env && tmp->env->type != PLAYER) |
774 | { |
771 | { |
775 | /* Just toss the object - probably shouldn't be hanging |
772 | /* Just toss the object - probably shouldn't be hanging |
776 | * around anyways |
773 | * around anyways |
777 | */ |
774 | */ |
778 | remove_ob (tmp); |
775 | tmp->remove (); |
779 | free_object (tmp); |
776 | tmp->destroy (); |
780 | return; |
777 | return; |
781 | } |
778 | } |
782 | else |
779 | else |
783 | { |
780 | { |
784 | while (tmp != NULL && tmp->invisible) |
781 | while (tmp != NULL && tmp->invisible) |
… | |
… | |
933 | nextinv = nextinv->below; |
930 | nextinv = nextinv->below; |
934 | if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && !QUERY_FLAG (curinv, FLAG_APPLIED)) |
931 | if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && !QUERY_FLAG (curinv, FLAG_APPLIED)) |
935 | { |
932 | { |
936 | switch (curinv->type) |
933 | switch (curinv->type) |
937 | { |
934 | { |
938 | case HORN: |
935 | case HORN: |
939 | case BOOK: |
936 | case BOOK: |
940 | case SPELLBOOK: |
937 | case SPELLBOOK: |
941 | case GIRDLE: |
938 | case GIRDLE: |
942 | case AMULET: |
939 | case AMULET: |
943 | case RING: |
940 | case RING: |
944 | case CLOAK: |
941 | case CLOAK: |
945 | case BOOTS: |
942 | case BOOTS: |
946 | case GLOVES: |
943 | case GLOVES: |
947 | case BRACERS: |
944 | case BRACERS: |
948 | case SCROLL: |
945 | case SCROLL: |
949 | case ARMOUR_IMPROVER: |
946 | case ARMOUR_IMPROVER: |
950 | case WEAPON_IMPROVER: |
947 | case WEAPON_IMPROVER: |
951 | case WAND: |
948 | case WAND: |
952 | case ROD: |
949 | case ROD: |
953 | case POTION: |
950 | case POTION: |
954 | drop (op, curinv); |
951 | drop (op, curinv); |
955 | curinv = nextinv; |
952 | curinv = nextinv; |
956 | break; |
953 | break; |
957 | default: |
954 | default: |
958 | curinv = nextinv; |
955 | curinv = nextinv; |
959 | break; |
956 | break; |
960 | } |
957 | } |
961 | } |
958 | } |
962 | curinv = nextinv; |
959 | curinv = nextinv; |
963 | } |
960 | } |
964 | } |
961 | } |
… | |
… | |
1044 | { |
1041 | { |
1045 | object *tmp; |
1042 | object *tmp; |
1046 | |
1043 | |
1047 | if (!op || !op->contr) |
1044 | if (!op || !op->contr) |
1048 | return NULL; |
1045 | return NULL; |
|
|
1046 | |
1049 | if (!op->contr->mark) |
1047 | if (!op->contr->mark) |
1050 | { |
1048 | { |
1051 | |
|
|
1052 | /* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/ |
1049 | /* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/ |
1053 | return NULL; |
1050 | return 0; |
1054 | } |
1051 | } |
|
|
1052 | |
1055 | /* This may seem like overkill, but we need to make sure that they |
1053 | /* This may seem like overkill, but we need to make sure that they |
1056 | * player hasn't dropped the item. We use count on the off chance that |
1054 | * player hasn't dropped the item. We use count on the off chance that |
1057 | * an item got reincarnated at some point. |
1055 | * an item got reincarnated at some point. |
1058 | */ |
1056 | */ |
1059 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1057 | for (tmp = op->inv; tmp; tmp = tmp->below) |
1060 | { |
1058 | { |
1061 | if (tmp->invisible) |
1059 | if (tmp->invisible) |
1062 | continue; |
1060 | continue; |
|
|
1061 | |
1063 | if (tmp == op->contr->mark) |
1062 | if (tmp == op->contr->mark) |
1064 | { |
1063 | { |
1065 | if (tmp->count == op->contr->mark_count) |
1064 | if (!tmp->destroyed ()) |
1066 | return tmp; |
1065 | return tmp; |
1067 | else |
1066 | else |
1068 | { |
1067 | { |
1069 | op->contr->mark = NULL; |
1068 | op->contr->mark = 0; |
1070 | op->contr->mark_count = 0; |
|
|
1071 | |
|
|
1072 | /* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/ |
1069 | /* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/ |
1073 | return NULL; |
1070 | return 0; |
1074 | } |
1071 | } |
1075 | } |
1072 | } |
1076 | } |
1073 | } |
|
|
1074 | |
1077 | return NULL; |
1075 | return 0; |
1078 | } |
1076 | } |
1079 | |
1077 | |
1080 | |
1078 | |
1081 | /* op should be a player, params is any params. |
1079 | /* op should be a player, params is any params. |
1082 | * If no params given, we print out the currently marked object. |
1080 | * If no params given, we print out the currently marked object. |
… | |
… | |
1085 | int |
1083 | int |
1086 | command_mark (object *op, char *params) |
1084 | command_mark (object *op, char *params) |
1087 | { |
1085 | { |
1088 | if (!op->contr) |
1086 | if (!op->contr) |
1089 | return 1; |
1087 | return 1; |
|
|
1088 | |
1090 | if (!params) |
1089 | if (!params) |
1091 | { |
1090 | { |
1092 | object *mark = find_marked_object (op); |
1091 | object *mark = find_marked_object (op); |
1093 | |
1092 | |
1094 | if (!mark) |
1093 | if (!mark) |
… | |
… | |
1106 | return 1; |
1105 | return 1; |
1107 | } |
1106 | } |
1108 | else |
1107 | else |
1109 | { |
1108 | { |
1110 | op->contr->mark = mark1; |
1109 | op->contr->mark = mark1; |
1111 | op->contr->mark_count = mark1->count; |
|
|
1112 | new_draw_info_format (NDI_UNIQUE, 0, op, "Marked item %s", query_name (mark1)); |
1110 | new_draw_info_format (NDI_UNIQUE, 0, op, "Marked item %s", query_name (mark1)); |
1113 | return 0; |
1111 | return 0; |
1114 | } |
1112 | } |
1115 | } |
1113 | } |
|
|
1114 | |
1116 | return 0; /*shouldnt get here */ |
1115 | return 0; /*shouldnt get here */ |
1117 | } |
1116 | } |
1118 | |
1117 | |
1119 | |
1118 | |
1120 | /* op is the player |
1119 | /* op is the player |
… | |
… | |
1139 | /* Anyone know why this used to use the clone value instead of the |
1138 | /* Anyone know why this used to use the clone value instead of the |
1140 | * maxhp field? This seems that it should give more accurate results. |
1139 | * maxhp field? This seems that it should give more accurate results. |
1141 | */ |
1140 | */ |
1142 | switch ((mon->stats.hp + 1) * 4 / (mon->stats.maxhp + 1)) |
1141 | switch ((mon->stats.hp + 1) * 4 / (mon->stats.maxhp + 1)) |
1143 | { /* From 1-4 */ |
1142 | { /* From 1-4 */ |
1144 | case 1: |
1143 | case 1: |
1145 | new_draw_info (NDI_UNIQUE, 0, op, "It is in a bad shape."); |
1144 | new_draw_info (NDI_UNIQUE, 0, op, "It is in a bad shape."); |
1146 | break; |
1145 | break; |
1147 | case 2: |
1146 | case 2: |
1148 | new_draw_info (NDI_UNIQUE, 0, op, "It is hurt."); |
1147 | new_draw_info (NDI_UNIQUE, 0, op, "It is hurt."); |
1149 | break; |
1148 | break; |
1150 | case 3: |
1149 | case 3: |
1151 | new_draw_info (NDI_UNIQUE, 0, op, "It is somewhat hurt."); |
1150 | new_draw_info (NDI_UNIQUE, 0, op, "It is somewhat hurt."); |
1152 | break; |
1151 | break; |
1153 | case 4: |
1152 | case 4: |
1154 | new_draw_info (NDI_UNIQUE, 0, op, "It is in excellent shape."); |
1153 | new_draw_info (NDI_UNIQUE, 0, op, "It is in excellent shape."); |
1155 | break; |
1154 | break; |
1156 | } |
1155 | } |
1157 | if (present_in_ob (POISONING, mon) != NULL) |
1156 | if (present_in_ob (POISONING, mon) != NULL) |
1158 | new_draw_info (NDI_UNIQUE, 0, op, "It looks very ill."); |
1157 | new_draw_info (NDI_UNIQUE, 0, op, "It looks very ill."); |
1159 | } |
1158 | } |
1160 | |
1159 | |
… | |
… | |
1170 | return ""; |
1169 | return ""; |
1171 | |
1170 | |
1172 | buf[0] = '\0'; |
1171 | buf[0] = '\0'; |
1173 | switch (tmp->type) |
1172 | switch (tmp->type) |
1174 | { |
1173 | { |
1175 | case RING: |
1174 | case RING: |
1176 | case SKILL: |
1175 | case SKILL: |
1177 | case WEAPON: |
1176 | case WEAPON: |
1178 | case ARMOUR: |
1177 | case ARMOUR: |
1179 | case BRACERS: |
1178 | case BRACERS: |
1180 | case HELMET: |
1179 | case HELMET: |
1181 | case SHIELD: |
1180 | case SHIELD: |
1182 | case BOOTS: |
1181 | case BOOTS: |
1183 | case GLOVES: |
1182 | case GLOVES: |
1184 | case AMULET: |
1183 | case AMULET: |
1185 | case GIRDLE: |
1184 | case GIRDLE: |
1186 | case BOW: |
1185 | case BOW: |
1187 | case ARROW: |
1186 | case ARROW: |
1188 | case CLOAK: |
1187 | case CLOAK: |
1189 | case FOOD: |
1188 | case FOOD: |
1190 | case DRINK: |
1189 | case DRINK: |
1191 | case FLESH: |
1190 | case FLESH: |
1192 | case SKILL_TOOL: |
1191 | case SKILL_TOOL: |
1193 | case POWER_CRYSTAL: |
1192 | case POWER_CRYSTAL: |
1194 | if (*(cp = describe_item (tmp, pl)) != '\0') |
1193 | if (*(cp = describe_item (tmp, pl)) != '\0') |
1195 | { |
1194 | { |
1196 | int len; |
1195 | int len; |
1197 | |
1196 | |
1198 | strncpy (buf, query_name (tmp), VERY_BIG_BUF - 1); |
1197 | assign (buf, query_name (tmp)); |
1199 | buf[VERY_BIG_BUF - 1] = 0; |
|
|
1200 | len = strlen (buf); |
1198 | len = strlen (buf); |
1201 | if (len < VERY_BIG_BUF - 5) |
1199 | if (len < VERY_BIG_BUF - 5) |
1202 | { |
1200 | { |
1203 | /* Since we know the length, we save a few cpu cycles by using |
1201 | /* Since we know the length, we save a few cpu cycles by using |
1204 | * it instead of calling strcat */ |
1202 | * it instead of calling strcat */ |
1205 | strcpy (buf + len, " "); |
1203 | strcpy (buf + len, " "); |
1206 | len++; |
1204 | len++; |
1207 | strncpy (buf + len, cp, VERY_BIG_BUF - len - 1); |
1205 | assign (buf + len, cp, VERY_BIG_BUF - len - 1); |
1208 | buf[VERY_BIG_BUF - 1] = 0; |
|
|
1209 | } |
1206 | } |
1210 | } |
1207 | } |
1211 | } |
1208 | } |
|
|
1209 | |
1212 | if (buf[0] == '\0') |
1210 | if (buf[0] == '\0') |
1213 | { |
1211 | assign (buf, query_name (tmp)); |
1214 | strncpy (buf, query_name (tmp), VERY_BIG_BUF - 1); |
|
|
1215 | buf[VERY_BIG_BUF - 1] = 0; |
|
|
1216 | } |
|
|
1217 | |
1212 | |
1218 | return buf; |
1213 | return buf; |
1219 | } |
1214 | } |
1220 | |
1215 | |
1221 | void |
1216 | void |
… | |
… | |
1243 | buf[0] = '\0'; |
1238 | buf[0] = '\0'; |
1244 | } |
1239 | } |
1245 | |
1240 | |
1246 | switch (tmp->type) |
1241 | switch (tmp->type) |
1247 | { |
1242 | { |
1248 | case SPELLBOOK: |
1243 | case SPELLBOOK: |
1249 | if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) && tmp->inv) |
1244 | if (QUERY_FLAG (tmp, FLAG_IDENTIFIED) && tmp->inv) |
1250 | { |
1245 | { |
1251 | sprintf (buf, "%s is a %s level %s spell", &tmp->inv->name, get_levelnumber (tmp->inv->level), &tmp->inv->skill); |
1246 | sprintf (buf, "%s is a %s level %s spell", &tmp->inv->name, get_levelnumber (tmp->inv->level), &tmp->inv->skill); |
1252 | } |
1247 | } |
1253 | break; |
1248 | break; |
1254 | |
1249 | |
1255 | case BOOK: |
1250 | case BOOK: |
1256 | if (tmp->msg != NULL) |
1251 | if (tmp->msg != NULL) |
1257 | strcpy (buf, "Something is written in it."); |
1252 | strcpy (buf, "Something is written in it."); |
1258 | break; |
1253 | break; |
1259 | |
1254 | |
1260 | case CONTAINER: |
1255 | case CONTAINER: |
1261 | if (tmp->race != NULL) |
1256 | if (tmp->race != NULL) |
1262 | { |
1257 | { |
1263 | if (tmp->weight_limit && tmp->stats.Str < 100) |
1258 | if (tmp->weight_limit && tmp->stats.Str < 100) |
1264 | sprintf (buf, "It can hold only %s and its weight limit is %.1f kg.", |
1259 | sprintf (buf, "It can hold only %s and its weight limit is %.1f kg.", |
1265 | &tmp->race, tmp->weight_limit / (10.0 * (100 - tmp->stats.Str))); |
1260 | &tmp->race, tmp->weight_limit / (10.0 * (100 - tmp->stats.Str))); |
1266 | else |
1261 | else |
1267 | sprintf (buf, "It can hold only %s.", &tmp->race); |
1262 | sprintf (buf, "It can hold only %s.", &tmp->race); |
1268 | } |
1263 | } |
1269 | else if (tmp->weight_limit && tmp->stats.Str < 100) |
1264 | else if (tmp->weight_limit && tmp->stats.Str < 100) |
1270 | sprintf (buf, "Its weight limit is %.1f kg.", tmp->weight_limit / (10.0 * (100 - tmp->stats.Str))); |
1265 | sprintf (buf, "Its weight limit is %.1f kg.", tmp->weight_limit / (10.0 * (100 - tmp->stats.Str))); |
1271 | break; |
1266 | break; |
1272 | |
1267 | |
1273 | case WAND: |
1268 | case WAND: |
1274 | if (QUERY_FLAG (tmp, FLAG_IDENTIFIED)) |
1269 | if (QUERY_FLAG (tmp, FLAG_IDENTIFIED)) |
1275 | sprintf (buf, "It has %d charges left.", tmp->stats.food); |
1270 | sprintf (buf, "It has %d charges left.", tmp->stats.food); |
1276 | break; |
1271 | break; |
1277 | } |
1272 | } |
1278 | |
1273 | |
1279 | if (buf[0] != '\0') |
1274 | if (buf[0] != '\0') |
1280 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
1275 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
1281 | |
1276 | |
… | |
… | |
1457 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d MAGICDEVICE", i & PU_MAGIC_DEVICE ? 1 : 0); |
1452 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d MAGICDEVICE", i & PU_MAGIC_DEVICE ? 1 : 0); |
1458 | |
1453 | |
1459 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d NOT CURSED", i & PU_NOT_CURSED ? 1 : 0); |
1454 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d NOT CURSED", i & PU_NOT_CURSED ? 1 : 0); |
1460 | |
1455 | |
1461 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d JEWELS", i & PU_JEWELS ? 1 : 0); |
1456 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d JEWELS", i & PU_JEWELS ? 1 : 0); |
|
|
1457 | new_draw_info_format (NDI_UNIQUE, 0, op, "%d FLESH", i & PU_FLESH ? 1 : 0); |
1462 | |
1458 | |
1463 | new_draw_info_format (NDI_UNIQUE, 0, op, ""); |
1459 | new_draw_info_format (NDI_UNIQUE, 0, op, ""); |
1464 | } |
1460 | } |
1465 | |
1461 | |
1466 | int |
1462 | int |
… | |
… | |
1468 | { |
1464 | { |
1469 | uint32 i; |
1465 | uint32 i; |
1470 | static const char *names[] = { |
1466 | static const char *names[] = { |
1471 | "debug", "inhibit", "stop", "food", "drink", "valuables", "bow", "arrow", "helmet", |
1467 | "debug", "inhibit", "stop", "food", "drink", "valuables", "bow", "arrow", "helmet", |
1472 | "shield", "armour", "boots", "gloves", "cloak", "key", "missile", "allweapon", |
1468 | "shield", "armour", "boots", "gloves", "cloak", "key", "missile", "allweapon", |
1473 | "magical", "potion", "spellbook", "skillscroll", "readables", "magicdevice", "notcursed", "jewels", NULL |
1469 | "magical", "potion", "spellbook", "skillscroll", "readables", "magicdevice", "notcursed", |
|
|
1470 | "jewels", "flesh", NULL |
1474 | }; |
1471 | }; |
1475 | static uint32 modes[] = { |
1472 | static uint32 modes[] = { |
1476 | PU_DEBUG, PU_INHIBIT, PU_STOP, PU_FOOD, PU_DRINK, PU_VALUABLES, PU_BOW, PU_ARROW, PU_HELMET, |
1473 | PU_DEBUG, PU_INHIBIT, PU_STOP, PU_FOOD, PU_DRINK, PU_VALUABLES, PU_BOW, PU_ARROW, PU_HELMET, |
1477 | PU_SHIELD, PU_ARMOUR, PU_BOOTS, PU_GLOVES, PU_CLOAK, PU_KEY, PU_MISSILEWEAPON, PU_ALLWEAPON, |
1474 | PU_SHIELD, PU_ARMOUR, PU_BOOTS, PU_GLOVES, PU_CLOAK, PU_KEY, PU_MISSILEWEAPON, PU_ALLWEAPON, |
1478 | PU_MAGICAL, PU_POTION, PU_SPELLBOOK, PU_SKILLSCROLL, PU_READABLES, PU_MAGIC_DEVICE, PU_NOT_CURSED, PU_JEWELS, 0 |
1475 | PU_MAGICAL, PU_POTION, PU_SPELLBOOK, PU_SKILLSCROLL, PU_READABLES, PU_MAGIC_DEVICE, PU_NOT_CURSED, |
|
|
1476 | PU_JEWELS, PU_FLESH, 0 |
1479 | }; |
1477 | }; |
1480 | |
1478 | |
1481 | if (!params) |
1479 | if (!params) |
1482 | { |
1480 | { |
1483 | /* if the new mode is used, just print the settings */ |
1481 | /* if the new mode is used, just print the settings */ |
… | |
… | |
1534 | void |
1532 | void |
1535 | set_pickup_mode (object *op, int i) |
1533 | set_pickup_mode (object *op, int i) |
1536 | { |
1534 | { |
1537 | switch (op->contr->mode = i) |
1535 | switch (op->contr->mode = i) |
1538 | { |
1536 | { |
1539 | case 0: |
1537 | case 0: |
1540 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Don't pick up."); |
1538 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Don't pick up."); |
1541 | break; |
1539 | break; |
1542 | case 1: |
1540 | case 1: |
1543 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item."); |
1541 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item."); |
1544 | break; |
1542 | break; |
1545 | case 2: |
1543 | case 2: |
1546 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item and stop."); |
1544 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item and stop."); |
1547 | break; |
1545 | break; |
1548 | case 3: |
1546 | case 3: |
1549 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Stop before picking up."); |
1547 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Stop before picking up."); |
1550 | break; |
1548 | break; |
1551 | case 4: |
1549 | case 4: |
1552 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items."); |
1550 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items."); |
1553 | break; |
1551 | break; |
1554 | case 5: |
1552 | case 5: |
1555 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items and stop."); |
1553 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items and stop."); |
1556 | break; |
1554 | break; |
1557 | case 6: |
1555 | case 6: |
1558 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all magic items."); |
1556 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all magic items."); |
1559 | break; |
1557 | break; |
1560 | case 7: |
1558 | case 7: |
1561 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all coins and gems"); |
1559 | new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all coins and gems"); |
1562 | break; |
1560 | break; |
1563 | } |
1561 | } |
1564 | } |
1562 | } |
1565 | |
1563 | |
1566 | int |
1564 | int |
1567 | command_search_items (object *op, char *params) |
1565 | command_search_items (object *op, char *params) |
… | |
… | |
1595 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
1593 | new_draw_info (NDI_UNIQUE, 0, op, buf); |
1596 | fix_player (op); |
1594 | fix_player (op); |
1597 | return 1; |
1595 | return 1; |
1598 | } |
1596 | } |
1599 | |
1597 | |
1600 | /* |
|
|
1601 | * Changing the custom name of an item |
|
|
1602 | * |
|
|
1603 | * Syntax is: rename <what object> to <new name> |
|
|
1604 | * if '<what object>' is omitted, marked object is used |
|
|
1605 | * if 'to <new name>' is omitted, custom name is cleared |
|
|
1606 | * |
|
|
1607 | * Names are considered for all purpose having a length <=127 (max length sent to client |
|
|
1608 | * by server) */ |
|
|
1609 | |
|
|
1610 | int |
|
|
1611 | command_rename_item (object *op, char *params) |
|
|
1612 | { |
|
|
1613 | char buf[VERY_BIG_BUF]; |
|
|
1614 | int itemnumber; |
|
|
1615 | object *item = NULL; |
|
|
1616 | char *closebrace; |
|
|
1617 | size_t counter; |
|
|
1618 | |
|
|
1619 | if (params) |
|
|
1620 | { |
|
|
1621 | /* Let's skip white spaces */ |
|
|
1622 | while (' ' == *params) |
|
|
1623 | params++; |
|
|
1624 | |
|
|
1625 | /* Checking the first part */ |
|
|
1626 | if ((itemnumber = atoi (params)) != 0) |
|
|
1627 | { |
|
|
1628 | for (item = op->inv; item && ((item->count != (tag_t) itemnumber) || item->invisible); item = item->below); |
|
|
1629 | if (!item) |
|
|
1630 | { |
|
|
1631 | new_draw_info (NDI_UNIQUE, 0, op, "Tried to rename an invalid item."); |
|
|
1632 | return 1; |
|
|
1633 | } |
|
|
1634 | while (isdigit (*params) || ' ' == *params) |
|
|
1635 | params++; |
|
|
1636 | } |
|
|
1637 | else if ('<' == *params) |
|
|
1638 | { |
|
|
1639 | /* Got old name, let's get it & find appropriate matching item */ |
|
|
1640 | closebrace = strchr (params, '>'); |
|
|
1641 | if (!closebrace) |
|
|
1642 | { |
|
|
1643 | new_draw_info (NDI_UNIQUE, 0, op, "Syntax error!"); |
|
|
1644 | return 1; |
|
|
1645 | } |
|
|
1646 | /* Sanity check for buffer overruns */ |
|
|
1647 | if ((closebrace - params) > 127) |
|
|
1648 | { |
|
|
1649 | new_draw_info (NDI_UNIQUE, 0, op, "Old name too long (up to 127 characters allowed)!"); |
|
|
1650 | return 1; |
|
|
1651 | } |
|
|
1652 | /* Copy the old name */ |
|
|
1653 | strncpy (buf, params + 1, closebrace - params - 1); |
|
|
1654 | buf[closebrace - params - 1] = '\0'; |
|
|
1655 | |
|
|
1656 | /* Find best matching item */ |
|
|
1657 | item = find_best_object_match (op, buf); |
|
|
1658 | if (!item) |
|
|
1659 | { |
|
|
1660 | new_draw_info (NDI_UNIQUE, 0, op, "Could not find a matching item to rename."); |
|
|
1661 | return 1; |
|
|
1662 | } |
|
|
1663 | |
|
|
1664 | /* Now need to move pointer to just after > */ |
|
|
1665 | params = closebrace + 1; |
|
|
1666 | while (' ' == *params) |
|
|
1667 | params++; |
|
|
1668 | |
|
|
1669 | } |
|
|
1670 | else |
|
|
1671 | { |
|
|
1672 | /* Use marked item */ |
|
|
1673 | item = find_marked_object (op); |
|
|
1674 | if (!item) |
|
|
1675 | { |
|
|
1676 | new_draw_info (NDI_UNIQUE, 0, op, "No marked item to rename."); |
|
|
1677 | return 1; |
|
|
1678 | } |
|
|
1679 | } |
|
|
1680 | |
|
|
1681 | /* Now let's find the new name */ |
|
|
1682 | if (!strncmp (params, "to ", 3)) |
|
|
1683 | { |
|
|
1684 | params += 3; |
|
|
1685 | while (' ' == *params) |
|
|
1686 | params++; |
|
|
1687 | if ('<' != *params) |
|
|
1688 | { |
|
|
1689 | new_draw_info (NDI_UNIQUE, 0, op, "Syntax error, expecting < at start of new name!"); |
|
|
1690 | return 1; |
|
|
1691 | } |
|
|
1692 | closebrace = strchr (params + 1, '>'); |
|
|
1693 | if (!closebrace) |
|
|
1694 | { |
|
|
1695 | new_draw_info (NDI_UNIQUE, 0, op, "Syntax error, expecting > at end of new name!"); |
|
|
1696 | return 1; |
|
|
1697 | } |
|
|
1698 | |
|
|
1699 | /* Sanity check for buffer overruns */ |
|
|
1700 | if ((closebrace - params) > 127) |
|
|
1701 | { |
|
|
1702 | new_draw_info (NDI_UNIQUE, 0, op, "New name too long (up to 127 characters allowed)!"); |
|
|
1703 | return 1; |
|
|
1704 | } |
|
|
1705 | |
|
|
1706 | /* Copy the new name */ |
|
|
1707 | strncpy (buf, params + 1, closebrace - params - 1); |
|
|
1708 | buf[closebrace - params - 1] = '\0'; |
|
|
1709 | |
|
|
1710 | /* Let's check it for weird characters */ |
|
|
1711 | for (counter = 0; counter < strlen (buf); counter++) |
|
|
1712 | { |
|
|
1713 | if (isalnum (buf[counter])) |
|
|
1714 | continue; |
|
|
1715 | if (' ' == buf[counter]) |
|
|
1716 | continue; |
|
|
1717 | if ('\'' == buf[counter]) |
|
|
1718 | continue; |
|
|
1719 | if ('+' == buf[counter]) |
|
|
1720 | continue; |
|
|
1721 | if ('_' == buf[counter]) |
|
|
1722 | continue; |
|
|
1723 | if ('-' == buf[counter]) |
|
|
1724 | continue; |
|
|
1725 | |
|
|
1726 | /* If we come here, then the name contains an invalid character... |
|
|
1727 | tell the player & exit */ |
|
|
1728 | new_draw_info (NDI_UNIQUE, 0, op, "Invalid new name!"); |
|
|
1729 | return 1; |
|
|
1730 | } |
|
|
1731 | |
|
|
1732 | } |
|
|
1733 | else |
|
|
1734 | { |
|
|
1735 | /* If param contains something, then syntax error... */ |
|
|
1736 | if (strlen (params)) |
|
|
1737 | { |
|
|
1738 | new_draw_info (NDI_UNIQUE, 0, op, "Syntax error, expected 'to <' after old name!"); |
|
|
1739 | return 1; |
|
|
1740 | } |
|
|
1741 | /* New name is empty */ |
|
|
1742 | buf[0] = '\0'; |
|
|
1743 | } |
|
|
1744 | } |
|
|
1745 | else |
|
|
1746 | { |
|
|
1747 | /* Last case: params==NULL */ |
|
|
1748 | item = find_marked_object (op); |
|
|
1749 | if (!item) |
|
|
1750 | { |
|
|
1751 | new_draw_info (NDI_UNIQUE, 0, op, "No marked item to rename."); |
|
|
1752 | return 1; |
|
|
1753 | } |
|
|
1754 | buf[0] = '\0'; |
|
|
1755 | } |
|
|
1756 | |
|
|
1757 | if (QUERY_FLAG (item, FLAG_UNPAID)) |
|
|
1758 | { |
|
|
1759 | new_draw_info (NDI_UNIQUE, 0, op, "You can't rename an unpaid item! You should pay for it first."); |
|
|
1760 | return 1; |
|
|
1761 | } |
|
|
1762 | |
|
|
1763 | /* Coming here, everything is fine... */ |
|
|
1764 | if (!strlen (buf)) |
|
|
1765 | { |
|
|
1766 | /* Clear custom name */ |
|
|
1767 | if (item->custom_name) |
|
|
1768 | { |
|
|
1769 | item->custom_name = 0; |
|
|
1770 | |
|
|
1771 | new_draw_info_format (NDI_UNIQUE, 0, op, "You stop calling your %s with weird names.", |
|
|
1772 | query_base_name (item, item->nrof > 1 ? 1 : 0)); |
|
|
1773 | esrv_update_item (UPD_NAME, op, item); |
|
|
1774 | } |
|
|
1775 | else |
|
|
1776 | { |
|
|
1777 | new_draw_info (NDI_UNIQUE, 0, op, "This item has no custom name."); |
|
|
1778 | } |
|
|
1779 | } |
|
|
1780 | else |
|
|
1781 | { |
|
|
1782 | /* Set custom name */ |
|
|
1783 | item->custom_name = buf; |
|
|
1784 | |
|
|
1785 | new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s will now be called %s.", query_base_name (item, item->nrof > 1 ? 1 : 0), buf); |
|
|
1786 | esrv_update_item (UPD_NAME, op, item); |
|
|
1787 | } |
|
|
1788 | |
|
|
1789 | return 1; |
|
|
1790 | } |
|
|