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.13 by root, Sun Sep 3 22:45:55 2006 UTC vs.
Revision 1.14 by root, Mon Sep 4 11:07:59 2006 UTC

1/* 1/*
2 * static char *rcsid_object_c = 2 * static char *rcsid_object_c =
3 * "$Id: object.C,v 1.13 2006/09/03 22:45:55 root Exp $"; 3 * "$Id: object.C,v 1.14 2006/09/04 11:07:59 root Exp $";
4 */ 4 */
5 5
6/* 6/*
7 CrossFire, A Multiplayer game for X-windows 7 CrossFire, A Multiplayer game for X-windows
8 8
37#endif /* win32 */ 37#endif /* win32 */
38#include <object.h> 38#include <object.h>
39#include <funcpoint.h> 39#include <funcpoint.h>
40#include <skills.h> 40#include <skills.h>
41#include <loader.h> 41#include <loader.h>
42#ifdef MEMORY_DEBUG
43int nroffreeobjects = 0;
44int nrofallocobjects = 0; 42int nrofallocobjects = 0;
45#undef OBJ_EXPAND
46#define OBJ_EXPAND 1
47#else
48object objarray[STARTMAX]; /* All objects, allocated this way at first */
49int nroffreeobjects = STARTMAX; /* How many OBs allocated and free (free) */
50int nrofallocobjects = STARTMAX; /* How many OBs allocated (free + used) */
51#endif
52 43
53object *objects; /* Pointer to the list of used objects */ 44object *objects; /* Pointer to the list of used objects */
54object *free_objects; /* Pointer to the list of unused objects */
55object *active_objects; /* List of active objects that need to be processed */ 45object *active_objects; /* List of active objects that need to be processed */
56 46
57short freearr_x[SIZEOFFREE]= 47short freearr_x[SIZEOFFREE]=
58 {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, 48 {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,
59 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1}; 49 0,1,2,3,3,3,3,3,3,3,2,1,0,-1,-2,-3,-3,-3,-3,-3,-3,-3,-2,-1};
388 break; 378 break;
389 379
390 return op; 380 return op;
391} 381}
392 382
393void free_all_object_data(void) { 383void free_all_object_data ()
394#ifdef MEMORY_DEBUG 384{
395 object *op, *next; 385 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
396
397 for (op=free_objects; op!=NULL; ) {
398 next=op->next;
399 free(op);
400 nrofallocobjects--;
401 nroffreeobjects--;
402 op=next;
403 }
404#endif
405 LOG(llevDebug,"%d allocated objects, %d free objects, STARMAX=%d\n",
406 nrofallocobjects, nroffreeobjects,STARTMAX);
407} 386}
408 387
409/* 388/*
410 * Returns the object which this object marks as being the owner. 389 * Returns the object which this object marks as being the owner.
411 * A id-scheme is used to avoid pointing to objects which have been 390 * A id-scheme is used to avoid pointing to objects which have been
438 op->owner->refcount--; 417 op->owner->refcount--;
439 418
440 op->owner = NULL; 419 op->owner = NULL;
441 op->ownercount = 0; 420 op->ownercount = 0;
442} 421}
443
444
445 422
446/* 423/*
447 * Sets the owner and sets the skill and exp pointers to owner's current 424 * Sets the owner and sets the skill and exp pointers to owner's current
448 * skill and experience objects. 425 * skill and experience objects.
449 */ 426 */
496 } 473 }
497 set_owner(op, owner); 474 set_owner(op, owner);
498 475
499} 476}
500 477
501/*
502 * Resets vital variables in an object
503 */
504
505void reset_object(object *op) {
506
507 op->name = NULL;
508 op->name_pl = NULL;
509 op->title = NULL;
510 op->race = NULL;
511 op->slaying = NULL;
512 op->skill = NULL;
513 op->msg = NULL;
514 op->materialname = NULL;
515 op->lore = NULL;
516 clear_object(op);
517}
518
519/* Zero the key_values on op, decrementing the shared-string 478/* Zero the key_values on op, decrementing the shared-string
520 * refcounts and freeing the links. 479 * refcounts and freeing the links.
521 */ 480 */
522static void free_key_values(object * op) 481static void free_key_values(object * op)
523{ 482{
529 } 488 }
530 489
531 op->key_values = 0; 490 op->key_values = 0;
532} 491}
533 492
493void object::clear ()
494{
495 attachable_base::clear ();
496
497 free_key_values (this);
498
499 name = 0;
500 name_pl = 0;
501 title = 0;
502 race = 0;
503 slaying = 0;
504 skill = 0;
505 msg = 0;
506 lore = 0;
507 custom_name = 0;
508 materialname = 0;
509
510 memset (static_cast<object_pod *>(this), 0, sizeof (object_pod));
511
512 SET_FLAG (this, FLAG_REMOVED);
513}
514
515void object::clone (object *destination)
516{
517 *(object_copy *)destination = *(object_copy *)this;
518 *(object_pod *)destination = *(object_pod *)this;
519
520 if (self || cb)
521 INVOKE_OBJECT (CLONE, this, ARG_OBJECT (destination));
522}
523
534/* 524/*
535 * clear_object() frees everything allocated by an object, and also 525 * clear_object() frees everything allocated by an object, and also
536 * clears all variables and flags to default settings. 526 * clears all variables and flags to default settings.
537 */ 527 */
538 528
539void clear_object(object *op) 529void clear_object (object *op)
540{ 530{
541 op->clear (); 531 op->clear ();
542
543 free_key_values (op);
544
545 /* the memset will clear all these values for us, but we need
546 * to reduce the refcount on them.
547 */
548 op->name = 0;
549 op->name_pl = 0;
550 op->title = 0;
551 op->race = 0;
552 op->slaying = 0;
553 op->skill = 0;
554 op->msg = 0;
555 op->lore = 0;
556 op->materialname = 0;
557
558 memset((void*)op, 0, sizeof (object_special));
559 /* Below here, we clear things that are not done by the memset,
560 * or set default values that are not zero.
561 */
562 /* This is more or less true */
563 SET_FLAG (op, FLAG_REMOVED);
564 532
565 op->contr = NULL; 533 op->contr = NULL;
566 op->below = NULL; 534 op->below = NULL;
567 op->above = NULL; 535 op->above = NULL;
568 op->inv = NULL; 536 op->inv = NULL;
574 op->refcount=0; 542 op->refcount=0;
575 op->active_next = NULL; 543 op->active_next = NULL;
576 op->active_prev = NULL; 544 op->active_prev = NULL;
577 /* What is not cleared is next, prev, and count */ 545 /* What is not cleared is next, prev, and count */
578 546
579 op->expmul=1.0; 547 op->expmul = 1.0;
580 op->face = blank_face; 548 op->face = blank_face;
581 op->attacked_by_count = (tag_t) -1; 549 op->attacked_by_count = -1;
582 550
583 if (settings.casting_time) 551 if (settings.casting_time)
584 op->casting_time = -1; 552 op->casting_time = -1;
585} 553}
586 554
591 * data that is malloc'd needs to be re-malloc/copied. Otherwise, 559 * data that is malloc'd needs to be re-malloc/copied. Otherwise,
592 * if the first object is freed, the pointers in the new object 560 * if the first object is freed, the pointers in the new object
593 * will point at garbage. 561 * will point at garbage.
594 */ 562 */
595 563
596void copy_object(object *op2, object *op) 564void copy_object (object *op2, object *op)
597{ 565{
598 int is_freed=QUERY_FLAG(op,FLAG_FREED),is_removed=QUERY_FLAG(op,FLAG_REMOVED); 566 bool is_freed = QUERY_FLAG (op, FLAG_FREED);
567 bool is_removed = QUERY_FLAG (op, FLAG_REMOVED);
599 568
600 op->clear ();
601
602 free_key_values (op);
603
604 *(object_special *)op = *(object_special *)op2;
605 op2->clone (op); 569 op2->clone (op);
606 570
607 if (is_freed) SET_FLAG(op,FLAG_FREED); 571 if (is_freed) SET_FLAG (op, FLAG_FREED);
608 if (is_removed) SET_FLAG(op,FLAG_REMOVED); 572 if (is_removed) SET_FLAG (op, FLAG_REMOVED);
609 573
610 if (op2->speed < 0) 574 if (op2->speed < 0)
611 op->speed_left = op2->speed_left - RANDOM() % 200 / 100.0; 575 op->speed_left = op2->speed_left - RANDOM() % 200 / 100.0;
612 576
613 /* Copy over key_values, if any. */ 577 /* Copy over key_values, if any. */
614 if (op2->key_values != NULL) { 578 if (op2->key_values != NULL)
579 {
615 key_value *tail = NULL; 580 key_value *tail = NULL;
616 key_value *i; 581 key_value *i;
617 582
618 op->key_values = NULL; 583 op->key_values = NULL;
619 584
634 else 599 else
635 { 600 {
636 tail->next = new_link; 601 tail->next = new_link;
637 tail = new_link; 602 tail = new_link;
638 } 603 }
639 } 604 }
640 } 605 }
641 606
642 update_ob_speed (op); 607 update_ob_speed (op);
643}
644
645/*
646 * expand_objects() allocates more objects for the list of unused objects.
647 * It is called from get_object() if the unused list is empty.
648 */
649
650void expand_objects(void) {
651 int i;
652 object *obj;
653 obj = new object [OBJ_EXPAND];
654
655 free_objects=obj;
656 obj[0].prev=NULL;
657 obj[0].next= &obj[1],
658 SET_FLAG(&(obj[0]), FLAG_REMOVED);
659 SET_FLAG(&(obj[0]), FLAG_FREED);
660
661 for(i=1;i<OBJ_EXPAND-1;i++) {
662 obj[i].next= &obj[i+1],
663 obj[i].prev= &obj[i-1],
664 SET_FLAG(&(obj[i]), FLAG_REMOVED);
665 SET_FLAG(&(obj[i]), FLAG_FREED);
666 }
667 obj[OBJ_EXPAND-1].prev= &obj[OBJ_EXPAND-2],
668 obj[OBJ_EXPAND-1].next=NULL,
669 SET_FLAG(&(obj[OBJ_EXPAND-1]), FLAG_REMOVED);
670 SET_FLAG(&(obj[OBJ_EXPAND-1]), FLAG_FREED);
671
672 nrofallocobjects += OBJ_EXPAND;
673 nroffreeobjects += OBJ_EXPAND;
674} 608}
675 609
676/* 610/*
677 * get_object() grabs an object from the list of unused objects, makes 611 * get_object() grabs an object from the list of unused objects, makes
678 * sure it is initialised, and returns it. 612 * sure it is initialised, and returns it.
679 * If there are no free objects, expand_objects() is called to get more. 613 * If there are no free objects, expand_objects() is called to get more.
680 */ 614 */
681 615
682object *get_object(void) 616object *get_object ()
683{ 617{
684 object *op; 618 object *op = new object;
685 619
686 if(free_objects==NULL)
687 expand_objects();
688
689 op = free_objects;
690
691 if (!QUERY_FLAG (op, FLAG_FREED))
692 LOG(llevError,"Fatal: Getting busy object.\n");
693
694 free_objects = op->next;
695
696 if (free_objects != NULL)
697 free_objects->prev = NULL;
698
699 op->count= ++ob_count; 620 op->count = ++ob_count;
700 op->name=NULL; 621
701 op->name_pl=NULL; 622 op->active_next = 0;
702 op->title=NULL; 623 op->active_prev = 0;
703 op->race=NULL; 624
704 op->slaying=NULL;
705 op->skill = NULL;
706 op->lore=NULL;
707 op->msg=NULL;
708 op->materialname=NULL;
709 op->next=objects; 625 op->next = objects;
710 op->prev=NULL; 626 op->prev = 0;
711 op->active_next = NULL; 627
712 op->active_prev = NULL;
713 if(objects!=NULL) 628 if (objects)
714 objects->prev=op; 629 objects->prev = op;
630
715 objects=op; 631 objects = op;
716 clear_object(op); 632
717 SET_FLAG(op,FLAG_REMOVED); 633 SET_FLAG (op, FLAG_REMOVED);
718 nroffreeobjects--; 634
719 return op; 635 return op;
720} 636}
721 637
722/* 638/*
723 * If an object with the IS_TURNABLE() flag needs to be turned due 639 * If an object with the IS_TURNABLE() flag needs to be turned due
931 * 847 *
932 * If free_inventory is set, free inventory as well. Else drop items in 848 * If free_inventory is set, free inventory as well. Else drop items in
933 * inventory to the ground. 849 * inventory to the ground.
934 */ 850 */
935 851
852void
936void free_object(object *ob) { 853free_object (object * ob)
854{
937 free_object2(ob, 0); 855 free_object2 (ob, 0);
938} 856}
857
858void
939void free_object2(object *ob, int free_inventory) { 859free_object2 (object * ob, int free_inventory)
860{
940 object *tmp,*op; 861 object *tmp, *op;
941 862
942 ob->clear ();
943
944 if (!QUERY_FLAG(ob,FLAG_REMOVED)) { 863 if (!QUERY_FLAG (ob, FLAG_REMOVED))
864 {
945 LOG(llevDebug,"Free object called with non removed object\n"); 865 LOG (llevDebug, "Free object called with non removed object\n");
946 dump_object(ob); 866 dump_object (ob);
947#ifdef MANY_CORES 867#ifdef MANY_CORES
948 abort(); 868 abort ();
949#endif 869#endif
950 } 870 }
871
951 if(QUERY_FLAG(ob,FLAG_FRIENDLY)) { 872 if (QUERY_FLAG (ob, FLAG_FRIENDLY))
873 {
952 LOG(llevMonster,"Warning: tried to free friendly object.\n"); 874 LOG (llevMonster, "Warning: tried to free friendly object.\n");
953 remove_friendly_object(ob); 875 remove_friendly_object (ob);
954 } 876 }
877
955 if(QUERY_FLAG(ob,FLAG_FREED)) { 878 if (QUERY_FLAG (ob, FLAG_FREED))
879 {
956 dump_object(ob); 880 dump_object (ob);
957 LOG(llevError,"Trying to free freed object.\n%s\n",errmsg); 881 LOG (llevError, "Trying to free freed object.\n%s\n", errmsg);
958 return; 882 return;
959 } 883 }
884
960 if(ob->more!=NULL) { 885 if (ob->more != NULL)
886 {
961 free_object2(ob->more, free_inventory); 887 free_object2 (ob->more, free_inventory);
962 ob->more=NULL; 888 ob->more = NULL;
963 } 889 }
890
964 if (ob->inv) { 891 if (ob->inv)
892 {
965 /* Only if the space blocks everything do we not process - 893 /* Only if the space blocks everything do we not process -
966 * if some form of movemnt is allowed, let objects 894 * if some form of movemnt is allowed, let objects
967 * drop on that space. 895 * drop on that space.
968 */ 896 */
969 if (free_inventory || ob->map==NULL || ob->map->in_memory!=MAP_IN_MEMORY || 897 if (free_inventory || ob->map == NULL
898 || ob->map->in_memory != MAP_IN_MEMORY
970 (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) 899 || (GET_MAP_MOVE_BLOCK (ob->map, ob->x, ob->y) == MOVE_ALL))
971 { 900 {
972 op=ob->inv; 901 op = ob->inv;
973 while(op!=NULL) { 902
903 while (op != NULL)
904 {
974 tmp=op->below; 905 tmp = op->below;
975 remove_ob(op); 906 remove_ob (op);
976 free_object2(op, free_inventory); 907 free_object2 (op, free_inventory);
977 op=tmp; 908 op = tmp;
978 }
979 }
980 else { /* Put objects in inventory onto this space */
981 op=ob->inv;
982 while(op!=NULL) {
983 tmp=op->below;
984 remove_ob(op);
985 if(QUERY_FLAG(op,FLAG_STARTEQUIP)||QUERY_FLAG(op,FLAG_NO_DROP) ||
986 op->type==RUNE || op->type==TRAP || QUERY_FLAG(op,FLAG_IS_A_TEMPLATE))
987 free_object(op);
988 else {
989 op->x=ob->x;
990 op->y=ob->y;
991 insert_ob_in_map(op,ob->map,NULL,0); /* Insert in same map as the envir */
992 }
993 op=tmp;
994 }
995 }
996 } 909 }
910 }
911 else
912 { /* Put objects in inventory onto this space */
913 op = ob->inv;
914
915 while (op != NULL)
916 {
917 tmp = op->below;
918 remove_ob (op);
919
920 if (QUERY_FLAG (op, FLAG_STARTEQUIP)
921 || QUERY_FLAG (op, FLAG_NO_DROP) || op->type == RUNE
922 || op->type == TRAP || QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))
923 free_object (op);
924 else
925 {
926 op->x = ob->x;
927 op->y = ob->y;
928 insert_ob_in_map (op, ob->map, NULL, 0); /* Insert in same map as the envir */
929 }
930
931 op = tmp;
932 }
933 }
934 }
935
997 /* Remove object from the active list */ 936 /* Remove object from the active list */
998 ob->speed = 0; 937 ob->speed = 0;
999 update_ob_speed(ob); 938 update_ob_speed (ob);
1000 939
1001 SET_FLAG(ob, FLAG_FREED); 940 SET_FLAG (ob, FLAG_FREED);
1002 ob->count = 0; 941 ob->count = 0;
1003 942
1004 /* Remove this object from the list of used objects */ 943 /* Remove this object from the list of used objects */
1005 if(ob->prev==NULL) { 944 if (ob->prev == NULL)
945 {
1006 objects=ob->next; 946 objects = ob->next;
947
1007 if(objects!=NULL) 948 if (objects != NULL)
1008 objects->prev=NULL; 949 objects->prev = NULL;
950 }
951 else
1009 } 952 {
1010 else {
1011 ob->prev->next=ob->next; 953 ob->prev->next = ob->next;
954
1012 if(ob->next!=NULL) 955 if (ob->next != NULL)
1013 ob->next->prev=ob->prev; 956 ob->next->prev = ob->prev;
1014 } 957 }
1015
1016 ob->name = 0;
1017 ob->name_pl = 0;
1018 ob->title = 0;
1019 ob->race = 0;
1020 ob->slaying = 0;
1021 ob->skill = 0;
1022 ob->lore = 0;
1023 ob->msg = 0;
1024 ob->materialname = 0;
1025 958
1026 free_key_values (ob); 959 free_key_values (ob);
1027 960
1028 /* Now link it with the free_objects list: */ 961 /* Now link it with the free_objects list: */
1029 ob->prev=NULL; 962 ob->prev = 0;
1030 ob->next=free_objects; 963 ob->next = 0;
1031 964
1032 if(free_objects!=NULL) 965 delete ob;
1033 free_objects->prev=ob;
1034
1035 free_objects=ob;
1036 nroffreeobjects++;
1037}
1038
1039/*
1040 * count_free() returns the number of objects on the list of free objects.
1041 */
1042
1043int count_free ()
1044{
1045 int i=0;
1046 object *tmp=free_objects;
1047 while(tmp!=NULL)
1048 tmp=tmp->next, i++;
1049 return i;
1050}
1051
1052/*
1053 * count_used() returns the number of objects on the list of used objects.
1054 */
1055
1056int count_used()
1057{
1058 int i=0;
1059 object *tmp=objects;
1060 while(tmp!=NULL)
1061 tmp=tmp->next, i++;
1062 return i;
1063}
1064
1065/*
1066 * count_active() returns the number of objects on the list of active objects.
1067 */
1068
1069int count_active()
1070{
1071 int i=0;
1072 object *tmp=active_objects;
1073 while(tmp!=NULL)
1074 tmp=tmp->active_next, i++;
1075 return i;
1076} 966}
1077 967
1078/* 968/*
1079 * sub_weight() recursively (outwards) subtracts a number from the 969 * sub_weight() recursively (outwards) subtracts a number from the
1080 * weight of an object (and what is carried by it's environment(s)). 970 * weight of an object (and what is carried by it's environment(s)).

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines