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.15 by root, Tue Sep 12 19:20:08 2006 UTC vs.
Revision 1.31 by root, Fri Dec 22 16:34:00 2006 UTC

16 16
17 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
18 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 20
21 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>
22 22
23 Object (handling) commands 23 Object (handling) commands
24*/ 24*/
25 25
26#include <global.h> 26#include <global.h>
34 34
35/* 35/*
36 * Object id parsing functions 36 * Object id parsing functions
37 */ 37 */
38 38
39#define OBLINKMALLOC(p) if(!((p)=(objectlink *)malloc(sizeof(objectlink))))\
40 fatal(OUT_OF_MEMORY);
41
42#define ADD_ITEM(NEW,COUNT)\ 39#define ADD_ITEM(NEW,COUNT)\
43 if(!first) {\ 40 if(!first) {\
44 OBLINKMALLOC(first);\ 41 first = new objectlink;\
45 last=first;\ 42 last=first;\
46 } else {\ 43 } else {\
47 OBLINKMALLOC(last->next);\ 44 last->next = new objectlink;\
48 last=last->next;\ 45 last=last->next;\
49 }\ 46 }\
50 last->next=NULL;\ 47 last->next=0;\
51 last->ob=(NEW);\ 48 last->ob=(NEW);\
52 last->id=(COUNT); 49 last->id=(COUNT);
53 50
54/** 51/**
55 * Search the inventory of 'pl' for what matches best with params. 52 * Search the inventory of 'pl' for what matches best with params.
262 /* IF the player is flying & trying to take the item out of a container 259 /* IF the player is flying & trying to take the item out of a container
263 * that is in his inventory, let him. tmp->env points to the container 260 * that is in his inventory, let him. tmp->env points to the container
264 * (sack, luggage, etc), tmp->env->env then points to the player (nested 261 * (sack, luggage, etc), tmp->env->env then points to the player (nested
265 * containers not allowed as of now) 262 * containers not allowed as of now)
266 */ 263 */
267 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) && tmp->in_player () != pl)
268 { 265 {
269 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!");
270 return; 267 return;
271 } 268 }
269
272 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 270 if (QUERY_FLAG (tmp, FLAG_NO_DROP))
273 return; 271 return;
272
274 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))
275 { 274 {
276 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!");
277 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
278 if (pl->type == PLAYER) 278 if (pl->type == PLAYER)
279 esrv_del_item (pl->contr, tmp->count); 279 esrv_del_item (pl->contr, tmp->count);
280 if (!QUERY_FLAG (tmp, FLAG_REMOVED)) 280
281 remove_ob (tmp); 281 tmp->destroy ();
282 free_object (tmp);
283 return; 282 return;
284 } 283 }
285 284
286 if (nrof > tmp_nrof || nrof == 0) 285 if (nrof > tmp_nrof || nrof == 0)
287 nrof = tmp_nrof; 286 nrof = tmp_nrof;
287
288 /* 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 */
289 weight = tmp->weight * nrof; 289 weight = tmp->weight * nrof;
290 if (tmp->inv) 290 if (tmp->inv)
291 weight += tmp->carrying * (100 - tmp->stats.Str) / 100; 291 weight += tmp->carrying * (100 - tmp->stats.Str) / 100;
292
292 if (pl->stats.Str <= MAX_STAT) 293 if (pl->stats.Str <= MAX_STAT)
293 effective_weight_limit = weight_limit[pl->stats.Str]; 294 effective_weight_limit = weight_limit[pl->stats.Str];
294 else 295 else
295 effective_weight_limit = weight_limit[MAX_STAT]; 296 effective_weight_limit = weight_limit[MAX_STAT];
297
296 if ((pl->weight + pl->carrying + weight) > effective_weight_limit) 298 if ((pl->weight + pl->carrying + weight) > effective_weight_limit)
297 { 299 {
298 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.");
299 return; 301 return;
300 } 302 }
303
301 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ)) 304 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ))
302 SET_FLAG (tmp, FLAG_WAS_WIZ); 305 SET_FLAG (tmp, FLAG_WAS_WIZ);
306
303 if (nrof != tmp_nrof) 307 if (nrof != tmp_nrof)
304 { 308 {
305 object *tmp2 = tmp; 309 object *tmp2 = tmp;
306 tag_t tmp2_tag = tmp2->count;
307 310
308 tmp = get_split_ob (tmp, nrof); 311 tmp = get_split_ob (tmp, nrof);
309 if (!tmp) 312 if (!tmp)
310 { 313 {
311 new_draw_info (NDI_UNIQUE, 0, pl, errmsg); 314 new_draw_info (NDI_UNIQUE, 0, pl, errmsg);
312 return; 315 return;
313 } 316 }
317
314 /* Tell a client what happened rest of objects */ 318 /* Tell a client what happened rest of objects */
315 if (pl->type == PLAYER) 319 if (pl->type == PLAYER)
316 { 320 {
317 if (was_destroyed (tmp2, tmp2_tag)) 321 if (tmp2->destroyed ())
318 esrv_del_item (pl->contr, tmp2_tag); 322 esrv_del_item (pl->contr, tmp2->count);
319 else 323 else
320 esrv_send_item (pl, tmp2); 324 esrv_send_item (pl, tmp2);
321 } 325 }
322 } 326 }
323 else 327 else
328 */ 332 */
329 if (!QUERY_FLAG (tmp, FLAG_REMOVED)) 333 if (!QUERY_FLAG (tmp, FLAG_REMOVED))
330 { 334 {
331 if (tmp->env && pl->type == PLAYER) 335 if (tmp->env && pl->type == PLAYER)
332 esrv_del_item (pl->contr, tmp->count); 336 esrv_del_item (pl->contr, tmp->count);
333 remove_ob (tmp); /* Unlink it */ 337 tmp->remove (); /* Unlink it */
334 } 338 }
335 } 339 }
336 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 340 if (QUERY_FLAG (tmp, FLAG_UNPAID))
337 (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));
338 else 342 else
360 /* Update the container the object was in */ 364 /* Update the container the object was in */
361 if (env && env != pl && env != op) 365 if (env && env != pl && env != op)
362 esrv_update_item (UPD_WEIGHT, pl, env); 366 esrv_update_item (UPD_WEIGHT, pl, env);
363} 367}
364 368
365 369/* modified slightly to allow monsters use this -b.t. 5-31-95 */
366void 370void
367pick_up (object *op, object *alt) 371pick_up (object *op, object *alt)
368
369/* modified slightly to allow monsters use this -b.t. 5-31-95 */
370{ 372{
371 int need_fix_tmp = 0; 373 int need_fix_tmp = 0;
372 object *tmp = NULL; 374 object *tmp = NULL;
373 mapstruct *tmp_map = NULL; 375 maptile *tmp_map = NULL;
374 int count; 376 int count;
375 tag_t tag;
376 377
377 /* Decide which object to pick. */ 378 /* Decide which object to pick. */
378 if (alt) 379 if (alt)
379 { 380 {
380 if (!can_pick (op, alt)) 381 if (!can_pick (op, alt))
389 if (op->below == NULL || !can_pick (op, op->below)) 390 if (op->below == NULL || !can_pick (op, op->below))
390 { 391 {
391 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.");
392 goto leave; 393 goto leave;
393 } 394 }
395
394 tmp = op->below; 396 tmp = op->below;
395 } 397 }
396 398
397 /* Try to catch it. */ 399 /* Try to catch it. */
398 tmp_map = tmp->map; 400 tmp_map = tmp->map;
431 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))
432 break; /* General container comes next */ 434 break; /* General container comes next */
433 if (!alt) 435 if (!alt)
434 alt = op; /* No free containers */ 436 alt = op; /* No free containers */
435 } 437 }
438
436 if (tmp->env == alt) 439 if (tmp->env == alt)
437 { 440 {
438 /* here it could be possible to check rent, 441 /* here it could be possible to check rent,
439 * if someone wants to implement it 442 * if someone wants to implement it
440 */ 443 */
449 { 452 {
450 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!");
451 goto leave; 454 goto leave;
452 } 455 }
453 456
454 tag = tmp->count;
455 pick_up_object (op, alt, tmp, count); 457 pick_up_object (op, alt, tmp, count);
458
456 if (was_destroyed (tmp, tag) || tmp->env) 459 if (tmp->destroyed () || tmp->env)
457 need_fix_tmp = 0; 460 need_fix_tmp = 0;
461
458 if (op->type == PLAYER) 462 if (op->type == PLAYER)
459 op->contr->count = 0; 463 op->contr->count = 0;
464
460 goto leave; 465 goto leave;
461 466
462leave: 467leave:
463 if (need_fix_tmp) 468 if (need_fix_tmp)
464 fix_stopped_item (tmp, tmp_map, op); 469 fix_stopped_item (tmp, tmp_map, op);
480 else 485 else
481 { 486 {
482 tmp = op->above; 487 tmp = op->above;
483 if (tmp) 488 if (tmp)
484 while (tmp->above) 489 while (tmp->above)
485 {
486 tmp = tmp->above; 490 tmp = tmp->above;
487 } 491
488 if (!tmp) 492 if (!tmp)
489 tmp = op->below; 493 tmp = op->below;
490 } 494 }
491 495
492 if (tmp == NULL) 496 if (tmp == NULL)
554 * so this function isn't named very good anymore. 558 * so this function isn't named very good anymore.
555 */ 559 */
556void 560void
557put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof) 561put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof)
558{ 562{
559 tag_t tmp_tag, tmp2_tag;
560 object *tmp2, *sack2; 563 object *tmp2, *sack2;
561 char buf[MAX_BUF]; 564 char buf[MAX_BUF];
562 565
563 if (sack == tmp) 566 if (sack == tmp)
564 return; /* Can't put an object in itself */ 567 return; /* Can't put an object in itself */
568
565 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 569 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP))
566 { 570 {
567 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));
568 return; 572 return;
569 } 573 }
574
570 if (tmp->type == CONTAINER && tmp->inv) 575 if (tmp->type == CONTAINER && tmp->inv)
571 { 576 {
572 577
573 /* 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
574 * we instead move the contents of that container into the active 579 * we instead move the contents of that container into the active
575 * 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.
576 */ 581 */
577 sack2 = tmp; 582 sack2 = tmp;
578 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
579 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) 585 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp)
580 { 586 {
581 tmp = tmp2->below; 587 tmp = tmp2->below;
588
582 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)))
583 { 590 {
584 put_object_in_sack (op, sack, tmp2, 0); 591 put_object_in_sack (op, sack, tmp2, 0);
585 } 592 }
586 else 593 else
588 sprintf (buf, "Your %s fills up.", query_name (sack)); 595 sprintf (buf, "Your %s fills up.", query_name (sack));
589 new_draw_info (NDI_UNIQUE, 0, op, buf); 596 new_draw_info (NDI_UNIQUE, 0, op, buf);
590 break; 597 break;
591 } 598 }
592 } 599 }
600
593 esrv_update_item (UPD_WEIGHT, op, sack2); 601 esrv_update_item (UPD_WEIGHT, op, sack2);
594 return; 602 return;
595 } 603 }
596 604
597 /* Don't worry about this for containers - our caller should have 605 /* Don't worry about this for containers - our caller should have
599 */ 607 */
600 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)))
601 return; 609 return;
602 610
603 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 611 if (QUERY_FLAG (tmp, FLAG_APPLIED))
604 {
605 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 612 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
606 return; 613 return;
607 }
608 614
609 /* 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 */
610 if (nrof && tmp->nrof != nrof) 616 if (nrof && tmp->nrof != nrof)
611 { 617 {
612 object *tmp2 = tmp; 618 object *tmp2 = tmp;
613 619
614 tmp2_tag = tmp2->count;
615 tmp = get_split_ob (tmp, nrof); 620 tmp = get_split_ob (tmp, nrof);
616 621
617 if (!tmp) 622 if (!tmp)
618 { 623 {
619 new_draw_info (NDI_UNIQUE, 0, op, errmsg); 624 new_draw_info (NDI_UNIQUE, 0, op, errmsg);
620 return; 625 return;
621 } 626 }
622 /* Tell a client what happened other objects */ 627 /* Tell a client what happened other objects */
623 if (was_destroyed (tmp2, tmp2_tag)) 628 if (tmp2->destroyed ())
624 esrv_del_item (op->contr, tmp2_tag); 629 esrv_del_item (op->contr, tmp2->count);
625 else /* this can proably be replaced with an update */ 630 else /* this can proably be replaced with an update */
626 esrv_send_item (op, tmp2); 631 esrv_send_item (op, tmp2);
627 } 632 }
628 else 633 else
629 remove_ob (tmp); 634 tmp->remove ();
630 635
631 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));
632 tmp_tag = tmp->count;
633 tmp2 = insert_ob_in_ob (tmp, sack); 637 tmp2 = insert_ob_in_ob (tmp, sack);
634 fix_player (op); /* This is overkill, fix_player() is called somewhere */ 638 op->update_stats (); /* This is overkill, fix_player() is called somewhere */
635 /* in object.c */ 639 /* in object.c */
636 640
637 /* If an object merged (and thus, different object), we need to 641 /* If an object merged (and thus, different object), we need to
638 * delete the original. 642 * delete the original.
639 */ 643 */
640 if (tmp2 != tmp) 644 if (tmp2 != tmp)
641 esrv_del_item (op->contr, tmp_tag); 645 esrv_del_item (op->contr, tmp->count);
642 646
643 esrv_send_item (op, tmp2); 647 esrv_send_item (op, tmp2);
644 648
645 /* update the sacks weight */ 649 /* update the sacks weight */
646 esrv_update_item (UPD_WEIGHT, op, sack); 650 esrv_update_item (UPD_WEIGHT, op, sack);
663 667
664 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 668 if (QUERY_FLAG (tmp, FLAG_APPLIED))
665 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 669 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
666 return; /* can't unapply it */ 670 return; /* can't unapply it */
667 671
668 /* 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
669 * off 673 * off
670 */ 674 */
671 if (nrof && tmp->nrof != nrof) 675 if (nrof && tmp->nrof != nrof)
672 { 676 {
673 object *tmp2 = tmp; 677 object *tmp2 = tmp;
674 tag_t tmp2_tag = tmp2->count;
675 678
676 tmp = get_split_ob (tmp, nrof); 679 tmp = get_split_ob (tmp, nrof);
677 if (!tmp) 680 if (!tmp)
678 { 681 {
679 new_draw_info (NDI_UNIQUE, 0, op, errmsg); 682 new_draw_info (NDI_UNIQUE, 0, op, errmsg);
682 /* 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
683 * original object 686 * original object
684 */ 687 */
685 if (op->type == PLAYER) 688 if (op->type == PLAYER)
686 { 689 {
687 if (was_destroyed (tmp2, tmp2_tag)) 690 if (tmp2->destroyed ())
688 esrv_del_item (op->contr, tmp2_tag); 691 esrv_del_item (op->contr, tmp2->count);
689 else 692 else
690 esrv_send_item (op, tmp2); 693 esrv_send_item (op, tmp2);
691 } 694 }
692 } 695 }
693 else 696 else
694 remove_ob (tmp); 697 tmp->remove ();
695 698
696 if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op))) 699 if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op)))
697 return; 700 return;
698 701
699 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 702 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP))
700 { 703 {
701 sprintf (buf, "You drop the %s.", query_name (tmp)); 704 sprintf (buf, "You drop the %s.", query_name (tmp));
702 new_draw_info (NDI_UNIQUE, 0, op, buf); 705 new_draw_info (NDI_UNIQUE, 0, op, buf);
703 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.");
707
704 if (op->type == PLAYER) 708 if (op->type == PLAYER)
705 esrv_del_item (op->contr, tmp->count); 709 esrv_del_item (op->contr, tmp->count);
706 free_object (tmp); 710
707 fix_player (op); 711 tmp->destroy ();
712 op->update_stats ();
708 return; 713 return;
709 } 714 }
710 715
711/* If SAVE_INTERVAL is commented out, we never want to save 716/* If SAVE_INTERVAL is commented out, we never want to save
712 * the player here. 717 * the player here.
717 * of what he is dropping? 722 * of what he is dropping?
718 */ 723 */
719 if (op->type == PLAYER && !QUERY_FLAG (tmp, FLAG_UNPAID) && 724 if (op->type == PLAYER && !QUERY_FLAG (tmp, FLAG_UNPAID) &&
720 (tmp->nrof ? tmp->value * tmp->nrof : tmp->value > 2000) && (op->contr->last_save_time + SAVE_INTERVAL) <= time (NULL)) 725 (tmp->nrof ? tmp->value * tmp->nrof : tmp->value > 2000) && (op->contr->last_save_time + SAVE_INTERVAL) <= time (NULL))
721 { 726 {
722 save_player (op, 1); 727 op->contr->save ();
723 op->contr->last_save_time = time (NULL); 728 op->contr->last_save_time = time (NULL);
724 } 729 }
725#endif /* SAVE_INTERVAL */ 730#endif /* SAVE_INTERVAL */
726 731
727 if (op->type == PLAYER) 732 if (op->type == PLAYER)
728 esrv_del_item (op->contr, tmp->count); 733 esrv_del_item (op->contr, tmp->count);
729 734
730 /* Call this before we update the various windows/players. At least 735 /* Call this before we update the various windows/players. At least
731 * that we, we know the weight is correct. 736 * that we, we know the weight is correct.
732 */ 737 */
733 fix_player (op); /* This is overkill, fix_player() is called somewhere */ 738 op->update_stats (); /* This is overkill, fix_player() is called somewhere */
734 /* in object.c */ 739 /* in object.c */
735 740
736 if (op->type == PLAYER) 741 if (op->type == PLAYER)
737 { 742 {
738 op->contr->socket.update_look = 1;
739 /* Need to update the weight for the player */ 743 /* Need to update the weight for the player */
740 esrv_send_item (op, op); 744 esrv_send_item (op, op);
745 op->contr->ns->floorbox_update ();
741 } 746 }
742 747
743 for (floor = get_map_ob (op->map, op->x, op->y); floor; floor = floor->above) 748 for (floor = GET_MAP_OB (op->map, op->x, op->y); floor; floor = floor->above)
744 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op))) 749 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op)))
745 return; 750 return;
746 751
747 if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY) 752 if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY)
748 sell_item (tmp, op); 753 sell_item (tmp, op);
767 if (tmp->env && tmp->env->type != PLAYER) 772 if (tmp->env && tmp->env->type != PLAYER)
768 { 773 {
769 /* Just toss the object - probably shouldn't be hanging 774 /* Just toss the object - probably shouldn't be hanging
770 * around anyways 775 * around anyways
771 */ 776 */
772 remove_ob (tmp); 777 tmp->remove ();
773 free_object (tmp); 778 tmp->destroy ();
774 return; 779 return;
775 } 780 }
776 else 781 else
777 { 782 {
778 while (tmp != NULL && tmp->invisible) 783 while (tmp != NULL && tmp->invisible)
797 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped."); 802 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped.");
798#endif 803#endif
799 return; 804 return;
800 } 805 }
801 806
802 if (op->type == PLAYER) 807 if (op->type == PLAYER && op->contr->last_used == tmp)
803 { 808 op->contr->last_used = tmp->below ? tmp->below
804 if (op->contr->last_used == tmp && op->contr->last_used_id == tmp->count) 809 : tmp->above ? tmp->above
805 { 810 : 0;
806 object *n = NULL;
807
808 if (tmp->below != NULL)
809 n = tmp->below;
810 else if (tmp->above != NULL)
811 n = tmp->above;
812 op->contr->last_used = n;
813 if (n != NULL)
814 op->contr->last_used_id = n->count;
815 else
816 op->contr->last_used_id = 0;
817 }
818 };
819 811
820 if (op->container) 812 if (op->container)
821 { 813 {
822 if (op->type == PLAYER) 814 if (op->type == PLAYER)
823 {
824 put_object_in_sack (op, op->container, tmp, op->contr->count); 815 put_object_in_sack (op, op->container, tmp, op->contr->count);
825 }
826 else 816 else
827 {
828 put_object_in_sack (op, op->container, tmp, 0); 817 put_object_in_sack (op, op->container, tmp, 0);
829 };
830 } 818 }
831 else 819 else
832 { 820 {
833 if (op->type == PLAYER) 821 if (op->type == PLAYER)
834 {
835 drop_object (op, tmp, op->contr->count); 822 drop_object (op, tmp, op->contr->count);
836 }
837 else 823 else
838 {
839 drop_object (op, tmp, 0); 824 drop_object (op, tmp, 0);
840 };
841 } 825 }
826
842 if (op->type == PLAYER) 827 if (op->type == PLAYER)
843 op->contr->count = 0; 828 op->contr->count = 0;
844} 829}
845 830
846 831
954 } 939 }
955 } 940 }
956 curinv = nextinv; 941 curinv = nextinv;
957 } 942 }
958 } 943 }
959 op->contr->socket.update_look = 1; 944
945 op->contr->ns->floorbox_update ();
960 946
961/* draw_look(op);*/ 947/* draw_look(op);*/
962 return 0; 948 return 0;
963} 949}
964 950
994 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); 980 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop.");
995 } 981 }
996 if (op->type == PLAYER) 982 if (op->type == PLAYER)
997 { 983 {
998 op->contr->count = 0; 984 op->contr->count = 0;
999 op->contr->socket.update_look = 1; 985 op->contr->ns->floorbox_update ();
1000 }; 986 };
1001 987
1002/* draw_look(op);*/ 988/* draw_look(op);*/
1003 return 0; 989 return 0;
1004} 990}
1038{ 1024{
1039 object *tmp; 1025 object *tmp;
1040 1026
1041 if (!op || !op->contr) 1027 if (!op || !op->contr)
1042 return NULL; 1028 return NULL;
1029
1043 if (!op->contr->mark) 1030 if (!op->contr->mark)
1044 { 1031 {
1045
1046/* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/ 1032/* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/
1047 return NULL; 1033 return 0;
1048 } 1034 }
1035
1049 /* This may seem like overkill, but we need to make sure that they 1036 /* This may seem like overkill, but we need to make sure that they
1050 * player hasn't dropped the item. We use count on the off chance that 1037 * player hasn't dropped the item. We use count on the off chance that
1051 * an item got reincarnated at some point. 1038 * an item got reincarnated at some point.
1052 */ 1039 */
1053 for (tmp = op->inv; tmp; tmp = tmp->below) 1040 for (tmp = op->inv; tmp; tmp = tmp->below)
1054 { 1041 {
1055 if (tmp->invisible) 1042 if (tmp->invisible)
1056 continue; 1043 continue;
1044
1057 if (tmp == op->contr->mark) 1045 if (tmp == op->contr->mark)
1058 { 1046 {
1059 if (tmp->count == op->contr->mark_count) 1047 if (!tmp->destroyed ())
1060 return tmp; 1048 return tmp;
1061 else 1049 else
1062 { 1050 {
1063 op->contr->mark = NULL; 1051 op->contr->mark = 0;
1064 op->contr->mark_count = 0;
1065
1066/* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/ 1052/* new_draw_info(NDI_UNIQUE,0,op,"You have no marked object");*/
1067 return NULL; 1053 return 0;
1068 } 1054 }
1069 } 1055 }
1070 } 1056 }
1057
1071 return NULL; 1058 return 0;
1072} 1059}
1073 1060
1074 1061
1075/* op should be a player, params is any params. 1062/* op should be a player, params is any params.
1076 * If no params given, we print out the currently marked object. 1063 * If no params given, we print out the currently marked object.
1079int 1066int
1080command_mark (object *op, char *params) 1067command_mark (object *op, char *params)
1081{ 1068{
1082 if (!op->contr) 1069 if (!op->contr)
1083 return 1; 1070 return 1;
1071
1084 if (!params) 1072 if (!params)
1085 { 1073 {
1086 object *mark = find_marked_object (op); 1074 object *mark = find_marked_object (op);
1087 1075
1088 if (!mark) 1076 if (!mark)
1100 return 1; 1088 return 1;
1101 } 1089 }
1102 else 1090 else
1103 { 1091 {
1104 op->contr->mark = mark1; 1092 op->contr->mark = mark1;
1105 op->contr->mark_count = mark1->count;
1106 new_draw_info_format (NDI_UNIQUE, 0, op, "Marked item %s", query_name (mark1)); 1093 new_draw_info_format (NDI_UNIQUE, 0, op, "Marked item %s", query_name (mark1));
1107 return 0; 1094 return 0;
1108 } 1095 }
1109 } 1096 }
1097
1110 return 0; /*shouldnt get here */ 1098 return 0; /*shouldnt get here */
1111} 1099}
1112 1100
1113 1101
1114/* op is the player 1102/* op is the player
1447 new_draw_info_format (NDI_UNIQUE, 0, op, "%d MAGICDEVICE", i & PU_MAGIC_DEVICE ? 1 : 0); 1435 new_draw_info_format (NDI_UNIQUE, 0, op, "%d MAGICDEVICE", i & PU_MAGIC_DEVICE ? 1 : 0);
1448 1436
1449 new_draw_info_format (NDI_UNIQUE, 0, op, "%d NOT CURSED", i & PU_NOT_CURSED ? 1 : 0); 1437 new_draw_info_format (NDI_UNIQUE, 0, op, "%d NOT CURSED", i & PU_NOT_CURSED ? 1 : 0);
1450 1438
1451 new_draw_info_format (NDI_UNIQUE, 0, op, "%d JEWELS", i & PU_JEWELS ? 1 : 0); 1439 new_draw_info_format (NDI_UNIQUE, 0, op, "%d JEWELS", i & PU_JEWELS ? 1 : 0);
1440 new_draw_info_format (NDI_UNIQUE, 0, op, "%d FLESH", i & PU_FLESH ? 1 : 0);
1452 1441
1453 new_draw_info_format (NDI_UNIQUE, 0, op, ""); 1442 new_draw_info_format (NDI_UNIQUE, 0, op, "");
1454} 1443}
1455 1444
1456int 1445int
1458{ 1447{
1459 uint32 i; 1448 uint32 i;
1460 static const char *names[] = { 1449 static const char *names[] = {
1461 "debug", "inhibit", "stop", "food", "drink", "valuables", "bow", "arrow", "helmet", 1450 "debug", "inhibit", "stop", "food", "drink", "valuables", "bow", "arrow", "helmet",
1462 "shield", "armour", "boots", "gloves", "cloak", "key", "missile", "allweapon", 1451 "shield", "armour", "boots", "gloves", "cloak", "key", "missile", "allweapon",
1463 "magical", "potion", "spellbook", "skillscroll", "readables", "magicdevice", "notcursed", "jewels", NULL 1452 "magical", "potion", "spellbook", "skillscroll", "readables", "magicdevice", "notcursed",
1453 "jewels", "flesh", NULL
1464 }; 1454 };
1465 static uint32 modes[] = { 1455 static uint32 modes[] = {
1466 PU_DEBUG, PU_INHIBIT, PU_STOP, PU_FOOD, PU_DRINK, PU_VALUABLES, PU_BOW, PU_ARROW, PU_HELMET, 1456 PU_DEBUG, PU_INHIBIT, PU_STOP, PU_FOOD, PU_DRINK, PU_VALUABLES, PU_BOW, PU_ARROW, PU_HELMET,
1467 PU_SHIELD, PU_ARMOUR, PU_BOOTS, PU_GLOVES, PU_CLOAK, PU_KEY, PU_MISSILEWEAPON, PU_ALLWEAPON, 1457 PU_SHIELD, PU_ARMOUR, PU_BOOTS, PU_GLOVES, PU_CLOAK, PU_KEY, PU_MISSILEWEAPON, PU_ALLWEAPON,
1468 PU_MAGICAL, PU_POTION, PU_SPELLBOOK, PU_SKILLSCROLL, PU_READABLES, PU_MAGIC_DEVICE, PU_NOT_CURSED, PU_JEWELS, 0 1458 PU_MAGICAL, PU_POTION, PU_SPELLBOOK, PU_SKILLSCROLL, PU_READABLES, PU_MAGIC_DEVICE, PU_NOT_CURSED,
1459 PU_JEWELS, PU_FLESH, 0
1469 }; 1460 };
1470 1461
1471 if (!params) 1462 if (!params)
1472 { 1463 {
1473 /* if the new mode is used, just print the settings */ 1464 /* if the new mode is used, just print the settings */
1570 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'."); 1561 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'.");
1571 return 1; 1562 return 1;
1572 } 1563 }
1573 op->contr->search_str[0] = '\0'; 1564 op->contr->search_str[0] = '\0';
1574 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off."); 1565 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off.");
1575 fix_player (op); 1566 op->update_stats ();
1576 return 1; 1567 return 1;
1577 } 1568 }
1578 if ((int) strlen (params) >= MAX_BUF) 1569 if ((int) strlen (params) >= MAX_BUF)
1579 { 1570 {
1580 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long."); 1571 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long.");
1581 return 1; 1572 return 1;
1582 } 1573 }
1583 strcpy (op->contr->search_str, params); 1574 strcpy (op->contr->search_str, params);
1584 sprintf (buf, "Searching for '%s'.", op->contr->search_str); 1575 sprintf (buf, "Searching for '%s'.", op->contr->search_str);
1585 new_draw_info (NDI_UNIQUE, 0, op, buf); 1576 new_draw_info (NDI_UNIQUE, 0, op, buf);
1586 fix_player (op); 1577 op->update_stats ();
1587 return 1; 1578 return 1;
1588} 1579}
1589 1580
1590/*
1591 * Changing the custom name of an item
1592 *
1593 * Syntax is: rename <what object> to <new name>
1594 * if '<what object>' is omitted, marked object is used
1595 * if 'to <new name>' is omitted, custom name is cleared
1596 *
1597 * Names are considered for all purpose having a length <=127 (max length sent to client
1598 * by server) */
1599
1600int
1601command_rename_item (object *op, char *params)
1602{
1603 char buf[VERY_BIG_BUF];
1604 int itemnumber;
1605 object *item = NULL;
1606 char *closebrace;
1607 size_t counter;
1608
1609 if (params)
1610 {
1611 /* Let's skip white spaces */
1612 while (' ' == *params)
1613 params++;
1614
1615 /* Checking the first part */
1616 if ((itemnumber = atoi (params)) != 0)
1617 {
1618 for (item = op->inv; item && ((item->count != (tag_t) itemnumber) || item->invisible); item = item->below);
1619 if (!item)
1620 {
1621 new_draw_info (NDI_UNIQUE, 0, op, "Tried to rename an invalid item.");
1622 return 1;
1623 }
1624 while (isdigit (*params) || ' ' == *params)
1625 params++;
1626 }
1627 else if ('<' == *params)
1628 {
1629 /* Got old name, let's get it & find appropriate matching item */
1630 closebrace = strchr (params, '>');
1631 if (!closebrace)
1632 {
1633 new_draw_info (NDI_UNIQUE, 0, op, "Syntax error!");
1634 return 1;
1635 }
1636
1637 /* Sanity check for buffer overruns */
1638 if ((closebrace - params) > 127)
1639 {
1640 new_draw_info (NDI_UNIQUE, 0, op, "Old name too long (up to 127 characters allowed)!");
1641 return 1;
1642 }
1643
1644 /* Copy the old name */
1645 assign (buf, params + 1, closebrace - params - 1);
1646
1647 /* Find best matching item */
1648 item = find_best_object_match (op, buf);
1649 if (!item)
1650 {
1651 new_draw_info (NDI_UNIQUE, 0, op, "Could not find a matching item to rename.");
1652 return 1;
1653 }
1654
1655 /* Now need to move pointer to just after > */
1656 params = closebrace + 1;
1657 while (' ' == *params)
1658 params++;
1659
1660 }
1661 else
1662 {
1663 /* Use marked item */
1664 item = find_marked_object (op);
1665 if (!item)
1666 {
1667 new_draw_info (NDI_UNIQUE, 0, op, "No marked item to rename.");
1668 return 1;
1669 }
1670 }
1671
1672 /* Now let's find the new name */
1673 if (!strncmp (params, "to ", 3))
1674 {
1675 params += 3;
1676 while (' ' == *params)
1677 params++;
1678 if ('<' != *params)
1679 {
1680 new_draw_info (NDI_UNIQUE, 0, op, "Syntax error, expecting < at start of new name!");
1681 return 1;
1682 }
1683 closebrace = strchr (params + 1, '>');
1684 if (!closebrace)
1685 {
1686 new_draw_info (NDI_UNIQUE, 0, op, "Syntax error, expecting > at end of new name!");
1687 return 1;
1688 }
1689
1690 /* Sanity check for buffer overruns */
1691 if ((closebrace - params) > 127)
1692 {
1693 new_draw_info (NDI_UNIQUE, 0, op, "New name too long (up to 127 characters allowed)!");
1694 return 1;
1695 }
1696
1697 /* Copy the new name */
1698 assign (buf, params + 1, closebrace - params - 1);
1699
1700 /* Let's check it for weird characters */
1701 for (counter = 0; counter < strlen (buf); counter++)
1702 {
1703 if (isalnum (buf[counter]))
1704 continue;
1705 if (' ' == buf[counter])
1706 continue;
1707 if ('\'' == buf[counter])
1708 continue;
1709 if ('+' == buf[counter])
1710 continue;
1711 if ('_' == buf[counter])
1712 continue;
1713 if ('-' == buf[counter])
1714 continue;
1715
1716 /* If we come here, then the name contains an invalid character...
1717 tell the player & exit */
1718 new_draw_info (NDI_UNIQUE, 0, op, "Invalid new name!");
1719 return 1;
1720 }
1721
1722 }
1723 else
1724 {
1725 /* If param contains something, then syntax error... */
1726 if (strlen (params))
1727 {
1728 new_draw_info (NDI_UNIQUE, 0, op, "Syntax error, expected 'to <' after old name!");
1729 return 1;
1730 }
1731 /* New name is empty */
1732 buf[0] = '\0';
1733 }
1734 }
1735 else
1736 {
1737 /* Last case: params==NULL */
1738 item = find_marked_object (op);
1739 if (!item)
1740 {
1741 new_draw_info (NDI_UNIQUE, 0, op, "No marked item to rename.");
1742 return 1;
1743 }
1744 buf[0] = '\0';
1745 }
1746
1747 if (QUERY_FLAG (item, FLAG_UNPAID))
1748 {
1749 new_draw_info (NDI_UNIQUE, 0, op, "You can't rename an unpaid item! You should pay for it first.");
1750 return 1;
1751 }
1752
1753 /* Coming here, everything is fine... */
1754 if (!strlen (buf))
1755 {
1756 /* Clear custom name */
1757 if (item->custom_name)
1758 {
1759 item->custom_name = 0;
1760
1761 new_draw_info_format (NDI_UNIQUE, 0, op, "You stop calling your %s with weird names.",
1762 query_base_name (item, item->nrof > 1 ? 1 : 0));
1763 esrv_update_item (UPD_NAME, op, item);
1764 }
1765 else
1766 {
1767 new_draw_info (NDI_UNIQUE, 0, op, "This item has no custom name.");
1768 }
1769 }
1770 else
1771 {
1772 /* Set custom name */
1773 item->custom_name = buf;
1774
1775 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);
1776 esrv_update_item (UPD_NAME, op, item);
1777 }
1778
1779 return 1;
1780}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines