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

Comparing deliantra/server/common/object.C (file contents):
Revision 1.29 by root, Mon Sep 11 12:38:36 2006 UTC vs.
Revision 1.47 by root, Thu Sep 14 22:33:59 2006 UTC

1
2/* 1/*
3 CrossFire, A Multiplayer game for X-windows 2 CrossFire, A Multiplayer game for X-windows
4 3
5 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 4 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
6 Copyright (C) 1992 Frank Tore Johansen 5 Copyright (C) 1992 Frank Tore Johansen
17 16
18 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
19 along with this program; if not, write to the Free Software 18 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 20
22 The authors can be reached via e-mail at crossfire-devel@real-time.com 21 The authors can be reached via e-mail at <crossfire@schmorp.de>
23*/ 22*/
24 23
25/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. 24/* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects.
26 sub/add_weight will transcend the environment updating the carrying 25 sub/add_weight will transcend the environment updating the carrying
27 variable. */ 26 variable. */
29#include <stdio.h> 28#include <stdio.h>
30#include <sys/types.h> 29#include <sys/types.h>
31#include <sys/uio.h> 30#include <sys/uio.h>
32#include <object.h> 31#include <object.h>
33#include <funcpoint.h> 32#include <funcpoint.h>
34#include <skills.h>
35#include <loader.h> 33#include <loader.h>
36 34
37int nrofallocobjects = 0; 35int nrofallocobjects = 0;
36static UUID uuid;
37const uint64 UUID_SKIP = 1<<19;
38 38
39object *objects; /* Pointer to the list of used objects */
40object *active_objects; /* List of active objects that need to be processed */ 39object *active_objects; /* List of active objects that need to be processed */
41 40
42short freearr_x[SIZEOFFREE] = { 0, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1, 41short freearr_x[SIZEOFFREE] = { 0, 0, 1, 1, 1, 0, -1, -1, -1, 0, 1, 2, 2, 2, 2, 2, 1, 0, -1, -2, -2, -2, -2, -2, -1,
43 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1 42 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, -1, -2, -3, -3, -3, -3, -3, -3, -3, -2, -1
44}; 43};
50}; 49};
51int freedir[SIZEOFFREE] = { 50int freedir[SIZEOFFREE] = {
52 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8, 51 0, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 2, 2, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 8,
53 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8 52 1, 2, 2, 2, 2, 2, 3, 4, 4, 4, 4, 4, 5, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 8
54}; 53};
54
55static void
56write_uuid (void)
57{
58 char filename1[MAX_BUF], filename2[MAX_BUF];
59
60 sprintf (filename1, "%s/uuid", settings.localdir);
61 sprintf (filename2, "%s/uuid~", settings.localdir);
62
63 FILE *fp;
64
65 if (!(fp = fopen (filename2, "w")))
66 {
67 LOG (llevError, "ERROR: cannot open %s for writing, unable to write UUID!\n", filename2);
68 return;
69 }
70
71 fprintf (fp, "<1,%llx>\n", (unsigned long long)uuid.seq + UUID_SKIP * 2);
72 fclose (fp);
73 rename (filename2, filename1);
74}
75
76static void
77read_uuid (void)
78{
79 char filename[MAX_BUF];
80
81 sprintf (filename, "%s/uuid", settings.localdir);
82
83 FILE *fp;
84
85 if (!(fp = fopen (filename, "r")))
86 {
87 if (errno == ENOENT)
88 {
89 LOG (llevInfo, "RESET uid to 1\n");
90 uuid.seq = 0;
91 write_uuid ();
92 return;
93 }
94
95 LOG (llevError, "FATAL: cannot open %s for reading!\n", filename);
96 _exit (1);
97 }
98
99 int version;
100 unsigned long long uid;
101 if (2 != fscanf (fp, "<%d,%llx>\n", &version, &uid) || version != 1)
102 {
103 LOG (llevError, "FATAL: error reading uid from %s!\n", filename);
104 _exit (1);
105 }
106
107 uuid.seq = uid;
108 write_uuid ();
109 LOG (llevDebug, "read UID: %lld\n", uid);
110 fclose (fp);
111}
112
113UUID
114gen_uuid ()
115{
116 UUID uid;
117
118 uid.seq = ++uuid.seq;
119
120 if (!(uuid.seq & (UUID_SKIP - 1)))
121 write_uuid ();
122
123 return uid;
124}
125
126void
127init_uuid ()
128{
129 read_uuid ();
130}
55 131
56/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 132/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
57static int 133static int
58compare_ob_value_lists_one (const object *wants, const object *has) 134compare_ob_value_lists_one (const object *wants, const object *has)
59{ 135{
255 { 331 {
256 if (inv->inv) 332 if (inv->inv)
257 sum_weight (inv); 333 sum_weight (inv);
258 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 334 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
259 } 335 }
336
260 if (op->type == CONTAINER && op->stats.Str) 337 if (op->type == CONTAINER && op->stats.Str)
261 sum = (sum * (100 - op->stats.Str)) / 100; 338 sum = (sum * (100 - op->stats.Str)) / 100;
339
262 if (op->carrying != sum) 340 if (op->carrying != sum)
263 op->carrying = sum; 341 op->carrying = sum;
342
264 return sum; 343 return sum;
265} 344}
266 345
267/** 346/**
268 * Return the outermost environment object for a given object. 347 * Return the outermost environment object for a given object.
366void 445void
367dump_all_objects (void) 446dump_all_objects (void)
368{ 447{
369 object *op; 448 object *op;
370 449
371 for (op = objects; op != NULL; op = op->next) 450 for (op = object::first; op != NULL; op = op->next)
372 { 451 {
373 dump_object (op); 452 dump_object (op);
374 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg); 453 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg);
375 } 454 }
376} 455}
402object * 481object *
403find_object (tag_t i) 482find_object (tag_t i)
404{ 483{
405 object *op; 484 object *op;
406 485
407 for (op = objects; op != NULL; op = op->next) 486 for (op = object::first; op != NULL; op = op->next)
408 if (op->count == i) 487 if (op->count == i)
409 break; 488 break;
410 return op; 489 return op;
411} 490}
412 491
417 */ 496 */
418 497
419object * 498object *
420find_object_name (const char *str) 499find_object_name (const char *str)
421{ 500{
422 const char *name = shstr::find (str); 501 shstr_cmp str_ (str);
423 object *op; 502 object *op;
424 503
425 for (op = objects; op != NULL; op = op->next) 504 for (op = object::first; op != NULL; op = op->next)
426 if (&op->name == name) 505 if (op->name == str_)
427 break; 506 break;
428 507
429 return op; 508 return op;
430} 509}
431 510
434{ 513{
435 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 514 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
436} 515}
437 516
438/* 517/*
439 * Returns the object which this object marks as being the owner.
440 * A id-scheme is used to avoid pointing to objects which have been
441 * freed and are now reused. If this is detected, the owner is
442 * set to NULL, and NULL is returned.
443 * Changed 2004-02-12 - if the player is setting at the play again
444 * prompt, he is removed, and we don't want to treat him as an owner of
445 * anything, so check removed flag. I don't expect that this should break
446 * anything - once an object is removed, it is basically dead anyways.
447 */
448
449object *
450get_owner (object *op)
451{
452 if (op->owner == NULL)
453 return NULL;
454
455 if (!QUERY_FLAG (op->owner, FLAG_FREED) && !QUERY_FLAG (op->owner, FLAG_REMOVED) && op->owner->count == op->ownercount)
456 return op->owner;
457
458 op->owner = NULL;
459 op->ownercount = 0;
460 return NULL;
461}
462
463void
464clear_owner (object *op)
465{
466 if (!op)
467 return;
468
469 if (op->owner && op->ownercount == op->owner->count)
470 op->owner->refcount--;
471
472 op->owner = NULL;
473 op->ownercount = 0;
474}
475
476/*
477 * Sets the owner and sets the skill and exp pointers to owner's current 518 * Sets the owner and sets the skill and exp pointers to owner's current
478 * skill and experience objects. 519 * skill and experience objects.
479 */ 520 */
480void 521void
481set_owner (object *op, object *owner) 522object::set_owner (object *owner)
482{ 523{
483 if (owner == NULL || op == NULL) 524 if (!owner)
484 return; 525 return;
485 526
486 /* next line added to allow objects which own objects */ 527 /* next line added to allow objects which own objects */
487 /* Add a check for ownercounts in here, as I got into an endless loop 528 /* Add a check for ownercounts in here, as I got into an endless loop
488 * with the fireball owning a poison cloud which then owned the 529 * with the fireball owning a poison cloud which then owned the
489 * fireball. I believe that was caused by one of the objects getting 530 * fireball. I believe that was caused by one of the objects getting
490 * freed and then another object replacing it. Since the ownercounts 531 * freed and then another object replacing it. Since the ownercounts
491 * didn't match, this check is valid and I believe that cause is valid. 532 * didn't match, this check is valid and I believe that cause is valid.
492 */ 533 */
493 while (owner->owner && owner != owner->owner && owner->ownercount == owner->owner->count) 534 while (owner->owner)
494 owner = owner->owner; 535 owner = owner->owner;
495 536
496 /* IF the owner still has an owner, we did not resolve to a final owner.
497 * so lets not add to that.
498 */
499 if (owner->owner)
500 return;
501
502 op->owner = owner; 537 this->owner = owner;
503
504 op->ownercount = owner->count;
505 owner->refcount++;
506}
507
508/* Set the owner to clone's current owner and set the skill and experience
509 * objects to clone's objects (typically those objects that where the owner's
510 * current skill and experience objects at the time when clone's owner was
511 * set - not the owner's current skill and experience objects).
512 *
513 * Use this function if player created an object (e.g. fire bullet, swarm
514 * spell), and this object creates further objects whose kills should be
515 * accounted for the player's original skill, even if player has changed
516 * skills meanwhile.
517 */
518void
519copy_owner (object *op, object *clone)
520{
521 object *owner = get_owner (clone);
522
523 if (owner == NULL)
524 {
525 /* players don't have owners - they own themselves. Update
526 * as appropriate.
527 */
528 if (clone->type == PLAYER)
529 owner = clone;
530 else
531 return;
532 }
533
534 set_owner (op, owner);
535} 538}
536 539
537/* Zero the key_values on op, decrementing the shared-string 540/* Zero the key_values on op, decrementing the shared-string
538 * refcounts and freeing the links. 541 * refcounts and freeing the links.
539 */ 542 */
555{ 558{
556 attachable_base::clear (); 559 attachable_base::clear ();
557 560
558 free_key_values (this); 561 free_key_values (this);
559 562
560 clear_owner (this); 563 owner = 0;
561
562 name = 0; 564 name = 0;
563 name_pl = 0; 565 name_pl = 0;
564 title = 0; 566 title = 0;
565 race = 0; 567 race = 0;
566 slaying = 0; 568 slaying = 0;
567 skill = 0; 569 skill = 0;
568 msg = 0; 570 msg = 0;
569 lore = 0; 571 lore = 0;
570 custom_name = 0; 572 custom_name = 0;
571 materialname = 0; 573 materialname = 0;
574 contr = 0;
575 below = 0;
576 above = 0;
577 inv = 0;
578 container = 0;
579 env = 0;
580 more = 0;
581 head = 0;
582 map = 0;
583 active_next = 0;
584 active_prev = 0;
572 585
573 memset (static_cast < object_pod * >(this), 0, sizeof (object_pod)); 586 memset (static_cast<object_pod *>(this), 0, sizeof (object_pod));
574 587
575 SET_FLAG (this, FLAG_REMOVED); 588 SET_FLAG (this, FLAG_REMOVED);
589
590 /* What is not cleared is next, prev, and count */
591
592 expmul = 1.0;
593 face = blank_face;
594
595 if (settings.casting_time)
596 casting_time = -1;
576} 597}
577 598
578void object::clone (object *destination) 599void object::clone (object *destination)
579{ 600{
580 *(object_copy *) destination = *this; 601 *(object_copy *)destination = *this;
581 *(object_pod *) destination = *this; 602 *(object_pod *)destination = *this;
582 603
583 if (self || cb) 604 if (self || cb)
584 INVOKE_OBJECT (CLONE, this, ARG_OBJECT (destination)); 605 INVOKE_OBJECT (CLONE, this, ARG_OBJECT (destination));
585}
586
587/*
588 * clear_object() frees everything allocated by an object, and also
589 * clears all variables and flags to default settings.
590 */
591
592void
593clear_object (object *op)
594{
595 op->clear ();
596
597 op->contr = NULL;
598 op->below = NULL;
599 op->above = NULL;
600 op->inv = NULL;
601 op->container = NULL;
602 op->env = NULL;
603 op->more = NULL;
604 op->head = NULL;
605 op->map = NULL;
606 op->refcount = 0;
607 op->active_next = NULL;
608 op->active_prev = NULL;
609 /* What is not cleared is next, prev, and count */
610
611 op->expmul = 1.0;
612 op->face = blank_face;
613 op->attacked_by_count = -1;
614
615 if (settings.casting_time)
616 op->casting_time = -1;
617} 606}
618 607
619/* 608/*
620 * copy object first frees everything allocated by the second object, 609 * copy object first frees everything allocated by the second object,
621 * and then copies the contends of the first object into the second 610 * and then copies the contends of the first object into the second
622 * object, allocating what needs to be allocated. Basically, any 611 * object, allocating what needs to be allocated. Basically, any
623 * data that is malloc'd needs to be re-malloc/copied. Otherwise, 612 * data that is malloc'd needs to be re-malloc/copied. Otherwise,
624 * if the first object is freed, the pointers in the new object 613 * if the first object is freed, the pointers in the new object
625 * will point at garbage. 614 * will point at garbage.
626 */ 615 */
627
628void 616void
629copy_object (object *op2, object *op) 617copy_object (object *op2, object *op)
630{ 618{
631 bool is_freed = QUERY_FLAG (op, FLAG_FREED); 619 bool is_freed = QUERY_FLAG (op, FLAG_FREED);
632 bool is_removed = QUERY_FLAG (op, FLAG_REMOVED); 620 bool is_removed = QUERY_FLAG (op, FLAG_REMOVED);
692/* 680/*
693 * Updates the speed of an object. If the speed changes from 0 to another 681 * Updates the speed of an object. If the speed changes from 0 to another
694 * value, or vice versa, then add/remove the object from the active list. 682 * value, or vice versa, then add/remove the object from the active list.
695 * This function needs to be called whenever the speed of an object changes. 683 * This function needs to be called whenever the speed of an object changes.
696 */ 684 */
697
698void 685void
699update_ob_speed (object *op) 686update_ob_speed (object *op)
700{ 687{
701 extern int arch_init; 688 extern int arch_init;
702 689
711 abort (); 698 abort ();
712#else 699#else
713 op->speed = 0; 700 op->speed = 0;
714#endif 701#endif
715 } 702 }
703
716 if (arch_init) 704 if (arch_init)
717 {
718 return; 705 return;
719 } 706
720 if (FABS (op->speed) > MIN_ACTIVE_SPEED) 707 if (FABS (op->speed) > MIN_ACTIVE_SPEED)
721 { 708 {
722 /* If already on active list, don't do anything */ 709 /* If already on active list, don't do anything */
723 if (op->active_next || op->active_prev || op == active_objects) 710 if (op->active_next || op->active_prev || op == active_objects)
724 return; 711 return;
725 712
726 /* process_events() expects us to insert the object at the beginning 713 /* process_events() expects us to insert the object at the beginning
727 * of the list. */ 714 * of the list. */
728 op->active_next = active_objects; 715 op->active_next = active_objects;
716
729 if (op->active_next != NULL) 717 if (op->active_next != NULL)
730 op->active_next->active_prev = op; 718 op->active_next->active_prev = op;
719
731 active_objects = op; 720 active_objects = op;
732 } 721 }
733 else 722 else
734 { 723 {
735 /* If not on the active list, nothing needs to be done */ 724 /* If not on the active list, nothing needs to be done */
737 return; 726 return;
738 727
739 if (op->active_prev == NULL) 728 if (op->active_prev == NULL)
740 { 729 {
741 active_objects = op->active_next; 730 active_objects = op->active_next;
731
742 if (op->active_next != NULL) 732 if (op->active_next != NULL)
743 op->active_next->active_prev = NULL; 733 op->active_next->active_prev = NULL;
744 } 734 }
745 else 735 else
746 { 736 {
747 op->active_prev->active_next = op->active_next; 737 op->active_prev->active_next = op->active_next;
738
748 if (op->active_next) 739 if (op->active_next)
749 op->active_next->active_prev = op->active_prev; 740 op->active_next->active_prev = op->active_prev;
750 } 741 }
742
751 op->active_next = NULL; 743 op->active_next = NULL;
752 op->active_prev = NULL; 744 op->active_prev = NULL;
753 } 745 }
754} 746}
755 747
901 893
902 if (op->more != NULL) 894 if (op->more != NULL)
903 update_object (op->more, action); 895 update_object (op->more, action);
904} 896}
905 897
906static unordered_vector < object *>mortals; 898object::vector object::mortals;
907static 899object::vector object::objects; // not yet used
908std::vector < object *> 900object *object::first;
909 freed;
910 901
911void object::free_mortals () 902void object::free_mortals ()
912{ 903{
913 for (unordered_vector < object *>::iterator i = mortals.begin (); i != mortals.end ();) 904 for (AUTODECL (i, mortals.begin ()); i != mortals.end ();)
914 if (!(*i)->refcount) 905 if ((*i)->refcnt)
906 ++i; // further delay freeing
907 else
915 { 908 {
916 freed.push_back (*i); 909 delete *i;
917 mortals.erase (i); 910 mortals.erase (i);
918 } 911 }
919 else 912
920 ++i; 913 static int lastmortals = 0;//D
914
915 if (mortals.size() != lastmortals)//D
916 {
917 lastmortals = mortals.size ();//D
918 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
919 }
921} 920}
922 921
923object::object () 922object::object ()
924{ 923{
925 SET_FLAG (this, FLAG_REMOVED); 924 SET_FLAG (this, FLAG_REMOVED);
926 925
927 expmul = 1.0; 926 expmul = 1.0;
928 face = blank_face; 927 face = blank_face;
929 attacked_by_count = -1;
930} 928}
931 929
932object::~object () 930object::~object ()
933{ 931{
934 free_key_values (this); 932 free_key_values (this);
935} 933}
936 934
937void object::link () 935void object::link ()
938{ 936{
939 count = ++ob_count; 937 count = ++ob_count;
938 uuid = gen_uuid ();
940 939
941 prev = 0; 940 prev = 0;
942 next = objects; 941 next = object::first;
943 942
944 if (objects) 943 if (object::first)
945 objects->prev = this; 944 object::first->prev = this;
946 945
947 objects = this; 946 object::first = this;
948} 947}
949 948
950void object::unlink () 949void object::unlink ()
951{ 950{
952 count = 0; 951 //count = 0;//D
952 if (!prev && !next) return;//D
953
954 if (this == object::first)
955 object::first = next;
953 956
954 /* Remove this object from the list of used objects */ 957 /* Remove this object from the list of used objects */
955 if (prev)
956 {
957 prev->next = next; 958 if (prev) prev->next = next;
959 if (next) next->prev = prev;
960
958 prev = 0; 961 prev = 0;
959 }
960
961 if (next)
962 {
963 next->prev = prev;
964 next = 0; 962 next = 0;
965 }
966
967 if (this == objects)
968 objects = next;
969} 963}
970 964
971object *object::create () 965object *object::create ()
972{ 966{
973 object *
974 op;
975
976 if (freed.empty ())
977 op = new object; 967 object *op = new object;
978
979 else
980 {
981 // highly annoying, but the only way to get it stable right now
982 op = freed.back ();
983 freed.pop_back ();
984 op->~object ();
985 new ((void *) op) object;
986 }
987
988 op->link (); 968 op->link ();
989 return op; 969 return op;
990} 970}
991 971
992/* 972/*
1002void object::free (bool free_inventory) 982void object::free (bool free_inventory)
1003{ 983{
1004 if (QUERY_FLAG (this, FLAG_FREED)) 984 if (QUERY_FLAG (this, FLAG_FREED))
1005 return; 985 return;
1006 986
987 if (QUERY_FLAG (this, FLAG_FRIENDLY))
988 remove_friendly_object (this);
989
1007 if (!QUERY_FLAG (this, FLAG_REMOVED)) 990 if (!QUERY_FLAG (this, FLAG_REMOVED))
1008 remove_ob (this); 991 remove_ob (this);
1009
1010 if (QUERY_FLAG (this, FLAG_FRIENDLY))
1011 remove_friendly_object (this);
1012 992
1013 SET_FLAG (this, FLAG_FREED); 993 SET_FLAG (this, FLAG_FREED);
1014 994
1015 if (more) 995 if (more)
1016 { 996 {
1022 { 1002 {
1023 /* Only if the space blocks everything do we not process - 1003 /* Only if the space blocks everything do we not process -
1024 * if some form of movement is allowed, let objects 1004 * if some form of movement is allowed, let objects
1025 * drop on that space. 1005 * drop on that space.
1026 */ 1006 */
1027 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || (GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)) 1007 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)
1028 { 1008 {
1029 object *op = inv; 1009 object *op = inv;
1030 1010
1031 while (op) 1011 while (op)
1032 { 1012 {
1058 op = tmp; 1038 op = tmp;
1059 } 1039 }
1060 } 1040 }
1061 } 1041 }
1062 1042
1063 clear_owner (this); 1043 // clear those pointers that likely might have circular references to us
1044 owner = 0;
1045 enemy = 0;
1046 attacked_by = 0;
1064 1047
1065 /* Remove object from the active list */ 1048 /* Remove object from the active list */
1066 speed = 0; 1049 speed = 0;
1067 update_ob_speed (this); 1050 update_ob_speed (this);
1068 1051
1080sub_weight (object *op, signed long weight) 1063sub_weight (object *op, signed long weight)
1081{ 1064{
1082 while (op != NULL) 1065 while (op != NULL)
1083 { 1066 {
1084 if (op->type == CONTAINER) 1067 if (op->type == CONTAINER)
1085 {
1086 weight = (signed long) (weight * (100 - op->stats.Str) / 100); 1068 weight = (signed long) (weight * (100 - op->stats.Str) / 100);
1087 } 1069
1088 op->carrying -= weight; 1070 op->carrying -= weight;
1089 op = op->env; 1071 op = op->env;
1090 } 1072 }
1091} 1073}
1092 1074
1100 */ 1082 */
1101 1083
1102void 1084void
1103remove_ob (object *op) 1085remove_ob (object *op)
1104{ 1086{
1087 object *tmp, *last = 0;
1105 object * 1088 object *otmp;
1106 tmp, *
1107 last = NULL;
1108 object *
1109 otmp;
1110 1089
1111 tag_t 1090 tag_t tag;
1112 tag;
1113 int
1114 check_walk_off; 1091 int check_walk_off;
1115 mapstruct * 1092 mapstruct *m;
1116 m;
1117 1093
1118 sint16 1094 sint16 x, y;
1119 x,
1120 y;
1121 1095
1122 if (QUERY_FLAG (op, FLAG_REMOVED)) 1096 if (QUERY_FLAG (op, FLAG_REMOVED))
1123 return; 1097 return;
1124 1098
1125 SET_FLAG (op, FLAG_REMOVED); 1099 SET_FLAG (op, FLAG_REMOVED);
1288 * This function goes through all objects below and including top, and 1262 * This function goes through all objects below and including top, and
1289 * merges op to the first matching object. 1263 * merges op to the first matching object.
1290 * If top is NULL, it is calculated. 1264 * If top is NULL, it is calculated.
1291 * Returns pointer to object if it succeded in the merge, otherwise NULL 1265 * Returns pointer to object if it succeded in the merge, otherwise NULL
1292 */ 1266 */
1293
1294object * 1267object *
1295merge_ob (object *op, object *top) 1268merge_ob (object *op, object *top)
1296{ 1269{
1297 if (!op->nrof) 1270 if (!op->nrof)
1298 return 0; 1271 return 0;
1314 free_object (op); 1287 free_object (op);
1315 return top; 1288 return top;
1316 } 1289 }
1317 } 1290 }
1318 1291
1319 return NULL; 1292 return 0;
1320} 1293}
1321 1294
1322/* 1295/*
1323 * same as insert_ob_in_map except it handle separate coordinates and do a clean 1296 * same as insert_ob_in_map except it handle separate coordinates and do a clean
1324 * job preparing multi-part monsters 1297 * job preparing multi-part monsters
1651 remove_ob (tmp); 1624 remove_ob (tmp);
1652 free_object (tmp); 1625 free_object (tmp);
1653 } 1626 }
1654 } 1627 }
1655 1628
1656 tmp1 = arch_to_object (find_archetype (arch_string)); 1629 tmp1 = arch_to_object (archetype::find (arch_string));
1657 1630
1658 tmp1->x = op->x; 1631 tmp1->x = op->x;
1659 tmp1->y = op->y; 1632 tmp1->y = op->y;
1660 insert_ob_in_map (tmp1, op->map, op, 0); 1633 insert_ob_in_map (tmp1, op->map, op, 0);
1661} 1634}
2719 2692
2720 if (tempfile == NULL) 2693 if (tempfile == NULL)
2721 { 2694 {
2722 LOG (llevError, "Error - Unable to access load object temp file\n"); 2695 LOG (llevError, "Error - Unable to access load object temp file\n");
2723 return NULL; 2696 return NULL;
2724 }; 2697 }
2698
2725 fprintf (tempfile, obstr); 2699 fprintf (tempfile, obstr);
2726 fclose (tempfile); 2700 fclose (tempfile);
2727 2701
2728 op = get_object (); 2702 op = get_object ();
2729 2703
2786 * The returned string is shared. 2760 * The returned string is shared.
2787 */ 2761 */
2788const char * 2762const char *
2789get_ob_key_value (const object *op, const char *const key) 2763get_ob_key_value (const object *op, const char *const key)
2790{ 2764{
2791 key_value * 2765 key_value *link;
2792 link; 2766 shstr_cmp canonical_key (key);
2793 const char *
2794 canonical_key;
2795 2767
2796 canonical_key = shstr::find (key);
2797
2798 if (canonical_key == NULL) 2768 if (!canonical_key)
2799 { 2769 {
2800 /* 1. There being a field named key on any object 2770 /* 1. There being a field named key on any object
2801 * implies there'd be a shared string to find. 2771 * implies there'd be a shared string to find.
2802 * 2. Since there isn't, no object has this field. 2772 * 2. Since there isn't, no object has this field.
2803 * 3. Therefore, *this* object doesn't have this field. 2773 * 3. Therefore, *this* object doesn't have this field.
2804 */ 2774 */
2805 return NULL; 2775 return 0;
2806 } 2776 }
2807 2777
2808 /* This is copied from get_ob_key_link() above - 2778 /* This is copied from get_ob_key_link() above -
2809 * only 4 lines, and saves the function call overhead. 2779 * only 4 lines, and saves the function call overhead.
2810 */ 2780 */
2811 for (link = op->key_values; link != NULL; link = link->next) 2781 for (link = op->key_values; link; link = link->next)
2812 {
2813 if (link->key == canonical_key) 2782 if (link->key == canonical_key)
2814 {
2815 return link->value; 2783 return link->value;
2816 } 2784
2817 }
2818 return NULL; 2785 return 0;
2819} 2786}
2820 2787
2821 2788
2822/* 2789/*
2823 * Updates the canonical_key in op to value. 2790 * Updates the canonical_key in op to value.
2908{ 2875{
2909 shstr key_ (key); 2876 shstr key_ (key);
2910 2877
2911 return set_ob_key_value_s (op, key_, value, add_key); 2878 return set_ob_key_value_s (op, key_, value, add_key);
2912} 2879}
2880
2881object::depth_iterator::depth_iterator (object *container)
2882: iterator_base (container)
2883{
2884 while (item->inv)
2885 item = item->inv;
2886}
2887
2888void
2889object::depth_iterator::next ()
2890{
2891 if (item->below)
2892 {
2893 item = item->below;
2894
2895 while (item->inv)
2896 item = item->inv;
2897 }
2898 else
2899 item = item->env;
2900}
2901
2902// return a suitable string describing an objetc in enough detail to find it
2903const char *
2904object::debug_desc (char *info) const
2905{
2906 char info2[256 * 3];
2907 char *p = info;
2908
2909 p += snprintf (p, 256, "%d=\"%s%s%s\"",
2910 count,
2911 &name,
2912 title ? " " : "",
2913 title ? (const char *)title : "");
2914
2915 if (env)
2916 p += snprintf (p, 256, "(in %s)", env->debug_desc (info2));
2917
2918 if (map)
2919 p += snprintf (p, 256, "(on %s@%d+%d)", map->path, x, y);
2920
2921 return info;
2922}
2923
2924const char *
2925object::debug_desc () const
2926{
2927 static char info[256 * 3];
2928 return debug_desc (info);
2929}
2930

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines