ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_object.C
(Generate patch)

Comparing deliantra/server/server/c_object.C (file contents):
Revision 1.80 by elmex, Sun Oct 5 12:40:21 2008 UTC vs.
Revision 1.110 by root, Fri Mar 26 00:59:22 2010 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * it under the terms of the GNU General Public License as published by 9 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
20 * 21 *
21 * The authors can be reached via e-mail to <support@deliantra.net> 22 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 23 */
23 24
24/* 25/*
25 * Object (handling) commands 26 * Object (handling) commands
26 */ 27 */
27 28
28#include <global.h> 29#include <global.h>
29#include <loader.h>
30#include <skills.h> 30#include <skills.h>
31#include <sproto.h> 31#include <sproto.h>
32#include <living.h> 32#include <living.h>
33#include <math.h>
34 33
35/* 34/*
36 * Object id parsing functions 35 * Object id parsing functions
37 */ 36 */
38 37
133 { 132 {
134 new_draw_info (NDI_UNIQUE, 0, pl, "Usage: ready_skill <skill name>"); 133 new_draw_info (NDI_UNIQUE, 0, pl, "Usage: ready_skill <skill name>");
135 return 0; 134 return 0;
136 } 135 }
137 136
138 skill = find_skill_by_name (pl, params); 137 skill = find_skill_by_name_fuzzy (pl, params);
139 138
140 if (!skill) 139 if (!skill)
141 { 140 {
142 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no knowledge of the skill %s", params); 141 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no knowledge of the skill %s", params);
143 return 0; 142 return 0;
144 } 143 }
145 144
146 pl->change_skill (0); 145 pl->change_skill (0);
147 apply_special (pl, skill, AP_APPLY); 146 apply_special (pl, skill, AP_APPLY);
148 return 1; 147 return 1;
149}
150
151/* These functions (command_search, command_disarm) are really just wrappers for
152 * things like 'use_skill ...'). In fact, they should really be obsoleted
153 * and replaced with those.
154 */
155int
156command_search (object *op, char *params)
157{
158 return use_skill (op, skill_names[SK_FIND_TRAPS]);
159}
160
161int
162command_disarm (object *op, char *params)
163{
164 return use_skill (op, skill_names[SK_DISARM_TRAPS]);
165} 148}
166 149
167/* A little special because we do want to pass the full params along 150/* A little special because we do want to pass the full params along
168 * as it includes the object to throw. 151 * as it includes the object to throw.
169 */ 152 */
241 return 0; 224 return 0;
242 } 225 }
243 226
244 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type))) 227 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type)))
245 { 228 {
246 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can put only %s into the %s.", &sack->race, query_name (sack)); 229 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can only put objects of type '%s' into the %s.", &sack->race, query_name (sack));
247 return 0; 230 return 0;
248 } 231 }
249 232
250 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying) 233 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying)
251 { 234 {
377 count = tmp->nrof; 360 count = tmp->nrof;
378 361
379 /* container is open, so use it */ 362 /* container is open, so use it */
380 if (tmp->flag [FLAG_STARTEQUIP]) 363 if (tmp->flag [FLAG_STARTEQUIP])
381 alt = op; 364 alt = op;
382 else if (op->container) 365 else if ((alt = op->container_ ()))
383 { 366 {
384 alt = op->container;
385 if (alt != tmp->env && !sack_can_hold (op, alt, tmp, count)) 367 if (alt != tmp->env && !sack_can_hold (op, alt, tmp, count))
386 goto leave; 368 goto leave;
387 } 369 }
388 else 370 else
389 { /* non container pickup */ 371 { /* non container pickup */
443int 425int
444command_take (object *op, char *params) 426command_take (object *op, char *params)
445{ 427{
446 object *tmp, *next; 428 object *tmp, *next;
447 429
448 if (op->container) 430 if (op->container_ ())
449 tmp = op->container->inv; 431 tmp = op->container_ ()->inv;
450 else 432 else
451 { 433 {
452 tmp = op->above; 434 tmp = op->above;
453 if (tmp) 435 if (tmp)
454 while (tmp->above) 436 while (tmp->above)
466 448
467 /* Makes processing easier */ 449 /* Makes processing easier */
468 if (params && *params == '\0') 450 if (params && *params == '\0')
469 params = 0; 451 params = 0;
470 452
471 int cnt = MAX_ITEM_PER_DROP; 453 int cnt = MAX_ITEM_PER_ACTION;
472 454
473 while (tmp) 455 while (tmp)
474 { 456 {
475 next = tmp->below; 457 next = tmp->below;
476 458
520 502
521 return 0; 503 return 0;
522} 504}
523 505
524/* 506/*
525 * This function was part of drop, now is own function. 507 * This function was part of drop, now is own function.
526 * Player 'op' tries to put object 'tmp' into sack 'sack', 508 * Player 'op' tries to put object 'tmp' into sack 'sack',
527 * if nrof is non zero, then nrof objects is tried to put into sack. 509 * if nrof is non zero, then nrof objects is tried to put into sack.
510 *
528 * Note that the 'sack' in question can now be a transport, 511 * Note that the 'sack' in question can now be a transport,
529 * so this function isn't named very good anymore. 512 * so this function isn't named very good anymore.
530 */ 513 */
531void 514void
532put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof) 515put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof)
535 char buf[MAX_BUF]; 518 char buf[MAX_BUF];
536 519
537 if (sack == tmp) 520 if (sack == tmp)
538 return; /* Can't put an object in itself */ 521 return; /* Can't put an object in itself */
539 522
540 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 523 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_DROP))
541 { 524 {
542 new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack)); 525 new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack));
543 return; 526 return;
544 } 527 }
545 528
554 537
555 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) 538 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp)
556 { 539 {
557 tmp = tmp2->below; 540 tmp = tmp2->below;
558 541
559 if ((sack->type == CONTAINER && sack_can_hold (op, op->container, tmp2, tmp2->nrof))) 542 if ((sack->type == CONTAINER && sack_can_hold (op, op->container_ (), tmp2, tmp2->nrof)))
560 put_object_in_sack (op, sack, tmp2, 0); 543 put_object_in_sack (op, sack, tmp2, 0);
561 else 544 else
562 { 545 {
563 sprintf (buf, "Your %s fills up.", query_name (sack)); 546 sprintf (buf, "Your %s fills up.", query_name (sack));
564 new_draw_info (NDI_UNIQUE, 0, op, buf); 547 new_draw_info (NDI_UNIQUE, 0, op, buf);
585 568
586 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack)); 569 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack));
587 sack->insert (tmp); 570 sack->insert (tmp);
588} 571}
589 572
573/* In contrast to drop_object (op, tmp, nrof) above this function takes the
574 * already split off object, and feeds it to the event handlers and does
575 * other magic with it.
576 *
577 * <droppper> is the object that dropped this object and <obj> is the
578 * object that was dropped.
579 *
580 * Make sure to check what happened with <obj> after this function returns!
581 * Otherwise you may leak this object.
582 */
583void
584drop_object (object *dropper, object *obj)
585{
586 if (INVOKE_OBJECT (DROP, obj, ARG_OBJECT (dropper)))
587 return;
588
589 if (obj->destroyed () || obj->is_inserted ())
590 return;
591
592 if (QUERY_FLAG (obj, FLAG_STARTEQUIP))
593 {
594 dropper->statusmsg (format ("You drop the %s.", query_name (obj)));
595 dropper->statusmsg ("The god who lent it to you retrieves it.");
596
597 obj->destroy ();
598 dropper->update_stats ();
599 return;
600 }
601
602 for (object *floor = GET_MAP_OB (dropper->map, dropper->x, dropper->y);
603 floor;
604 floor = floor->above)
605 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (obj), ARG_OBJECT (dropper)))
606 return;
607
608 if (obj->destroyed () || obj->is_inserted ())
609 return;
610
611 if (is_in_shop (dropper) && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY)
612 if (!sell_item (obj, dropper))
613 return;
614
615 if (!obj->can_drop_at (dropper->map, dropper->x, dropper->y, dropper))
616 return;
617
618 /* If nothing special happened with this object, the default action is to
619 * insert it below the dropper:
620 */
621
622 obj->x = dropper->x;
623 obj->y = dropper->y;
624
625 insert_ob_in_map (obj, dropper->map, dropper, INS_BELOW_ORIGINATOR);
626}
627
590/* 628/*
591 * This function was part of drop, now is own function. 629 * This function was part of drop, now is own function.
592 * Player 'op' tries to drop object 'tmp', if tmp is non zero, then 630 * Player 'op' tries to drop object 'tmp', if tmp is non zero, then
593 * nrof objects is tried to dropped. 631 * nrof objects are tried to drop.
594 * This is used when dropping objects onto the floor. 632 * This is used when dropping objects onto the floor.
595 */ 633 */
596void 634void
597drop_object (object *op, object *tmp, uint32 nrof) 635drop_object (object *op, object *tmp, uint32 nrof)
598{ 636{
600 return; 638 return;
601 639
602 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 640 if (QUERY_FLAG (tmp, FLAG_APPLIED))
603 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 641 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
604 return; /* can't unapply it */ 642 return; /* can't unapply it */
605
606 //fprintf (stderr, "ui, on space is %ld\n", op->ms ().volume ());//D
607 643
608 /* We are only dropping some of the items. We split the current object 644 /* We are only dropping some of the items. We split the current object
609 * off 645 * off
610 */ 646 */
611 if (!can_split (op, tmp, nrof)) 647 if (!can_split (op, tmp, nrof))
612 return; 648 return;
613 649
614 if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op))) 650 drop_object (op, tmp);
615 return;
616 651
617 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 652 if (!tmp->destroyed () && !tmp->is_inserted ())
618 {
619 op->statusmsg (format ("You drop the %s.", query_name (tmp)));
620 op->statusmsg ("The god who lent it to you retrieves it.");
621
622 tmp->destroy ();
623 op->update_stats ();
624 return;
625 } 653 {
626 654 // if nothing happened with the object we give it back
627 /* Call this before we update the various windows/players. At least
628 * that we, we know the weight is correct.
629 */
630 // 2007-11-26: moved op->update_stats away and calling it later after
631 // all items of a drop command have been processed.
632
633 for (object *floor = GET_MAP_OB (op->map, op->x, op->y); floor; floor = floor->above)
634 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op)))
635 return;
636
637 if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY)
638 {
639 if (!sell_item (tmp, op))
640 {
641 // if we can't sell it we don't drop it, so give it back to the seller
642 op->insert (tmp); 655 op->insert (tmp);
643 return;
644 }
645 } 656 }
646
647 tmp->x = op->x;
648 tmp->y = op->y;
649
650 insert_ob_in_map (tmp, op->map, op, INS_BELOW_ORIGINATOR);
651} 657}
652 658
653void 659void
654drop (object *op, object *tmp) 660drop (object *op, object *tmp)
655{ 661{
668 */ 674 */
669 tmp->destroy (); 675 tmp->destroy ();
670 return; 676 return;
671 } 677 }
672 else 678 else
673 {
674 while (tmp && tmp->invisible) 679 while (tmp && tmp->invisible)
675 tmp = tmp->below; 680 tmp = tmp->below;
676 }
677 } 681 }
678 682
679 if (tmp == NULL) 683 if (!tmp)
680 { 684 {
681 new_draw_info (NDI_UNIQUE, 0, op, "You don't have anything to drop."); 685 new_draw_info (NDI_UNIQUE, 0, op, "You don't have anything to drop.");
682 return; 686 return;
683 } 687 }
684 688
698 } 702 }
699 703
700 if (op->type == PLAYER && op->contr->last_used == tmp) 704 if (op->type == PLAYER && op->contr->last_used == tmp)
701 op->contr->last_used = tmp->below ? tmp->below 705 op->contr->last_used = tmp->below ? tmp->below
702 : tmp->above ? tmp->above 706 : tmp->above ? tmp->above
703 : 0; 707 : (object *)0;
704 708
705 if (op->container) 709 if (op->container_ ())
706 { 710 {
707 if (op->type == PLAYER) 711 if (op->type == PLAYER)
708 put_object_in_sack (op, op->container, tmp, op->contr->count); 712 put_object_in_sack (op, op->container_ (), tmp, op->contr->count);
709 else 713 else
710 put_object_in_sack (op, op->container, tmp, 0); 714 put_object_in_sack (op, op->container_ (), tmp, 0);
711 } 715 }
712 else 716 else
713 { 717 {
714 if (op->type == PLAYER) 718 if (op->type == PLAYER)
715 drop_object (op, tmp, op->contr->count); 719 drop_object (op, tmp, op->contr->count);
742 /* 746 /*
743 Care must be taken that the next item pointer is not to money as 747 Care must be taken that the next item pointer is not to money as
744 the drop() routine will do unknown things to it when dropping 748 the drop() routine will do unknown things to it when dropping
745 in a shop. --Tero.Pelander@utu.fi 749 in a shop. --Tero.Pelander@utu.fi
746 */ 750 */
747
748 int cnt = MAX_ITEM_PER_DROP; 751 int cnt = MAX_ITEM_PER_ACTION;
749 752
750 if (!params) 753 if (!params)
751 { 754 {
752 while (curinv) 755 while (curinv)
753 { 756 {
754 nextinv = curinv->below; 757 nextinv = curinv->below;
755 758
756 while (nextinv && nextinv->type == MONEY) 759 while (nextinv && nextinv->type == MONEY)
757 nextinv = nextinv->below; 760 nextinv = nextinv->below;
758 761
759 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && curinv->type != MONEY && 762 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED)
760 curinv->type != FOOD && curinv->type != KEY && 763 && curinv->type != MONEY
761 curinv->type != SPECIAL_KEY && curinv->type != GEM && 764 && curinv->type != FOOD
765 && curinv->type != KEY
766 && curinv->type != SPECIAL_KEY
767 && curinv->type != GEM
768 && !curinv->invisible
762 !curinv->invisible && (curinv->type != CONTAINER || op->container != curinv)) 769 && (curinv->type != CONTAINER || op->container_ () != curinv))
763 { 770 {
764 drop (op, curinv); 771 drop (op, curinv);
765 if (--cnt <= 0) break; 772 if (--cnt <= 0) break;
766 } 773 }
767 774
853 860
854/* draw_look(op);*/ 861/* draw_look(op);*/
855 return 0; 862 return 0;
856} 863}
857 864
865
866/* This function tries to drop all objects in the <objs> vector.
867 * <dropper> is the object that wants to drop them.
868 * <cnt> can be a 0 pointer or a pointer to the maximum number of
869 * drop operations to perform.
870 *
871 * Returns true if at least one item was dropped.
872 */
873static bool
874drop_vector (object *dropper, vector<object *> &objs, int *cnt)
875{
876 vector<object *>::iterator i;
877
878 bool did_one = false;
879
880 for (i = objs.begin (); i != objs.end (); i++)
881 {
882 drop (dropper, *i);
883 if (cnt && --*cnt <= 0) break;
884 did_one = true;
885 }
886
887 return did_one;
888}
889
858/* Object op wants to drop object(s) params. params can be a 890/* Object op wants to drop object(s) params. params can be a
859 * comma seperated list. 891 * comma seperated list.
860 */ 892 */
861int 893int
862command_drop (object *op, char *params) 894command_drop (object *op, char *params)
869 new_draw_info (NDI_UNIQUE, 0, op, "Drop what?"); 901 new_draw_info (NDI_UNIQUE, 0, op, "Drop what?");
870 return 0; 902 return 0;
871 } 903 }
872 else 904 else
873 { 905 {
874 int cnt = MAX_ITEM_PER_DROP; 906 vector<object *> matched_objs;
875 907
876 for (tmp = op->inv; tmp; tmp = next) 908 for (tmp = op->inv; tmp; tmp = next)
877 { 909 {
878 next = tmp->below; 910 next = tmp->below;
879 if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) 911 if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible)
880 continue; 912 continue;
881 913
882 if (item_matched_string (op, tmp, params)) 914 if (item_matched_string (op, tmp, params))
883 { 915 matched_objs.push_back (tmp);
884 drop (op, tmp);
885 if (--cnt <= 0) break;
886 did_one = 1;
887 } 916 }
888 }
889 917
890 if (!did_one) 918 int cnt = MAX_ITEM_PER_ACTION;
919
920 if (!drop_vector (op, matched_objs, &cnt))
891 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); 921 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop.");
892 922
893 if (cnt <= 0) 923 if (cnt <= 0)
894 op->failmsg ("Only dropped some items, can't drop that many items at once."); 924 op->failmsg ("Only dropped some items, can't drop that many items at once.");
895 } 925 }
1025} 1055}
1026 1056
1027std::string 1057std::string
1028object::long_desc (object *who) 1058object::long_desc (object *who)
1029{ 1059{
1030 std::string buf (query_name (this)); 1060 std::string buf (query_name ());
1031 1061
1032 switch (type) 1062 switch (type)
1033 { 1063 {
1034 case RING: 1064 case RING:
1035 case SKILL: 1065 case SKILL:
1047 case CLOAK: 1077 case CLOAK:
1048 case FOOD: 1078 case FOOD:
1049 case DRINK: 1079 case DRINK:
1050 case FLESH: 1080 case FLESH:
1051 case SKILL_TOOL: 1081 case SKILL_TOOL:
1082 case LAMP:
1052 case POWER_CRYSTAL: 1083 case POWER_CRYSTAL:
1053 { 1084 {
1054 const char *cp = ::describe_item (this, who); 1085 const char *cp = ::describe_item (this, who);
1055 1086
1056 if (*cp) 1087 if (*cp)
1071examine_monster (object *op, object *tmp) 1102examine_monster (object *op, object *tmp)
1072{ 1103{
1073 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ()); 1104 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ());
1074} 1105}
1075 1106
1107static void
1108describe_dump_object (dynbuf &buf, object *ob)
1109{
1110 char *txt = dump_object (ob);
1111 for (char *p = txt; *p; ++p) if (*p == '\n') *p = '\r';
1112 buf << "\n" << txt << "\n";
1113
1114 if (!ob->is_arch ())
1115 describe_dump_object (buf, ob->arch);
1116}
1117
1076std::string 1118std::string
1077object::describe (object *who) 1119object::describe (object *who)
1078{ 1120{
1079 dynbuf_text buf (1024, 1024); 1121 dynbuf_text buf (1024, 1024);
1080 1122
1085 1127
1086 switch (type) 1128 switch (type)
1087 { 1129 {
1088 case SPELLBOOK: 1130 case SPELLBOOK:
1089 if (flag [FLAG_IDENTIFIED] && inv) 1131 if (flag [FLAG_IDENTIFIED] && inv)
1090 buf.printf ("%s is a %s %s spell.\r", &inv->name, get_levelnumber (inv->level), &inv->skill); 1132 buf.printf ("%s is a level %s %s spell.\r", &inv->name, get_levelnumber (inv->level), &inv->skill);
1091 break; 1133 break;
1092 1134
1093 case BOOK: 1135 case BOOK:
1094 if (msg) 1136 if (msg)
1095 buf << "Something is written in it.\r"; 1137 buf << "Something is written in it.\r";
1112 if (flag [FLAG_IDENTIFIED]) 1154 if (flag [FLAG_IDENTIFIED])
1113 buf.printf ("It has %d charges left.\r", stats.food); 1155 buf.printf ("It has %d charges left.\r", stats.food);
1114 break; 1156 break;
1115 } 1157 }
1116 1158
1117 if (materialname && !msg) 1159 if (material != MATERIAL_NULL && !msg)
1118 buf.printf ("It is made of: %s.\r", &materialname); 1160 buf << (nrof > 1 ? "They are made of " : "It is made of ")
1161 << material->description
1162 << ".\r";
1119 1163
1120 if (who) 1164 if (who)
1121 /* Where to wear this item */ 1165 /* Where to wear this item */
1122 for (int i = 0; i < NUM_BODY_LOCATIONS; i++) 1166 for (int i = 0; i < NUM_BODY_LOCATIONS; i++)
1123 if (slot[i].info) 1167 if (slot[i].info)
1131 } 1175 }
1132 1176
1133 if (weight) 1177 if (weight)
1134 buf.printf ("%s %3.3f kg.\r", nrof > 1 ? "They weigh" : "It weighs", weight * (nrof ? nrof : 1) / 1000.0); 1178 buf.printf ("%s %3.3f kg.\r", nrof > 1 ? "They weigh" : "It weighs", weight * (nrof ? nrof : 1) / 1000.0);
1135 1179
1180 if (flag [FLAG_STARTEQUIP])
1181 buf << (nrof > 1 ? "They were" : "It was")
1182 << " given by a god and will vanish when dropped.\r";
1183
1136 if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who) 1184 if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who)
1137 { 1185 {
1138 buf.printf ("You reckon %s worth %s.\r", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX)); 1186 buf.printf ("You reckon %s worth %s.\r", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX));
1139 1187
1140 if (is_in_shop (who)) 1188 if (is_in_shop (who))
1154 buf << "This is a buildable item.\r"; 1202 buf << "This is a buildable item.\r";
1155 1203
1156 /* Does the object have a message? Don't show message for all object 1204 /* Does the object have a message? Don't show message for all object
1157 * types - especially if the first entry is a match 1205 * types - especially if the first entry is a match
1158 */ 1206 */
1207 if (msg)
1208 {
1159 if (msg && type != EXIT && type != BOOK && type != CORPSE && !move_on && !has_dialogue ()) 1209 if (type != EXIT && type != BOOK && type != CORPSE && !move_on && !has_dialogue ())
1160 { 1210 {
1211 buf << '\r';
1212
1161 /* This is just a hack so when identifying the items, we print 1213 /* This is just a hack so when identifying the items, we print
1162 * out the extra message 1214 * out the extra message
1163 */ 1215 */
1164 if (need_identify (this) && flag [FLAG_IDENTIFIED]) 1216 if (need_identify (this) && flag [FLAG_IDENTIFIED])
1165 buf << "The object has a story:\r"; 1217 buf << "The object has a story:\r";
1166 1218
1167 buf << msg << '\n'; 1219 buf << msg << '\n';
1220 }
1221 }
1222 else if (inv && inv->type == SPELL && flag [FLAG_IDENTIFIED]
1223 && (type == SPELLBOOK || type == ROD || type == WAND
1224 || type == ROD || type == POTION || type == SCROLL))
1225 // for spellbooks and other stuff that contains spells, print the spell message,
1226 // unless the object has a custom message handled above.
1227 buf << '\r' << inv->msg << '\n';
1228
1229 // try to display the duration for some potions and scrolls
1230 // this includes change ability potions and group spells,
1231 // but does not handle protection potions
1232 if (inv && inv->type == SPELL && flag [FLAG_IDENTIFIED]
1233 && (type == POTION || type == SCROLL))
1234 {
1235 object *spell = inv;
1236
1237 if (spell->subtype == SP_PARTY_SPELL)
1238 spell = spell->other_arch;
1239
1240 if (spell->subtype == SP_CHANGE_ABILITY)
1241 buf.printf ("\nH<The effect will last about %.10g seconds.>",
1242 TICK2TIME (change_ability_duration (spell, this)));
1243 }
1244
1245 // Display a hint about inscribable items [empty books]
1246 // This includes the amount of text they can hold.
1247 if (type == INSCRIBABLE)
1248 {
1249 if (other_arch && other_arch->type == SCROLL)
1250 buf.printf ("\nH<You can use the inscription skill to inscribe a spell into it.>");
1251 else
1252 buf.printf ("\nH<You can use the inscription skill to inscribe text into it. It has room for up to %d characters.>",
1253 weight_limit);
1168 } 1254 }
1169 1255
1170 buf << '\n'; 1256 buf << '\n';
1257
1258 // the dungeon master additionally gets a complete dump
1259 if (who && who->flag [FLAG_WIZLOOK])
1260 {
1261 buf << "\nT<Object>\n";
1262 describe_dump_object (buf, this);
1263
1264 if (inv)
1265 {
1266 buf << "\nT<Top Inventory>\n";
1267 describe_dump_object (buf, inv);
1268 }
1269 }
1171 1270
1172 return std::string (buf.linearise (), buf.size ()); 1271 return std::string (buf.linearise (), buf.size ());
1173} 1272}
1174 1273
1175static void 1274static void
1176display_new_pickup (object *op) 1275display_new_pickup (object *op)
1177{ 1276{
1178 int i = op->contr->mode; 1277 int i = op->contr->mode;
1179 1278
1180 if (!(i & PU_NEWMODE))
1181 return;
1182
1183 new_draw_info_format (NDI_UNIQUE, 0, op, "%d NEWMODE", i & PU_NEWMODE ? 1 : 0);
1184 new_draw_info_format (NDI_UNIQUE, 0, op, "%d DEBUG", i & PU_DEBUG ? 1 : 0); 1279 new_draw_info_format (NDI_UNIQUE, 0, op, "%d DEBUG", i & PU_DEBUG ? 1 : 0);
1185 new_draw_info_format (NDI_UNIQUE, 0, op, "%d INHIBIT", i & PU_INHIBIT ? 1 : 0); 1280 new_draw_info_format (NDI_UNIQUE, 0, op, "%d INHIBIT", i & PU_INHIBIT ? 1 : 0);
1186 new_draw_info_format (NDI_UNIQUE, 0, op, "%d STOP", i & PU_STOP ? 1 : 0); 1281 new_draw_info_format (NDI_UNIQUE, 0, op, "%d STOP", i & PU_STOP ? 1 : 0);
1187 1282
1188 new_draw_info_format (NDI_UNIQUE, 0, op, "%d <= x pickup weight/value RATIO (0==off)", (i & PU_RATIO) * 5); 1283 new_draw_info_format (NDI_UNIQUE, 0, op, "%d <= x pickup weight/value RATIO (0==off)", (i & PU_RATIO) * 5);
1239 }; 1334 };
1240 1335
1241 if (!params) 1336 if (!params)
1242 { 1337 {
1243 /* if the new mode is used, just print the settings */ 1338 /* if the new mode is used, just print the settings */
1244 if (op->contr->mode & PU_NEWMODE)
1245 {
1246 display_new_pickup (op); 1339 display_new_pickup (op);
1247 return 1;
1248 }
1249 if (1)
1250 LOG (llevDebug, "command_pickup: !params\n");
1251 set_pickup_mode (op, (op->contr->mode > 6) ? 0 : op->contr->mode + 1);
1252 return 0; 1340 return 0;
1253 } 1341 }
1254 1342
1255 while (*params == ' ' && *params) 1343 while (*params == ' ' && *params)
1256 params++; 1344 params++;
1262 for (mode = 0; names[mode]; mode++) 1350 for (mode = 0; names[mode]; mode++)
1263 { 1351 {
1264 if (!strcmp (names[mode], params + 1)) 1352 if (!strcmp (names[mode], params + 1))
1265 { 1353 {
1266 i = op->contr->mode; 1354 i = op->contr->mode;
1267 if (!(i & PU_NEWMODE)) 1355
1268 i = PU_NEWMODE;
1269 if (*params == '+') 1356 if (*params == '+')
1270 i = i | modes[mode]; 1357 i = i | modes[mode];
1271 else 1358 else
1272 i = i & ~modes[mode]; 1359 i = i & ~modes[mode];
1360
1273 op->contr->mode = i; 1361 op->contr->mode = i;
1274 display_new_pickup (op); 1362 display_new_pickup (op);
1275 return 1; 1363 return 1;
1276 } 1364 }
1277 } 1365 }
1279 return 1; 1367 return 1;
1280 } 1368 }
1281 1369
1282 if (sscanf (params, "%u", &i) != 1) 1370 if (sscanf (params, "%u", &i) != 1)
1283 { 1371 {
1284 if (1)
1285 LOG (llevDebug, "command_pickup: params==NULL\n");
1286 new_draw_info (NDI_UNIQUE, 0, op, "Usage: pickup <0-7> or <value_density> ."); 1372 new_draw_info (NDI_UNIQUE, 0, op, "Usage: pickup <value_density> or [+-]type.");
1287 return 1; 1373 return 1;
1288 } 1374 }
1289 set_pickup_mode (op, i); 1375
1376 if (i <= PU_RATIO)
1377 i |= op->contr->mode & ~PU_RATIO;
1378
1379 op->contr->mode = i;
1290 1380
1291 return 1; 1381 return 1;
1292}
1293
1294void
1295set_pickup_mode (object *op, int i)
1296{
1297 switch (op->contr->mode = i)
1298 {
1299 case 0:
1300 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Don't pick up.");
1301 break;
1302 case 1:
1303 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item.");
1304 break;
1305 case 2:
1306 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item and stop.");
1307 break;
1308 case 3:
1309 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Stop before picking up.");
1310 break;
1311 case 4:
1312 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items.");
1313 break;
1314 case 5:
1315 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items and stop.");
1316 break;
1317 case 6:
1318 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all magic items.");
1319 break;
1320 case 7:
1321 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all coins and gems");
1322 break;
1323 }
1324} 1382}
1325 1383
1326int 1384int
1327command_search_items (object *op, char *params) 1385command_search_items (object *op, char *params)
1328{ 1386{
1329 char buf[MAX_BUF];
1330
1331 if (settings.search_items == FALSE)
1332 return 1;
1333
1334 if (params == NULL) 1387 if (params == NULL)
1335 { 1388 {
1336 if (op->contr->search_str[0] == '\0') 1389 if (op->contr->search_str[0] == '\0')
1337 { 1390 {
1338 new_draw_info (NDI_UNIQUE, 0, op, "Example: search magic+1"); 1391 new_draw_info (NDI_UNIQUE, 0, op, "Example: search-items magic+1");
1339 new_draw_info (NDI_UNIQUE, 0, op, "Would automatically pick up all"); 1392 new_draw_info (NDI_UNIQUE, 0, op, "Would automatically pick up all");
1340 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'."); 1393 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'.");
1341 return 1; 1394 return 1;
1342 } 1395 }
1343 1396
1344 op->contr->search_str[0] = '\0'; 1397 op->contr->search_str[0] = '\0';
1345 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off."); 1398 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off.");
1346 op->update_stats (); 1399 op->contr->queue_stats_update ();
1347 return 1; 1400 return 1;
1348 } 1401 }
1349 1402
1350 if ((int) strlen (params) >= MAX_BUF) 1403 if (strlen (params) >= sizeof (op->contr->search_str))
1351 { 1404 {
1352 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long."); 1405 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long.");
1353 return 1; 1406 return 1;
1354 } 1407 }
1355 1408
1356 strcpy (op->contr->search_str, params); 1409 strcpy (op->contr->search_str, params);
1357 sprintf (buf, "Searching for '%s'.", op->contr->search_str); 1410 new_draw_info (NDI_UNIQUE, 0, op, format ("Now searching for '%s'.", op->contr->search_str));
1358 new_draw_info (NDI_UNIQUE, 0, op, buf); 1411 op->contr->queue_stats_update ();
1359 op->update_stats (); 1412
1360 return 1; 1413 return 1;
1361} 1414}
1362 1415
1416int
1417command_unlock (object *op, char *params)
1418{
1419 /* if the unlock command typed with nothing, unlock everything,
1420 * this might be bad
1421 */
1422 if (params == NULL)
1423 {
1424 for (object *item = op->inv; item; item = item->below)
1425 {
1426 CLEAR_FLAG(item, FLAG_INV_LOCKED);
1427 //d// new_draw_info (NDI_UNIQUE, 0, op, "unlocked items with null param.");
1428 esrv_update_item (UPD_FLAGS, op, item);
1429 }
1430 return 0;
1431 }
1432
1433 /* if the unlock command is used with a param,
1434 * unlock what matches. i.e. unlock material, should unlock all the materials
1435 */
1436 for (object *item = op->inv; item; item = item->below)
1437 if (item->name.contains (params))
1438 {
1439 CLEAR_FLAG (item, FLAG_INV_LOCKED);
1440 //d// new_draw_info (NDI_UNIQUE, 0, op, "unlocked items with a param.");
1441 esrv_update_item (UPD_FLAGS, op, item);
1442 }
1443
1444 return 0;
1445}
1446
1447int
1448command_lock (object *op, char *params)
1449{
1450 /* if the lock command is typed by itself, lock everything
1451 */
1452 if (params == NULL)
1453 {
1454 for (object *item = op->inv; item; item = item->below)
1455 {
1456 SET_FLAG (item, FLAG_INV_LOCKED);
1457 //d// new_draw_info (NDI_UNIQUE, 0, op, "locked items with null param.");
1458 esrv_update_item (UPD_FLAGS, op, item);
1459 }
1460 return 0;
1461 }
1462
1463 /* if the lock command is used with a param, lock what matches.
1464 * i.e. lock material, should lock all the materials
1465 */
1466 for (object *item = op->inv; item; item = item->below)
1467 if (item->name.contains (params))
1468 {
1469 SET_FLAG (item, FLAG_INV_LOCKED);
1470 //d// new_draw_info (NDI_UNIQUE, 0, op, "locked items with param.");
1471 esrv_update_item (UPD_FLAGS, op, item);
1472 }
1473
1474 return 0;
1475}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines