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.25 by root, Tue Dec 12 21:39:57 2006 UTC vs.
Revision 1.39 by root, Sat Feb 10 21:01:10 2007 UTC

1/* 1/*
2 CrossFire, A Multiplayer game for X-windows 2 * CrossFire, A Multiplayer game for X-windows
3 3 *
4 * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
4 Copyright (C) 2002 Mark Wedel & Crossfire Development Team 5 * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5 Copyright (C) 1992 Frank Tore Johansen 6 * Copyright (C) 1992 Frank Tore Johansen
6 7 *
7 This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version. 11 * (at your option) any later version.
11 12 *
12 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,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details. 16 * GNU General Public License for more details.
16 17 *
17 You should have received a copy of the GNU General Public License 18 * You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software 19 * along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 21 *
21 The author can be reached via e-mail to <crossfire@schmorp.de> 22 * The author can be reached via e-mail to <crossfire@schmorp.de>
23 *
24 */
22 25
26/*
23 Object (handling) commands 27 * Object (handling) commands
24*/ 28 */
25 29
26#include <global.h> 30#include <global.h>
27#include <loader.h> 31#include <loader.h>
28#include <skills.h> 32#include <skills.h>
29#ifndef __CEXTRACT__
30# include <sproto.h> 33#include <sproto.h>
31#endif
32#include <living.h> 34#include <living.h>
33#include <math.h> 35#include <math.h>
34 36
35/* 37/*
36 * Object id parsing functions 38 * Object id parsing functions
259 /* IF the player is flying & trying to take the item out of a container 261 /* IF the player is flying & trying to take the item out of a container
260 * that is in his inventory, let him. tmp->env points to the container 262 * that is in his inventory, let him. tmp->env points to the container
261 * (sack, luggage, etc), tmp->env->env then points to the player (nested 263 * (sack, luggage, etc), tmp->env->env then points to the player (nested
262 * containers not allowed as of now) 264 * containers not allowed as of now)
263 */ 265 */
264 if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && is_player_inv (tmp) != pl) 266 if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && tmp->in_player () != pl)
265 { 267 {
266 new_draw_info (NDI_UNIQUE, 0, pl, "You are levitating, you can't reach the ground!"); 268 new_draw_info (NDI_UNIQUE, 0, pl, "You are levitating, you can't reach the ground!");
267 return; 269 return;
268 } 270 }
269 271
273 if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) && !QUERY_FLAG (pl, FLAG_WAS_WIZ)) 275 if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) && !QUERY_FLAG (pl, FLAG_WAS_WIZ))
274 { 276 {
275 new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff of smoke!"); 277 new_draw_info (NDI_UNIQUE, 0, pl, "The object disappears in a puff of smoke!");
276 new_draw_info (NDI_UNIQUE, 0, pl, "It must have been an illusion."); 278 new_draw_info (NDI_UNIQUE, 0, pl, "It must have been an illusion.");
277 279
278 if (pl->type == PLAYER) 280 if (pl->contr)
279 esrv_del_item (pl->contr, tmp->count); 281 esrv_del_item (pl->contr, tmp->count);
280 282
281 tmp->destroy (); 283 tmp->destroy ();
282 return; 284 return;
283 } 285 }
299 { 301 {
300 new_draw_info (0, 0, pl, "That item is too heavy for you to pick up."); 302 new_draw_info (0, 0, pl, "That item is too heavy for you to pick up.");
301 return; 303 return;
302 } 304 }
303 305
304 if (settings.real_wiz == FALSE && QUERY_FLAG (pl, FLAG_WAS_WIZ))
305 SET_FLAG (tmp, FLAG_WAS_WIZ);
306
307 if (nrof != tmp_nrof) 306 if (nrof != tmp_nrof)
308 { 307 {
309 object *tmp2 = tmp; 308 object *tmp2 = tmp;
310 309
311 tmp = get_split_ob (tmp, nrof); 310 tmp = get_split_ob (tmp, nrof);
313 { 312 {
314 new_draw_info (NDI_UNIQUE, 0, pl, errmsg); 313 new_draw_info (NDI_UNIQUE, 0, pl, errmsg);
315 return; 314 return;
316 } 315 }
317 316
318 /* Tell a client what happened rest of objects */ 317 /* Tell the client what happened to the rest of objects */
319 if (pl->type == PLAYER) 318 if (pl->contr)
320 {
321 if (tmp2->destroyed ()) 319 if (tmp2->destroyed ())
322 esrv_del_item (pl->contr, tmp2->count); 320 esrv_del_item (pl->contr, tmp2->count);
323 else 321 else
324 esrv_send_item (pl, tmp2); 322 esrv_update_item (UPD_NROF, pl, tmp2);
325 }
326 } 323 }
327 else 324 else
328 { 325 {
329 /* If the object is in a container, send a delete to the client. 326 /* If the object is in a container, send a delete to the client.
330 * - we are moving all the items from the container to elsewhere, 327 * - we are moving all the items from the container to elsewhere,
332 */ 329 */
333 if (!QUERY_FLAG (tmp, FLAG_REMOVED)) 330 if (!QUERY_FLAG (tmp, FLAG_REMOVED))
334 { 331 {
335 if (tmp->env && pl->type == PLAYER) 332 if (tmp->env && pl->type == PLAYER)
336 esrv_del_item (pl->contr, tmp->count); 333 esrv_del_item (pl->contr, tmp->count);
334
337 tmp->remove (); /* Unlink it */ 335 tmp->remove (); /* Unlink it */
338 } 336 }
339 } 337 }
338
340 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 339 if (QUERY_FLAG (tmp, FLAG_UNPAID))
341 (void) sprintf (buf, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP)); 340 sprintf (buf, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP));
342 else 341 else
343 (void) sprintf (buf, "You pick up the %s.", query_name (tmp)); 342 sprintf (buf, "You pick up the %s.", query_name (tmp));
343
344 new_draw_info (NDI_UNIQUE, 0, pl, buf); 344 new_draw_info (NDI_UNIQUE, 0, pl, buf);
345 345
346 tmp = insert_ob_in_ob (tmp, op); 346 tmp = insert_ob_in_ob (tmp, op);
347 347
348 /* All the stuff below deals with client/server code, and is only 348 /* All the stuff below deals with client/server code, and is only
349 * usable by players 349 * usable by players
350 */ 350 */
351 if (pl->type != PLAYER) 351 if (pl->contr)
352 return; 352 {
353
354 esrv_send_item (pl, tmp); 353 esrv_send_item (pl, tmp);
354
355 /* These are needed to update the weight for the container we 355 /* These are needed to update the weight for the container we
356 * are putting the object in. 356 * are putting the object in.
357 */ 357 */
358 if (op != pl) 358 if (op != pl)
359 { 359 {
360 esrv_update_item (UPD_WEIGHT, pl, op); 360 esrv_update_item (UPD_WEIGHT, pl, op);
361 esrv_send_item (pl, pl); 361 esrv_send_item (pl, pl);
362 } 362 }
363 363
364 /* Update the container the object was in */ 364 /* Update the container the object was in */
365 if (env && env != pl && env != op) 365 if (env && env != pl && env != op)
366 esrv_update_item (UPD_WEIGHT, pl, env); 366 esrv_update_item (UPD_WEIGHT, pl, env);
367 }
367} 368}
368 369
369/* modified slightly to allow monsters use this -b.t. 5-31-95 */ 370/* modified slightly to allow monsters use this -b.t. 5-31-95 */
370void 371void
371pick_up (object *op, object *alt) 372pick_up (object *op, object *alt)
430 431
431 if (!alt) 432 if (!alt)
432 for (alt = op->inv; alt; alt = alt->below) 433 for (alt = op->inv; alt; alt = alt->below)
433 if (alt->type == CONTAINER && QUERY_FLAG (alt, FLAG_APPLIED) && sack_can_hold (NULL, alt, tmp, count)) 434 if (alt->type == CONTAINER && QUERY_FLAG (alt, FLAG_APPLIED) && sack_can_hold (NULL, alt, tmp, count))
434 break; /* General container comes next */ 435 break; /* General container comes next */
436
435 if (!alt) 437 if (!alt)
436 alt = op; /* No free containers */ 438 alt = op; /* No free containers */
437 } 439 }
438 440
439 if (tmp->env == alt) 441 if (tmp->env == alt)
466 468
467leave: 469leave:
468 if (need_fix_tmp) 470 if (need_fix_tmp)
469 fix_stopped_item (tmp, tmp_map, op); 471 fix_stopped_item (tmp, tmp_map, op);
470} 472}
471
472 473
473/* This takes (picks up) and item. op is the player 474/* This takes (picks up) and item. op is the player
474 * who issued the command. params is a string to 475 * who issued the command. params is a string to
475 * match against the item name. Basically, always 476 * match against the item name. Basically, always
476 * returns zero, but that should be improved. 477 * returns zero, but that should be improved.
491 492
492 if (!tmp) 493 if (!tmp)
493 tmp = op->below; 494 tmp = op->below;
494 } 495 }
495 496
496 if (tmp == NULL) 497 if (!tmp)
497 { 498 {
498 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to take!"); 499 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to take!");
499 return 0; 500 return 0;
500 } 501 }
501 502
502 /* Makes processing easier */ 503 /* Makes processing easier */
503 if (params && *params == '\0') 504 if (params && *params == '\0')
504 params = NULL; 505 params = 0;
505 506
506 while (tmp) 507 while (tmp)
507 { 508 {
508 next = tmp->below; 509 next = tmp->below;
509 510
510 if (tmp->invisible) 511 if (tmp->invisible)
511 { 512 {
512 tmp = next; 513 tmp = next;
513 continue; 514 continue;
514 } 515 }
516
515 /* This following two if and else if could be merged into line 517 /* This following two if and else if could be merged into line
516 * but that probably will make it more difficult to read, and 518 * but that probably will make it more difficult to read, and
517 * not make it any more efficient 519 * not make it any more efficient
518 */ 520 */
519 if (params && item_matched_string (op, tmp, params)) 521 if (params && item_matched_string (op, tmp, params))
520 {
521 pick_up (op, tmp); 522 pick_up (op, tmp);
522 }
523 else if (can_pick (op, tmp) && !params) 523 else if (can_pick (op, tmp) && !params)
524 { 524 {
525 pick_up (op, tmp); 525 pick_up (op, tmp);
526 break; 526 break;
527 } 527 }
528
528 tmp = next; 529 tmp = next;
529 /* Might as well just skip over the player immediately -
530 * we know it can't be picked up
531 */
532 if (tmp == op)
533 tmp = tmp->below;
534 } 530 }
531
535 if (!params && !tmp) 532 if (!params && !tmp)
536 { 533 {
537 for (tmp = op->below; tmp != NULL; tmp = tmp->next) 534 for (tmp = op->below; tmp; tmp = tmp->below)
538 if (!tmp->invisible) 535 if (!tmp->invisible)
539 { 536 {
540 char buf[MAX_BUF]; 537 char buf[MAX_BUF];
541 538
542 sprintf (buf, "You can't pick up a %s.", &tmp->name); 539 sprintf (buf, "You can't pick up a %s.", &tmp->name);
543 new_draw_info (NDI_UNIQUE, 0, op, buf); 540 new_draw_info (NDI_UNIQUE, 0, op, buf);
544 break; 541 break;
545 } 542 }
543
546 if (!tmp) 544 if (!tmp)
547 new_draw_info (NDI_UNIQUE, 0, op, "There is nothing to pick up."); 545 new_draw_info (NDI_UNIQUE, 0, op, "There is nothing to pick up.");
548 } 546 }
547
549 return 0; 548 return 0;
550} 549}
551 550
552 551
553/* 552/*
633 else 632 else
634 tmp->remove (); 633 tmp->remove ();
635 634
636 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack)); 635 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack));
637 tmp2 = insert_ob_in_ob (tmp, sack); 636 tmp2 = insert_ob_in_ob (tmp, sack);
638 fix_player (op); /* This is overkill, fix_player() is called somewhere */ 637 op->update_stats (); /* This is overkill, fix_player() is called somewhere */
639 /* in object.c */ 638 /* in object.c */
640 639
641 /* If an object merged (and thus, different object), we need to 640 /* If an object merged (and thus, different object), we need to
642 * delete the original. 641 * delete the original.
643 */ 642 */
667 666
668 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 667 if (QUERY_FLAG (tmp, FLAG_APPLIED))
669 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 668 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE))
670 return; /* can't unapply it */ 669 return; /* can't unapply it */
671 670
671 //fprintf (stderr, "ui, on space is %ld\n", op->ms ().volume ());//D
672
672 /* We are only dropping some of the items. We split the current object 673 /* We are only dropping some of the items. We split the current object
673 * off 674 * off
674 */ 675 */
675 if (nrof && tmp->nrof != nrof) 676 if (nrof && tmp->nrof != nrof)
676 { 677 {
702 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 703 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP))
703 { 704 {
704 sprintf (buf, "You drop the %s.", query_name (tmp)); 705 sprintf (buf, "You drop the %s.", query_name (tmp));
705 new_draw_info (NDI_UNIQUE, 0, op, buf); 706 new_draw_info (NDI_UNIQUE, 0, op, buf);
706 new_draw_info (NDI_UNIQUE, 0, op, "The gods who lent it to you retrieves it."); 707 new_draw_info (NDI_UNIQUE, 0, op, "The gods who lent it to you retrieves it.");
708
707 if (op->type == PLAYER) 709 if (op->type == PLAYER)
708 esrv_del_item (op->contr, tmp->count); 710 esrv_del_item (op->contr, tmp->count);
711
709 tmp->destroy (); 712 tmp->destroy ();
710 fix_player (op); 713 op->update_stats ();
711 return; 714 return;
712 } 715 }
713
714/* If SAVE_INTERVAL is commented out, we never want to save
715 * the player here.
716 */
717#ifdef SAVE_INTERVAL
718 /* I'm not sure why there is a value check - since the save
719 * is done every SAVE_INTERVAL seconds, why care the value
720 * of what he is dropping?
721 */
722 if (op->type == PLAYER && !QUERY_FLAG (tmp, FLAG_UNPAID) &&
723 (tmp->nrof ? tmp->value * tmp->nrof : tmp->value > 2000) && (op->contr->last_save_time + SAVE_INTERVAL) <= time (NULL))
724 {
725 save_player (op, 1);
726 op->contr->last_save_time = time (NULL);
727 }
728#endif /* SAVE_INTERVAL */
729 716
730 if (op->type == PLAYER) 717 if (op->type == PLAYER)
731 esrv_del_item (op->contr, tmp->count); 718 esrv_del_item (op->contr, tmp->count);
732 719
733 /* Call this before we update the various windows/players. At least 720 /* Call this before we update the various windows/players. At least
734 * that we, we know the weight is correct. 721 * that we, we know the weight is correct.
735 */ 722 */
736 fix_player (op); /* This is overkill, fix_player() is called somewhere */ 723 op->update_stats (); /* This is overkill, fix_player() is called somewhere */
737 /* in object.c */ 724 /* in object.c */
738 725
739 if (op->type == PLAYER) 726 if (op->type == PLAYER)
740 { 727 {
741 op->contr->socket.update_look = 1;
742 /* Need to update the weight for the player */ 728 /* Need to update the weight for the player */
743 esrv_send_item (op, op); 729 esrv_send_item (op, op);
730 op->contr->ns->floorbox_update ();
744 } 731 }
745 732
746 for (floor = get_map_ob (op->map, op->x, op->y); floor; floor = floor->above) 733 for (floor = GET_MAP_OB (op->map, op->x, op->y); floor; floor = floor->above)
747 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op))) 734 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op)))
748 return; 735 return;
749 736
750 if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY) 737 if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY)
751 sell_item (tmp, op); 738 sell_item (tmp, op);
800 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped."); 787 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped.");
801#endif 788#endif
802 return; 789 return;
803 } 790 }
804 791
805 if (op->type == PLAYER) 792 if (op->type == PLAYER && op->contr->last_used == tmp)
806 { 793 op->contr->last_used = tmp->below ? tmp->below
807 if (op->contr->last_used == tmp && op->contr->last_used_id == tmp->count) 794 : tmp->above ? tmp->above
808 { 795 : 0;
809 object *n = NULL;
810
811 if (tmp->below != NULL)
812 n = tmp->below;
813 else if (tmp->above != NULL)
814 n = tmp->above;
815 op->contr->last_used = n;
816 if (n != NULL)
817 op->contr->last_used_id = n->count;
818 else
819 op->contr->last_used_id = 0;
820 }
821 };
822 796
823 if (op->container) 797 if (op->container)
824 { 798 {
825 if (op->type == PLAYER) 799 if (op->type == PLAYER)
826 {
827 put_object_in_sack (op, op->container, tmp, op->contr->count); 800 put_object_in_sack (op, op->container, tmp, op->contr->count);
828 }
829 else 801 else
830 {
831 put_object_in_sack (op, op->container, tmp, 0); 802 put_object_in_sack (op, op->container, tmp, 0);
832 };
833 } 803 }
834 else 804 else
835 { 805 {
836 if (op->type == PLAYER) 806 if (op->type == PLAYER)
837 {
838 drop_object (op, tmp, op->contr->count); 807 drop_object (op, tmp, op->contr->count);
839 }
840 else 808 else
841 {
842 drop_object (op, tmp, 0); 809 drop_object (op, tmp, 0);
843 };
844 } 810 }
811
845 if (op->type == PLAYER) 812 if (op->type == PLAYER)
846 op->contr->count = 0; 813 op->contr->count = 0;
847} 814}
848 815
849 816
957 } 924 }
958 } 925 }
959 curinv = nextinv; 926 curinv = nextinv;
960 } 927 }
961 } 928 }
962 op->contr->socket.update_look = 1; 929
930 op->contr->ns->floorbox_update ();
963 931
964/* draw_look(op);*/ 932/* draw_look(op);*/
965 return 0; 933 return 0;
966} 934}
967 935
997 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); 965 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop.");
998 } 966 }
999 if (op->type == PLAYER) 967 if (op->type == PLAYER)
1000 { 968 {
1001 op->contr->count = 0; 969 op->contr->count = 0;
1002 op->contr->socket.update_look = 1; 970 op->contr->ns->floorbox_update ();
1003 }; 971 };
1004 972
1005/* draw_look(op);*/ 973/* draw_look(op);*/
1006 return 0; 974 return 0;
1007} 975}
1011{ 979{
1012 if (!params) 980 if (!params)
1013 { 981 {
1014 object *tmp = op->below; 982 object *tmp = op->below;
1015 983
1016 while (tmp && !LOOK_OBJ (tmp)) 984 while (tmp && !tmp->client_visible ())
1017 tmp = tmp->below; 985 tmp = tmp->below;
1018 if (tmp) 986 if (tmp)
1019 examine (op, tmp); 987 examine (op, tmp);
1020 } 988 }
1021 else 989 else
1578 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'."); 1546 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'.");
1579 return 1; 1547 return 1;
1580 } 1548 }
1581 op->contr->search_str[0] = '\0'; 1549 op->contr->search_str[0] = '\0';
1582 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off."); 1550 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off.");
1583 fix_player (op); 1551 op->update_stats ();
1584 return 1; 1552 return 1;
1585 } 1553 }
1586 if ((int) strlen (params) >= MAX_BUF) 1554 if ((int) strlen (params) >= MAX_BUF)
1587 { 1555 {
1588 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long."); 1556 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long.");
1589 return 1; 1557 return 1;
1590 } 1558 }
1591 strcpy (op->contr->search_str, params); 1559 strcpy (op->contr->search_str, params);
1592 sprintf (buf, "Searching for '%s'.", op->contr->search_str); 1560 sprintf (buf, "Searching for '%s'.", op->contr->search_str);
1593 new_draw_info (NDI_UNIQUE, 0, op, buf); 1561 new_draw_info (NDI_UNIQUE, 0, op, buf);
1594 fix_player (op); 1562 op->update_stats ();
1595 return 1; 1563 return 1;
1596} 1564}
1597 1565

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines