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.89 by elmex, Mon Jan 12 00:17:23 2009 UTC vs.
Revision 1.126 by root, Tue Jan 3 11:25:36 2012 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,2009 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 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
68 67
69 int tmpmatch = item_matched_string (pl, tmp, params); 68 int tmpmatch = item_matched_string (pl, tmp, params);
70 69
71 if (tmpmatch > match_val) 70 if (tmpmatch > match_val)
72 { 71 {
73 if ((aflag == AP_APPLY) && (QUERY_FLAG (tmp, FLAG_APPLIED))) 72 if ((aflag == AP_APPLY) && (tmp->flag [FLAG_APPLIED]))
74 continue; 73 continue;
75 74
76 if ((aflag == AP_UNAPPLY) && (!QUERY_FLAG (tmp, FLAG_APPLIED))) 75 if ((aflag == AP_UNAPPLY) && (!tmp->flag [FLAG_APPLIED]))
77 continue; 76 continue;
78 77
79 match_val = tmpmatch; 78 match_val = tmpmatch;
80 best = tmp; 79 best = tmp;
81 } 80 }
137 136
138 skill = find_skill_by_name_fuzzy (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 %s skill.", params);
143 return 0; 142 return 0;
144 } 143 }
145 144
146 pl->change_skill (0); 145 pl->apply (skill);
147 apply_special (pl, skill, AP_APPLY);
148 return 1; 146 return 1;
149} 147}
150 148
151/* A little special because we do want to pass the full params along 149/* A little special because we do want to pass the full params along
152 * as it includes the object to throw. 150 * as it includes the object to throw.
153 */ 151 */
154int 152int
155command_throw (object *op, char *params) 153command_throw (object *op, char *params)
156{ 154{
157 if (object *skop = find_skill_by_name (op, skill_names[SK_THROWING])) 155 if (object *skop = find_skill_by_name (op, shstr_throwing))
158 return do_skill (op, op, skop, op->facing, params); 156 return do_skill (op, op, skop, op->facing, params);
159 else 157 else
160 new_draw_info (NDI_UNIQUE, 0, op, "You have no knowledge of the skill throwing."); 158 new_draw_info (NDI_UNIQUE, 0, op, "You have no knowledge of the throwing skill.");
161 159
162 return 0; 160 return 0;
163} 161}
164 162
165int 163int
191 189
192 while (*params == ' ') 190 while (*params == ' ')
193 params++; 191 params++;
194 192
195 if (object *inv = find_best_apply_object_match (op, params, aflag)) 193 if (object *inv = find_best_apply_object_match (op, params, aflag))
196 player_apply (op, inv, aflag, 0); 194 op->apply (inv, aflag);
197 else 195 else
198 new_draw_info_format (NDI_UNIQUE, 0, op, "Could not find any match to the %s.", params); 196 op->failmsgf ("Could not find any match to the %s.", params);
199 } 197 }
200 198
201 return 0; 199 return 0;
202} 200}
203 201
211 * not need to use split_ob and stuff. 209 * not need to use split_ob and stuff.
212 */ 210 */
213int 211int
214sack_can_hold (object *pl, object *sack, object *op, uint32 nrof) 212sack_can_hold (object *pl, object *sack, object *op, uint32 nrof)
215{ 213{
216 if (!QUERY_FLAG (sack, FLAG_APPLIED)) 214 if (!sack->flag [FLAG_APPLIED])
217 { 215 {
218 new_draw_info_format (NDI_UNIQUE, 0, pl, "The %s is not active.", query_name (sack)); 216 new_draw_info_format (NDI_UNIQUE, 0, pl, "The %s is not active.", query_name (sack));
219 return 0; 217 return 0;
220 } 218 }
221 219
225 return 0; 223 return 0;
226 } 224 }
227 225
228 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type))) 226 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type)))
229 { 227 {
230 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can put only %s into the %s.", &sack->race, query_name (sack)); 228 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can only put objects of type '%s' into the %s.", &sack->race, query_name (sack));
231 return 0; 229 return 0;
232 } 230 }
233 231
234 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying) 232 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying)
235 { 233 {
266 /* IF the player is flying & trying to take the item out of a container 264 /* IF the player is flying & trying to take the item out of a container
267 * that is in his inventory, let him. tmp->env points to the container 265 * that is in his inventory, let him. tmp->env points to the container
268 * (sack, luggage, etc), tmp->env->env then points to the player (nested 266 * (sack, luggage, etc), tmp->env->env then points to the player (nested
269 * containers not allowed as of now) 267 * containers not allowed as of now)
270 */ 268 */
271 if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && tmp->in_player () != pl) 269 if ((pl->move_type & MOVE_FLYING) && !pl->flag [FLAG_WIZ] && tmp->in_player () != pl)
272 { 270 {
273 pl->failmsg ("You are levitating, you can't reach the ground! " 271 pl->failmsg ("You are levitating, you can't reach the ground! "
274 "H<You have to stop levitating first, if you can, either by using your levitation skill, " 272 "H<You have to stop levitating first, if you can, either by using your levitation skill, "
275 "or waiting till the levitation effect wears off.>"); 273 "or waiting till the levitation effect wears off.>");
276 return; 274 return;
277 } 275 }
278 276
279 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 277 if (tmp->flag [FLAG_NO_DROP])
280 return; 278 return;
281 279
282 if (nrof > tmp_nrof || nrof <= 0) 280 if (nrof > tmp_nrof || nrof <= 0)
283 nrof = tmp_nrof; 281 nrof = tmp_nrof;
284 282
296 } 294 }
297 295
298 if (!can_split (pl, tmp, nrof)) 296 if (!can_split (pl, tmp, nrof))
299 return; 297 return;
300 298
301 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 299 if (tmp->flag [FLAG_UNPAID])
302 { 300 {
303 tmp->flag.reset (FLAG_UNPAID); 301 tmp->flag.reset (FLAG_UNPAID);
304 new_draw_info_format (NDI_UNIQUE, 0, pl, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP)); 302 new_draw_info_format (NDI_UNIQUE, 0, pl, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP));
305 tmp->flag.set (FLAG_UNPAID); 303 tmp->flag.set (FLAG_UNPAID);
306 } 304 }
361 count = tmp->nrof; 359 count = tmp->nrof;
362 360
363 /* container is open, so use it */ 361 /* container is open, so use it */
364 if (tmp->flag [FLAG_STARTEQUIP]) 362 if (tmp->flag [FLAG_STARTEQUIP])
365 alt = op; 363 alt = op;
366 else if (op->container) 364 else if ((alt = op->container_ ()))
367 { 365 {
368 alt = op->container;
369 if (alt != tmp->env && !sack_can_hold (op, alt, tmp, count)) 366 if (alt != tmp->env && !sack_can_hold (op, alt, tmp, count))
370 goto leave; 367 goto leave;
371 } 368 }
372 else 369 else
373 { /* non container pickup */ 370 { /* non container pickup */
374 for (alt = op->inv; alt; alt = alt->below) 371 for (alt = op->inv; alt; alt = alt->below)
375 if (alt->type == CONTAINER && QUERY_FLAG (alt, FLAG_APPLIED) && 372 if (alt->type == CONTAINER && alt->flag [FLAG_APPLIED] &&
376 alt->race && alt->race == tmp->race && sack_can_hold (NULL, alt, tmp, count)) 373 alt->race && alt->race == tmp->race && sack_can_hold (NULL, alt, tmp, count))
377 break; /* perfect match */ 374 break; /* perfect match */
378 375
379 if (!alt) 376 if (!alt)
380 for (alt = op->inv; alt; alt = alt->below) 377 for (alt = op->inv; alt; alt = alt->below)
381 if (alt->type == CONTAINER && QUERY_FLAG (alt, FLAG_APPLIED) && sack_can_hold (NULL, alt, tmp, count)) 378 if (alt->type == CONTAINER && alt->flag [FLAG_APPLIED] && sack_can_hold (NULL, alt, tmp, count))
382 break; /* General container comes next */ 379 break; /* General container comes next */
383 380
384 if (!alt) 381 if (!alt)
385 alt = op; /* No free containers */ 382 alt = op; /* No free containers */
386 } 383 }
396#ifdef PICKUP_DEBUG 393#ifdef PICKUP_DEBUG
397 LOG (llevDebug, "Pick_up(): %s picks %s (%d) and inserts it %s.\n", op->name, tmp->name, op->contr->count, alt->name); 394 LOG (llevDebug, "Pick_up(): %s picks %s (%d) and inserts it %s.\n", op->name, tmp->name, op->contr->count, alt->name);
398#endif 395#endif
399 396
400 /* startequip items are not allowed to be put into containers: */ 397 /* startequip items are not allowed to be put into containers: */
401 if (op->type == PLAYER && alt->type == CONTAINER && QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 398 if (op->type == PLAYER && alt->type == CONTAINER && tmp->flag [FLAG_STARTEQUIP])
402 { 399 {
403 new_draw_info (NDI_UNIQUE, 0, op, "This object cannot be put into containers!"); 400 new_draw_info (NDI_UNIQUE, 0, op, "This object cannot be put into containers!");
404 goto leave; 401 goto leave;
405 } 402 }
406 403
427int 424int
428command_take (object *op, char *params) 425command_take (object *op, char *params)
429{ 426{
430 object *tmp, *next; 427 object *tmp, *next;
431 428
432 if (op->container) 429 if (op->container_ ())
433 tmp = op->container->inv; 430 tmp = op->container_ ()->inv;
434 else 431 else
435 { 432 {
436 tmp = op->above; 433 tmp = op->above;
437 if (tmp) 434 if (tmp)
438 while (tmp->above) 435 while (tmp->above)
450 447
451 /* Makes processing easier */ 448 /* Makes processing easier */
452 if (params && *params == '\0') 449 if (params && *params == '\0')
453 params = 0; 450 params = 0;
454 451
455 int cnt = MAX_ITEM_PER_DROP; 452 int cnt = MAX_ITEM_PER_ACTION;
456 453
457 while (tmp) 454 while (tmp)
458 { 455 {
459 next = tmp->below; 456 next = tmp->below;
460 457
520 char buf[MAX_BUF]; 517 char buf[MAX_BUF];
521 518
522 if (sack == tmp) 519 if (sack == tmp)
523 return; /* Can't put an object in itself */ 520 return; /* Can't put an object in itself */
524 521
525 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 522 if (tmp->flag [FLAG_STARTEQUIP] || tmp->flag [FLAG_NO_DROP])
526 { 523 {
527 new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack)); 524 new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack));
528 return; 525 return;
529 } 526 }
530 527
539 536
540 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) 537 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp)
541 { 538 {
542 tmp = tmp2->below; 539 tmp = tmp2->below;
543 540
544 if ((sack->type == CONTAINER && sack_can_hold (op, op->container, tmp2, tmp2->nrof))) 541 if ((sack->type == CONTAINER && sack_can_hold (op, op->container_ (), tmp2, tmp2->nrof)))
545 put_object_in_sack (op, sack, tmp2, 0); 542 put_object_in_sack (op, sack, tmp2, 0);
546 else 543 else
547 { 544 {
548 sprintf (buf, "Your %s fills up.", query_name (sack)); 545 sprintf (buf, "Your %s fills up.", query_name (sack));
549 new_draw_info (NDI_UNIQUE, 0, op, buf); 546 new_draw_info (NDI_UNIQUE, 0, op, buf);
558 * already checked this. 555 * already checked this.
559 */ 556 */
560 if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof))) 557 if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof)))
561 return; 558 return;
562 559
563 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 560 if (tmp->flag [FLAG_APPLIED])
564 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 561 if (!op->apply (tmp, AP_UNAPPLY | AP_NO_MERGE))
565 return; 562 return;
566 563
567 /* we want to put some portion of the item into the container */ 564 /* we want to put some portion of the item into the container */
568 if (!can_split (op, tmp, nrof)) 565 if (!can_split (op, tmp, nrof))
569 return; 566 return;
570 567
571 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack)); 568 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack));
572 sack->insert (tmp); 569 sack->insert (tmp);
573}
574
575/*
576 * This function was part of drop, now is own function.
577 * Player 'op' tries to drop object 'tmp', if tmp is non zero, then
578 * nrof objects is tried to dropped.
579 * This is used when dropping objects onto the floor.
580 */
581void
582drop_object (object *op, object *tmp, uint32 nrof)
583{
584 if (QUERY_FLAG (tmp, FLAG_NO_DROP))
585 return;
586
587 if (QUERY_FLAG (tmp, FLAG_APPLIED))
588 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
589 return; /* can't unapply it */
590
591 //fprintf (stderr, "ui, on space is %ld\n", op->ms ().volume ());//D
592
593 /* We are only dropping some of the items. We split the current object
594 * off
595 */
596 if (!can_split (op, tmp, nrof))
597 return;
598
599 drop_object (op, tmp);
600
601 if (!tmp->destroyed () && !tmp->is_inserted ())
602 {
603 // if nothing happened with the object we give it back
604 op->insert (tmp);
605 }
606} 570}
607 571
608/* In contrast to drop_object (op, tmp, nrof) above this function takes the 572/* In contrast to drop_object (op, tmp, nrof) above this function takes the
609 * already split off object, and feeds it to the event handlers and does 573 * already split off object, and feeds it to the event handlers and does
610 * other magic with it. 574 * other magic with it.
613 * object that was dropped. 577 * object that was dropped.
614 * 578 *
615 * Make sure to check what happened with <obj> after this function returns! 579 * Make sure to check what happened with <obj> after this function returns!
616 * Otherwise you may leak this object. 580 * Otherwise you may leak this object.
617 */ 581 */
618
619void 582void
620drop_object (object *dropper, object *obj) 583drop_object (object *dropper, object *obj)
621{ 584{
622 if (INVOKE_OBJECT (DROP, obj, ARG_OBJECT (dropper))) 585 if (INVOKE_OBJECT (DROP, obj, ARG_OBJECT (dropper)))
623 return; 586 return;
624 587
625 if (obj->destroyed () || obj->is_inserted ()) 588 if (obj->destroyed () || obj->is_inserted ())
626 return; 589 return;
627 590
628 if (QUERY_FLAG (obj, FLAG_STARTEQUIP)) 591 if (obj->flag [FLAG_STARTEQUIP])
629 { 592 {
630 dropper->statusmsg (format ("You drop the %s.", query_name (obj))); 593 dropper->statusmsg (format ("You drop the %s.", query_name (obj)));
631 dropper->statusmsg ("The god who lent it to you retrieves it."); 594 dropper->statusmsg ("The god who lent it to you retrieves it.");
632 595
633 obj->destroy (); 596 obj->destroy ();
642 return; 605 return;
643 606
644 if (obj->destroyed () || obj->is_inserted ()) 607 if (obj->destroyed () || obj->is_inserted ())
645 return; 608 return;
646 609
647 if (is_in_shop (dropper) && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY) 610 if (dropper->is_in_shop () && !obj->flag [FLAG_UNPAID] && obj->type != MONEY)
648 if (!sell_item (obj, dropper)) 611 if (!sell_item (obj, dropper))
649 return; 612 return;
613
614 if (!obj->can_drop_at (dropper->map, dropper->x, dropper->y, dropper))
615 return;
650 616
651 /* If nothing special happened with this object, the default action is to 617 /* If nothing special happened with this object, the default action is to
652 * insert it below the dropper: 618 * insert it below the dropper:
653 */ 619 */
654 620
655 obj->x = dropper->x; 621 obj->x = dropper->x;
656 obj->y = dropper->y; 622 obj->y = dropper->y;
657 623
658 insert_ob_in_map (obj, dropper->map, dropper, INS_BELOW_ORIGINATOR); 624 insert_ob_in_map (obj, dropper->map, dropper, INS_BELOW_ORIGINATOR);
625}
626
627/*
628 * This function was part of drop, now is own function.
629 * Player 'op' tries to drop object 'tmp', if tmp is non zero, then
630 * nrof objects are tried to drop.
631 * This is used when dropping objects onto the floor.
632 */
633void
634drop_object (object *op, object *tmp, uint32 nrof)
635{
636 if (tmp->flag [FLAG_NO_DROP])
637 return;
638
639 if (tmp->flag [FLAG_APPLIED])
640 if (!op->apply (tmp, AP_UNAPPLY | AP_NO_MERGE))
641 return; /* can't unapply it */
642
643 /* We are only dropping some of the items. We split the current object
644 * off
645 */
646 if (!can_split (op, tmp, nrof))
647 return;
648
649 drop_object (op, tmp);
650
651 if (!tmp->destroyed () && !tmp->is_inserted ())
652 {
653 // if nothing happened with the object we give it back
654 op->insert (tmp);
655 }
659} 656}
660 657
661void 658void
662drop (object *op, object *tmp) 659drop (object *op, object *tmp)
663{ 660{
676 */ 673 */
677 tmp->destroy (); 674 tmp->destroy ();
678 return; 675 return;
679 } 676 }
680 else 677 else
681 {
682 while (tmp && tmp->invisible) 678 while (tmp && tmp->invisible)
683 tmp = tmp->below; 679 tmp = tmp->below;
684 }
685 } 680 }
686 681
687 if (tmp == NULL) 682 if (!tmp)
688 { 683 {
689 new_draw_info (NDI_UNIQUE, 0, op, "You don't have anything to drop."); 684 new_draw_info (NDI_UNIQUE, 0, op, "You don't have anything to drop.");
690 return; 685 return;
691 } 686 }
692 687
693 if (QUERY_FLAG (tmp, FLAG_INV_LOCKED)) 688 if (tmp->flag [FLAG_INV_LOCKED])
694 { 689 {
695 new_draw_info (NDI_UNIQUE, 0, op, "This item is locked"); 690 new_draw_info (NDI_UNIQUE, 0, op, "This item is locked");
696 return; 691 return;
697 } 692 }
698 693
699 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 694 if (tmp->flag [FLAG_NO_DROP])
700 { 695 {
701#if 0 696#if 0
702 /* Eneq(@csd.uu.se): Objects with NO_DROP defined can't be dropped. */ 697 /* Eneq(@csd.uu.se): Objects with NO_DROP defined can't be dropped. */
703 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped."); 698 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped.");
704#endif 699#endif
706 } 701 }
707 702
708 if (op->type == PLAYER && op->contr->last_used == tmp) 703 if (op->type == PLAYER && op->contr->last_used == tmp)
709 op->contr->last_used = tmp->below ? tmp->below 704 op->contr->last_used = tmp->below ? tmp->below
710 : tmp->above ? tmp->above 705 : tmp->above ? tmp->above
711 : 0; 706 : (object *)0;
712 707
713 if (op->container) 708 if (op->container_ ())
714 { 709 {
715 if (op->type == PLAYER) 710 if (op->type == PLAYER)
716 put_object_in_sack (op, op->container, tmp, op->contr->count); 711 put_object_in_sack (op, op->container_ (), tmp, op->contr->count);
717 else 712 else
718 put_object_in_sack (op, op->container, tmp, 0); 713 put_object_in_sack (op, op->container_ (), tmp, 0);
719 } 714 }
720 else 715 else
721 { 716 {
722 if (op->type == PLAYER) 717 if (op->type == PLAYER)
723 drop_object (op, tmp, op->contr->count); 718 drop_object (op, tmp, op->contr->count);
750 /* 745 /*
751 Care must be taken that the next item pointer is not to money as 746 Care must be taken that the next item pointer is not to money as
752 the drop() routine will do unknown things to it when dropping 747 the drop() routine will do unknown things to it when dropping
753 in a shop. --Tero.Pelander@utu.fi 748 in a shop. --Tero.Pelander@utu.fi
754 */ 749 */
755
756 int cnt = MAX_ITEM_PER_DROP; 750 int cnt = MAX_ITEM_PER_ACTION;
757 751
758 if (!params) 752 if (!params)
759 { 753 {
760 while (curinv) 754 while (curinv)
761 { 755 {
762 nextinv = curinv->below; 756 nextinv = curinv->below;
763 757
764 while (nextinv && nextinv->type == MONEY) 758 while (nextinv && nextinv->type == MONEY)
765 nextinv = nextinv->below; 759 nextinv = nextinv->below;
766 760
767 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && curinv->type != MONEY && 761 if (!curinv->flag [FLAG_INV_LOCKED]
768 curinv->type != FOOD && curinv->type != KEY && 762 && !curinv->invisible
769 curinv->type != SPECIAL_KEY && curinv->type != GEM && 763 && curinv->type != MONEY
770 !curinv->invisible && (curinv->type != CONTAINER || op->container != curinv)) 764 && curinv->type != FOOD
765 && curinv->type != KEY
766 && curinv->type != SPECIAL_KEY
767 && curinv->type != GEM
768 && curinv->type != CONTAINER)
771 { 769 {
772 drop (op, curinv); 770 drop (op, curinv);
773 if (--cnt <= 0) break; 771 if (--cnt <= 0) break;
774 } 772 }
775 773
783 nextinv = curinv->below; 781 nextinv = curinv->below;
784 782
785 while (nextinv && nextinv->type == MONEY) 783 while (nextinv && nextinv->type == MONEY)
786 nextinv = nextinv->below; 784 nextinv = nextinv->below;
787 785
788 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && ((curinv->type == WEAPON) || (curinv->type == BOW) || (curinv->type == ARROW))) 786 if (!curinv->flag [FLAG_INV_LOCKED] && ((curinv->type == WEAPON) || (curinv->type == BOW) || (curinv->type == ARROW)))
789 { 787 {
790 drop (op, curinv); 788 drop (op, curinv);
791 if (--cnt <= 0) break; 789 if (--cnt <= 0) break;
792 } 790 }
793 791
801 nextinv = curinv->below; 799 nextinv = curinv->below;
802 800
803 while (nextinv && nextinv->type == MONEY) 801 while (nextinv && nextinv->type == MONEY)
804 nextinv = nextinv->below; 802 nextinv = nextinv->below;
805 803
806 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && ((curinv->type == ARMOUR) || curinv->type == SHIELD || curinv->type == HELMET)) 804 if (!curinv->flag [FLAG_INV_LOCKED] && ((curinv->type == ARMOUR) || curinv->type == SHIELD || curinv->type == HELMET))
807 { 805 {
808 drop (op, curinv); 806 drop (op, curinv);
809 if (--cnt <= 0) break; 807 if (--cnt <= 0) break;
810 } 808 }
811 809
819 nextinv = curinv->below; 817 nextinv = curinv->below;
820 818
821 while (nextinv && nextinv->type == MONEY) 819 while (nextinv && nextinv->type == MONEY)
822 nextinv = nextinv->below; 820 nextinv = nextinv->below;
823 821
824 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && !QUERY_FLAG (curinv, FLAG_APPLIED)) 822 if (!curinv->flag [FLAG_INV_LOCKED] && !curinv->flag [FLAG_APPLIED])
825 { 823 {
826 switch (curinv->type) 824 switch (curinv->type)
827 { 825 {
828 case HORN: 826 case HORN:
829 case BOOK: 827 case BOOK:
869 * <cnt> can be a 0 pointer or a pointer to the maximum number of 867 * <cnt> can be a 0 pointer or a pointer to the maximum number of
870 * drop operations to perform. 868 * drop operations to perform.
871 * 869 *
872 * Returns true if at least one item was dropped. 870 * Returns true if at least one item was dropped.
873 */ 871 */
874bool 872static bool
875drop_vector (object *dropper, vector<object *> &objs, int *cnt) 873drop_vector (object *dropper, vector<object *> &objs, int *cnt)
876{ 874{
877 vector<object *>::iterator i; 875 vector<object *>::iterator i;
878 876
879 bool did_one = false; 877 bool did_one = false;
907 vector<object *> matched_objs; 905 vector<object *> matched_objs;
908 906
909 for (tmp = op->inv; tmp; tmp = next) 907 for (tmp = op->inv; tmp; tmp = next)
910 { 908 {
911 next = tmp->below; 909 next = tmp->below;
912 if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) 910 if (tmp->flag [FLAG_NO_DROP] || tmp->invisible)
913 continue; 911 continue;
914 912
915 if (item_matched_string (op, tmp, params)) 913 if (item_matched_string (op, tmp, params))
916 matched_objs.push_back (tmp); 914 matched_objs.push_back (tmp);
917 } 915 }
918 916
919 int cnt = MAX_ITEM_PER_DROP; 917 int cnt = MAX_ITEM_PER_ACTION;
920 918
921 if (!drop_vector (op, matched_objs, &cnt)) 919 if (!drop_vector (op, matched_objs, &cnt))
922 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); 920 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop.");
923 921
924 if (cnt <= 0) 922 if (cnt <= 0)
952 } 950 }
953 951
954 return 0; 952 return 0;
955} 953}
956 954
957/* op should be a player.
958 * we return the object the player has marked with the 'mark' command
959 * below. If no match is found (or object has changed), we return
960 * NULL. We leave it up to the calling function to print messages if
961 * nothing is found.
962 */
963object *
964find_marked_object (object *op)
965{
966 object *tmp;
967
968 if (!op || !op->contr)
969 return NULL;
970
971 if (!op->contr->mark)
972 {
973/* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/
974 return 0;
975 }
976
977 /* This may seem like overkill, but we need to make sure that they
978 * player hasn't dropped the item. We use count on the off chance that
979 * an item got reincarnated at some point.
980 */
981 for (tmp = op->inv; tmp; tmp = tmp->below)
982 {
983 if (tmp->invisible)
984 continue;
985
986 if (tmp == op->contr->mark)
987 {
988 if (!tmp->destroyed ())
989 return tmp;
990 else
991 {
992 op->contr->mark = 0;
993/* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/
994 return 0;
995 }
996 }
997 }
998
999 return 0;
1000}
1001
1002std::string 955std::string
1003object::describe_monster (object *who) 956object::describe_monster (object *who)
1004{ 957{
1005 dynbuf_text buf (512, 512); 958 dynbuf_text buf (512, 512);
1006 959
1007 object *mon = head ? head : this; 960 object *mon = head ? head : this;
1008 961
1009 if (QUERY_FLAG (mon, FLAG_UNDEAD)) 962 if (mon->flag [FLAG_UNDEAD])
1010 buf << "It is an undead force.\r"; 963 buf << "It is an undead force.\r";
1011 964
1012 if (mon->level > who->level) 965 if (mon->level > who->level)
1013 buf << "It is likely more powerful than you.\r"; 966 buf << "It is likely more powerful than you.\r";
1014 else if (mon->level < who->level) 967 else if (mon->level < who->level)
1071 case SHIELD: 1024 case SHIELD:
1072 case BOOTS: 1025 case BOOTS:
1073 case GLOVES: 1026 case GLOVES:
1074 case AMULET: 1027 case AMULET:
1075 case GIRDLE: 1028 case GIRDLE:
1029 case RANGED:
1076 case BOW: 1030 case BOW:
1077 case ARROW: 1031 case ARROW:
1078 case CLOAK: 1032 case CLOAK:
1079 case FOOD: 1033 case FOOD:
1080 case DRINK: 1034 case DRINK:
1101 */ 1055 */
1102void 1056void
1103examine_monster (object *op, object *tmp) 1057examine_monster (object *op, object *tmp)
1104{ 1058{
1105 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ()); 1059 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ());
1106}
1107
1108std::string
1109object::describe (object *who)
1110{
1111 dynbuf_text buf (1024, 1024);
1112
1113 buf.printf ("That is: %s.\r", long_desc (who).c_str ());
1114
1115 if (custom_name)
1116 buf.printf ("You call it %s.\r", &custom_name);
1117
1118 switch (type)
1119 {
1120 case SPELLBOOK:
1121 if (flag [FLAG_IDENTIFIED] && inv)
1122 buf.printf ("%s is a level %s %s spell.\r", &inv->name, get_levelnumber (inv->level), &inv->skill);
1123 break;
1124
1125 case BOOK:
1126 if (msg)
1127 buf << "Something is written in it.\r";
1128 break;
1129
1130 case CONTAINER:
1131 if (race)
1132 {
1133 if (weight_limit && stats.Str < 100)
1134 buf.printf ("It can hold only %s and its weight limit is %.1f kg.\r",
1135 &race, weight_limit / (10.0 * (100 - stats.Str)));
1136 else
1137 buf.printf ("It can hold only %s.\r", &race);
1138 }
1139 else if (weight_limit && stats.Str < 100)
1140 buf.printf ("Its weight limit is %.1f kg.\r", weight_limit / (10.0 * (100 - stats.Str)));
1141 break;
1142
1143 case WAND:
1144 if (flag [FLAG_IDENTIFIED])
1145 buf.printf ("It has %d charges left.\r", stats.food);
1146 break;
1147 }
1148
1149 if (materialname && !msg)
1150 buf.printf ("It is made of: %s.\r", &materialname);
1151
1152 if (who)
1153 /* Where to wear this item */
1154 for (int i = 0; i < NUM_BODY_LOCATIONS; i++)
1155 if (slot[i].info)
1156 {
1157 buf << (who->slot[i].info ? body_locations[i].use_name : body_locations[i].nonuse_name);
1158
1159 if (slot[i].info < -1 && who->slot[i].info)
1160 buf.printf ("(%d)", -slot[i].info);
1161
1162 buf << ".\r";
1163 }
1164
1165 if (weight)
1166 buf.printf ("%s %3.3f kg.\r", nrof > 1 ? "They weigh" : "It weighs", weight * (nrof ? nrof : 1) / 1000.0);
1167
1168 if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who)
1169 {
1170 buf.printf ("You reckon %s worth %s.\r", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX));
1171
1172 if (is_in_shop (who))
1173 {
1174 if (flag [FLAG_UNPAID])
1175 buf.printf ("%s would cost you %s.\r", nrof > 1 ? "They" : "It", query_cost_string (this, who, F_BUY | F_SHOP));
1176 else
1177 buf.printf ("You are offered %s for %s.\r", query_cost_string (this, who, F_SELL + F_SHOP), nrof > 1 ? "them" : "it");
1178 }
1179 }
1180
1181 if (flag [FLAG_MONSTER])
1182 buf << describe_monster (who);
1183
1184 /* Is this item buildable? */
1185 if (flag [FLAG_IS_BUILDABLE])
1186 buf << "This is a buildable item.\r";
1187
1188 /* Does the object have a message? Don't show message for all object
1189 * types - especially if the first entry is a match
1190 */
1191 if (msg && type != EXIT && type != BOOK && type != CORPSE && !move_on && !has_dialogue ())
1192 {
1193 /* This is just a hack so when identifying the items, we print
1194 * out the extra message
1195 */
1196 if (need_identify (this) && flag [FLAG_IDENTIFIED])
1197 buf << "The object has a story:\r";
1198
1199 buf << msg << '\n';
1200 }
1201
1202 buf << '\n';
1203
1204 return std::string (buf.linearise (), buf.size ());
1205} 1060}
1206 1061
1207static void 1062static void
1208display_new_pickup (object *op) 1063display_new_pickup (object *op)
1209{ 1064{
1315} 1170}
1316 1171
1317int 1172int
1318command_search_items (object *op, char *params) 1173command_search_items (object *op, char *params)
1319{ 1174{
1320 char buf[MAX_BUF];
1321
1322 if (params == NULL) 1175 if (params == NULL)
1323 { 1176 {
1324 if (op->contr->search_str[0] == '\0') 1177 if (op->contr->search_str[0] == '\0')
1325 { 1178 {
1326 new_draw_info (NDI_UNIQUE, 0, op, "Example: search-items magic+1"); 1179 new_draw_info (NDI_UNIQUE, 0, op, "Example: search-items magic+1");
1329 return 1; 1182 return 1;
1330 } 1183 }
1331 1184
1332 op->contr->search_str[0] = '\0'; 1185 op->contr->search_str[0] = '\0';
1333 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off."); 1186 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off.");
1334 op->update_stats (); 1187 op->contr->queue_stats_update ();
1335 return 1; 1188 return 1;
1336 } 1189 }
1337 1190
1338 if (strlen (params) >= MAX_BUF) 1191 if (strlen (params) >= sizeof (op->contr->search_str))
1339 { 1192 {
1340 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long."); 1193 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long.");
1341 return 1; 1194 return 1;
1342 } 1195 }
1343 1196
1344 strcpy (op->contr->search_str, params); 1197 strcpy (op->contr->search_str, params);
1345 sprintf (buf, "Now searching for '%s'.", op->contr->search_str); 1198 new_draw_info (NDI_UNIQUE, 0, op, format ("Now searching for '%s'.", op->contr->search_str));
1346 new_draw_info (NDI_UNIQUE, 0, op, buf); 1199 op->contr->queue_stats_update ();
1347 op->update_stats ();
1348 1200
1349 return 1; 1201 return 1;
1350} 1202}
1351 1203
1204int
1205command_unlock (object *op, char *params)
1206{
1207 /* if the unlock command typed with nothing, unlock everything,
1208 * this might be bad
1209 */
1210 if (params == NULL)
1211 {
1212 for (object *item = op->inv; item; item = item->below)
1213 {
1214 item->clr_flag (FLAG_INV_LOCKED);
1215 //d// new_draw_info (NDI_UNIQUE, 0, op, "unlocked items with null param.");
1216 esrv_update_item (UPD_FLAGS, op, item);
1217 }
1218 return 0;
1219 }
1220
1221 /* if the unlock command is used with a param,
1222 * unlock what matches. i.e. unlock material, should unlock all the materials
1223 */
1224 for (object *item = op->inv; item; item = item->below)
1225 if (item->name.contains (params))
1226 {
1227 item->clr_flag (FLAG_INV_LOCKED);
1228 //d// new_draw_info (NDI_UNIQUE, 0, op, "unlocked items with a param.");
1229 esrv_update_item (UPD_FLAGS, op, item);
1230 }
1231
1232 return 0;
1233}
1234
1235int
1236command_lock (object *op, char *params)
1237{
1238 /* if the lock command is typed by itself, lock everything
1239 */
1240 if (params == NULL)
1241 {
1242 for (object *item = op->inv; item; item = item->below)
1243 {
1244 item->set_flag (FLAG_INV_LOCKED);
1245 //d// new_draw_info (NDI_UNIQUE, 0, op, "locked items with null param.");
1246 esrv_update_item (UPD_FLAGS, op, item);
1247 }
1248 return 0;
1249 }
1250
1251 /* if the lock command is used with a param, lock what matches.
1252 * i.e. lock material, should lock all the materials
1253 */
1254 for (object *item = op->inv; item; item = item->below)
1255 if (item->name.contains (params))
1256 {
1257 item->set_flag (FLAG_INV_LOCKED);
1258 //d// new_draw_info (NDI_UNIQUE, 0, op, "locked items with param.");
1259 esrv_update_item (UPD_FLAGS, op, item);
1260 }
1261
1262 return 0;
1263}
1264
1265/* op should be a player, params is any params.
1266 * If no params given, we print out the currently marked object.
1267 * otherwise, try to find a matching object - try best match first.
1268 */
1269int
1270command_mark (object *op, char *params)
1271{
1272 if (!params)
1273 {
1274 if (object *mark = op->mark ())
1275 op->statusmsg (format ("%s is marked.", query_name (mark)));
1276 else
1277 op->failmsg ("You have no marked object.");
1278 }
1279 else
1280 {
1281 if (object *mark = find_best_object_match (op, params))
1282 {
1283 op->contr->mark = mark;
1284 op->statusmsg (format ("Marked item %s", query_name (mark)));
1285 }
1286 else
1287 op->failmsgf ("Could not find an object that matches %s", params);
1288 }
1289
1290 return 0; /*shouldnt get here */
1291}
1292

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines