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.34 by root, Tue Sep 12 01:09:53 2006 UTC

29#include <stdio.h> 29#include <stdio.h>
30#include <sys/types.h> 30#include <sys/types.h>
31#include <sys/uio.h> 31#include <sys/uio.h>
32#include <object.h> 32#include <object.h>
33#include <funcpoint.h> 33#include <funcpoint.h>
34#include <skills.h>
35#include <loader.h> 34#include <loader.h>
36 35
37int nrofallocobjects = 0; 36int nrofallocobjects = 0;
38 37
39object *objects; /* Pointer to the list of used objects */ 38object *objects; /* Pointer to the list of used objects */
443 * Changed 2004-02-12 - if the player is setting at the play again 442 * 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 443 * 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 444 * 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. 445 * anything - once an object is removed, it is basically dead anyways.
447 */ 446 */
448
449object * 447object *
450get_owner (object *op) 448object::get_owner ()
451{ 449{
452 if (op->owner == NULL) 450 if (!owner
453 return NULL; 451 || QUERY_FLAG (owner, FLAG_FREED)
452 || QUERY_FLAG (owner, FLAG_REMOVED))
453 owner = 0;
454 454
455 if (!QUERY_FLAG (op->owner, FLAG_FREED) && !QUERY_FLAG (op->owner, FLAG_REMOVED) && op->owner->count == op->ownercount)
456 return op->owner; 455 return 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} 456}
475 457
476/* 458/*
477 * Sets the owner and sets the skill and exp pointers to owner's current 459 * Sets the owner and sets the skill and exp pointers to owner's current
478 * skill and experience objects. 460 * skill and experience objects.
479 */ 461 */
480void 462void
481set_owner (object *op, object *owner) 463object::set_owner (object *owner)
482{ 464{
483 if (owner == NULL || op == NULL) 465 if (!owner)
484 return; 466 return;
485 467
486 /* next line added to allow objects which own objects */ 468 /* next line added to allow objects which own objects */
487 /* Add a check for ownercounts in here, as I got into an endless loop 469 /* 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 470 * with the fireball owning a poison cloud which then owned the
489 * fireball. I believe that was caused by one of the objects getting 471 * fireball. I believe that was caused by one of the objects getting
490 * freed and then another object replacing it. Since the ownercounts 472 * 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. 473 * didn't match, this check is valid and I believe that cause is valid.
492 */ 474 */
493 while (owner->owner && owner != owner->owner && owner->ownercount == owner->owner->count) 475 while (owner->owner)
494 owner = owner->owner; 476 owner = owner->owner;
495 477
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; 478 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} 479}
536 480
537/* Zero the key_values on op, decrementing the shared-string 481/* Zero the key_values on op, decrementing the shared-string
538 * refcounts and freeing the links. 482 * refcounts and freeing the links.
539 */ 483 */
555{ 499{
556 attachable_base::clear (); 500 attachable_base::clear ();
557 501
558 free_key_values (this); 502 free_key_values (this);
559 503
560 clear_owner (this); 504 owner = 0;
561
562 name = 0; 505 name = 0;
563 name_pl = 0; 506 name_pl = 0;
564 title = 0; 507 title = 0;
565 race = 0; 508 race = 0;
566 slaying = 0; 509 slaying = 0;
567 skill = 0; 510 skill = 0;
568 msg = 0; 511 msg = 0;
569 lore = 0; 512 lore = 0;
570 custom_name = 0; 513 custom_name = 0;
571 materialname = 0; 514 materialname = 0;
515 contr = 0;
516 below = 0;
517 above = 0;
518 inv = 0;
519 container = 0;
520 env = 0;
521 more = 0;
522 head = 0;
523 map = 0;
524 active_next = 0;
525 active_prev = 0;
572 526
573 memset (static_cast < object_pod * >(this), 0, sizeof (object_pod)); 527 memset (static_cast<object_pod *>(this), 0, sizeof (object_pod));
574 528
575 SET_FLAG (this, FLAG_REMOVED); 529 SET_FLAG (this, FLAG_REMOVED);
530
531 /* What is not cleared is next, prev, and count */
532
533 expmul = 1.0;
534 face = blank_face;
535 attacked_by_count = -1;
536
537 if (settings.casting_time)
538 casting_time = -1;
576} 539}
577 540
578void object::clone (object *destination) 541void object::clone (object *destination)
579{ 542{
580 *(object_copy *) destination = *this; 543 *(object_copy *)destination = *this;
581 *(object_pod *) destination = *this; 544 *(object_pod *)destination = *this;
582 545
583 if (self || cb) 546 if (self || cb)
584 INVOKE_OBJECT (CLONE, this, ARG_OBJECT (destination)); 547 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} 548}
618 549
619/* 550/*
620 * copy object first frees everything allocated by the second object, 551 * copy object first frees everything allocated by the second object,
621 * and then copies the contends of the first object into the second 552 * and then copies the contends of the first object into the second
622 * object, allocating what needs to be allocated. Basically, any 553 * object, allocating what needs to be allocated. Basically, any
623 * data that is malloc'd needs to be re-malloc/copied. Otherwise, 554 * 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 555 * if the first object is freed, the pointers in the new object
625 * will point at garbage. 556 * will point at garbage.
626 */ 557 */
627
628void 558void
629copy_object (object *op2, object *op) 559copy_object (object *op2, object *op)
630{ 560{
631 bool is_freed = QUERY_FLAG (op, FLAG_FREED); 561 bool is_freed = QUERY_FLAG (op, FLAG_FREED);
632 bool is_removed = QUERY_FLAG (op, FLAG_REMOVED); 562 bool is_removed = QUERY_FLAG (op, FLAG_REMOVED);
692/* 622/*
693 * Updates the speed of an object. If the speed changes from 0 to another 623 * 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. 624 * 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. 625 * This function needs to be called whenever the speed of an object changes.
696 */ 626 */
697
698void 627void
699update_ob_speed (object *op) 628update_ob_speed (object *op)
700{ 629{
701 extern int arch_init; 630 extern int arch_init;
702 631
711 abort (); 640 abort ();
712#else 641#else
713 op->speed = 0; 642 op->speed = 0;
714#endif 643#endif
715 } 644 }
645
716 if (arch_init) 646 if (arch_init)
717 {
718 return; 647 return;
719 } 648
720 if (FABS (op->speed) > MIN_ACTIVE_SPEED) 649 if (FABS (op->speed) > MIN_ACTIVE_SPEED)
721 { 650 {
722 /* If already on active list, don't do anything */ 651 /* If already on active list, don't do anything */
723 if (op->active_next || op->active_prev || op == active_objects) 652 if (op->active_next || op->active_prev || op == active_objects)
724 return; 653 return;
725 654
726 /* process_events() expects us to insert the object at the beginning 655 /* process_events() expects us to insert the object at the beginning
727 * of the list. */ 656 * of the list. */
728 op->active_next = active_objects; 657 op->active_next = active_objects;
658
729 if (op->active_next != NULL) 659 if (op->active_next != NULL)
730 op->active_next->active_prev = op; 660 op->active_next->active_prev = op;
661
731 active_objects = op; 662 active_objects = op;
732 } 663 }
733 else 664 else
734 { 665 {
735 /* If not on the active list, nothing needs to be done */ 666 /* If not on the active list, nothing needs to be done */
737 return; 668 return;
738 669
739 if (op->active_prev == NULL) 670 if (op->active_prev == NULL)
740 { 671 {
741 active_objects = op->active_next; 672 active_objects = op->active_next;
673
742 if (op->active_next != NULL) 674 if (op->active_next != NULL)
743 op->active_next->active_prev = NULL; 675 op->active_next->active_prev = NULL;
744 } 676 }
745 else 677 else
746 { 678 {
747 op->active_prev->active_next = op->active_next; 679 op->active_prev->active_next = op->active_next;
680
748 if (op->active_next) 681 if (op->active_next)
749 op->active_next->active_prev = op->active_prev; 682 op->active_next->active_prev = op->active_prev;
750 } 683 }
684
751 op->active_next = NULL; 685 op->active_next = NULL;
752 op->active_prev = NULL; 686 op->active_prev = NULL;
753 } 687 }
754} 688}
755 689
901 835
902 if (op->more != NULL) 836 if (op->more != NULL)
903 update_object (op->more, action); 837 update_object (op->more, action);
904} 838}
905 839
906static unordered_vector < object *>mortals; 840static unordered_vector<object *> mortals;
907static 841static std::vector<object *> freed;
908std::vector < object *>
909 freed;
910 842
911void object::free_mortals () 843void object::free_mortals ()
912{ 844{
913 for (unordered_vector < object *>::iterator i = mortals.begin (); i != mortals.end ();) 845 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();)
914 if (!(*i)->refcount) 846 if ((*i)->refcnt)
847 ++i; // further delay freeing
848 else
915 { 849 {
916 freed.push_back (*i); 850 freed.push_back (*i);//D
851 //delete *i;
917 mortals.erase (i); 852 mortals.erase (i);
918 } 853 }
919 else 854
920 ++i; 855 if (mortals.size())//D
856 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D
921} 857}
922 858
923object::object () 859object::object ()
924{ 860{
925 SET_FLAG (this, FLAG_REMOVED); 861 SET_FLAG (this, FLAG_REMOVED);
968 objects = next; 904 objects = next;
969} 905}
970 906
971object *object::create () 907object *object::create ()
972{ 908{
973 object * 909 object *op;
974 op;
975 910
976 if (freed.empty ()) 911 if (freed.empty ())
977 op = new object; 912 op = new object;
978
979 else 913 else
980 { 914 {
981 // highly annoying, but the only way to get it stable right now 915 // highly annoying, but the only way to get it stable right now
982 op = freed.back (); 916 op = freed.back ();
983 freed.pop_back (); 917 freed.pop_back ();
1002void object::free (bool free_inventory) 936void object::free (bool free_inventory)
1003{ 937{
1004 if (QUERY_FLAG (this, FLAG_FREED)) 938 if (QUERY_FLAG (this, FLAG_FREED))
1005 return; 939 return;
1006 940
941 if (QUERY_FLAG (this, FLAG_FRIENDLY))
942 remove_friendly_object (this);
943
1007 if (!QUERY_FLAG (this, FLAG_REMOVED)) 944 if (!QUERY_FLAG (this, FLAG_REMOVED))
1008 remove_ob (this); 945 remove_ob (this);
1009
1010 if (QUERY_FLAG (this, FLAG_FRIENDLY))
1011 remove_friendly_object (this);
1012 946
1013 SET_FLAG (this, FLAG_FREED); 947 SET_FLAG (this, FLAG_FREED);
1014 948
1015 if (more) 949 if (more)
1016 { 950 {
1022 { 956 {
1023 /* Only if the space blocks everything do we not process - 957 /* Only if the space blocks everything do we not process -
1024 * if some form of movement is allowed, let objects 958 * if some form of movement is allowed, let objects
1025 * drop on that space. 959 * drop on that space.
1026 */ 960 */
1027 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || (GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)) 961 if (free_inventory || !map || map->in_memory != MAP_IN_MEMORY || GET_MAP_MOVE_BLOCK (map, x, y) == MOVE_ALL)
1028 { 962 {
1029 object *op = inv; 963 object *op = inv;
1030 964
1031 while (op) 965 while (op)
1032 { 966 {
1058 op = tmp; 992 op = tmp;
1059 } 993 }
1060 } 994 }
1061 } 995 }
1062 996
1063 clear_owner (this); 997 owner = 0;
1064 998
1065 /* Remove object from the active list */ 999 /* Remove object from the active list */
1066 speed = 0; 1000 speed = 0;
1067 update_ob_speed (this); 1001 update_ob_speed (this);
1068 1002
2908{ 2842{
2909 shstr key_ (key); 2843 shstr key_ (key);
2910 2844
2911 return set_ob_key_value_s (op, key_, value, add_key); 2845 return set_ob_key_value_s (op, key_, value, add_key);
2912} 2846}
2847
2848object::depth_iterator::depth_iterator (object *container)
2849: iterator_base (container)
2850{
2851 while (item->inv)
2852 item = item->inv;
2853}
2854
2855void
2856object::depth_iterator::next ()
2857{
2858 if (item->below)
2859 {
2860 item = item->below;
2861
2862 while (item->inv)
2863 item = item->inv;
2864 }
2865 else
2866 item = item->env;
2867}
2868

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines