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.36 by root, Tue Sep 12 19:20:06 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. */
32#include <object.h> 31#include <object.h>
33#include <funcpoint.h> 32#include <funcpoint.h>
34#include <loader.h> 33#include <loader.h>
35 34
36int nrofallocobjects = 0; 35int nrofallocobjects = 0;
36static UUID uuid;
37const uint64 UUID_SKIP = 1<<19;
37 38
38object *objects; /* Pointer to the list of used objects */
39object *active_objects; /* List of active objects that need to be processed */ 39object *active_objects; /* List of active objects that need to be processed */
40 40
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, 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,
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 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
43}; 43};
49}; 49};
50int freedir[SIZEOFFREE] = { 50int freedir[SIZEOFFREE] = {
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, 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,
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 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
53}; 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}
54 131
55/* 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. */
56static int 133static int
57compare_ob_value_lists_one (const object *wants, const object *has) 134compare_ob_value_lists_one (const object *wants, const object *has)
58{ 135{
254 { 331 {
255 if (inv->inv) 332 if (inv->inv)
256 sum_weight (inv); 333 sum_weight (inv);
257 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); 334 sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1);
258 } 335 }
336
259 if (op->type == CONTAINER && op->stats.Str) 337 if (op->type == CONTAINER && op->stats.Str)
260 sum = (sum * (100 - op->stats.Str)) / 100; 338 sum = (sum * (100 - op->stats.Str)) / 100;
339
261 if (op->carrying != sum) 340 if (op->carrying != sum)
262 op->carrying = sum; 341 op->carrying = sum;
342
263 return sum; 343 return sum;
264} 344}
265 345
266/** 346/**
267 * Return the outermost environment object for a given object. 347 * Return the outermost environment object for a given object.
365void 445void
366dump_all_objects (void) 446dump_all_objects (void)
367{ 447{
368 object *op; 448 object *op;
369 449
370 for (op = objects; op != NULL; op = op->next) 450 for (op = object::first; op != NULL; op = op->next)
371 { 451 {
372 dump_object (op); 452 dump_object (op);
373 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg); 453 fprintf (logfile, "Object %d\n:%s\n", op->count, errmsg);
374 } 454 }
375} 455}
401object * 481object *
402find_object (tag_t i) 482find_object (tag_t i)
403{ 483{
404 object *op; 484 object *op;
405 485
406 for (op = objects; op != NULL; op = op->next) 486 for (op = object::first; op != NULL; op = op->next)
407 if (op->count == i) 487 if (op->count == i)
408 break; 488 break;
409 return op; 489 return op;
410} 490}
411 491
419find_object_name (const char *str) 499find_object_name (const char *str)
420{ 500{
421 shstr_cmp str_ (str); 501 shstr_cmp str_ (str);
422 object *op; 502 object *op;
423 503
424 for (op = objects; op != NULL; op = op->next) 504 for (op = object::first; op != NULL; op = op->next)
425 if (op->name == str_) 505 if (op->name == str_)
426 break; 506 break;
427 507
428 return op; 508 return op;
429} 509}
430 510
431void 511void
432free_all_object_data () 512free_all_object_data ()
433{ 513{
434 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects); 514 LOG (llevDebug, "%d allocated objects\n", nrofallocobjects);
435}
436
437/*
438 * Returns the object which this object marks as being the owner.
439 * A id-scheme is used to avoid pointing to objects which have been
440 * freed and are now reused. If this is detected, the owner is
441 * set to NULL, and NULL is returned.
442 * Changed 2004-02-12 - if the player is setting at the play again
443 * prompt, he is removed, and we don't want to treat him as an owner of
444 * anything, so check removed flag. I don't expect that this should break
445 * anything - once an object is removed, it is basically dead anyways.
446 */
447object *
448object::get_owner ()
449{
450 if (!owner
451 || QUERY_FLAG (owner, FLAG_FREED)
452 || QUERY_FLAG (owner, FLAG_REMOVED))
453 owner = 0;
454
455 return owner;
456} 515}
457 516
458/* 517/*
459 * 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
460 * skill and experience objects. 519 * skill and experience objects.
530 589
531 /* What is not cleared is next, prev, and count */ 590 /* What is not cleared is next, prev, and count */
532 591
533 expmul = 1.0; 592 expmul = 1.0;
534 face = blank_face; 593 face = blank_face;
535 attacked_by_count = -1;
536 594
537 if (settings.casting_time) 595 if (settings.casting_time)
538 casting_time = -1; 596 casting_time = -1;
539} 597}
540 598
835 893
836 if (op->more != NULL) 894 if (op->more != NULL)
837 update_object (op->more, action); 895 update_object (op->more, action);
838} 896}
839 897
840static unordered_vector<object *> mortals; 898object::vector object::mortals;
841static std::vector<object *> freed; 899object::vector object::objects; // not yet used
900object *object::first;
842 901
843void object::free_mortals () 902void object::free_mortals ()
844{ 903{
845 for (unordered_vector<object *>::iterator i = mortals.begin (); i != mortals.end ();) 904 for (AUTODECL (i, mortals.begin ()); i != mortals.end ();)
846 if ((*i)->refcnt) 905 if ((*i)->refcnt)
847 ++i; // further delay freeing 906 ++i; // further delay freeing
848 else 907 else
849 { 908 {
850 freed.push_back (*i);//D
851 //delete *i; 909 delete *i;
852 mortals.erase (i); 910 mortals.erase (i);
853 } 911 }
854 912
855 if (mortals.size() && 0)//D 913 static int lastmortals = 0;//D
914
915 if (mortals.size() != lastmortals)//D
916 {
917 lastmortals = mortals.size ();//D
856 LOG (llevDebug, "%d objects in mortal queue\n", mortals.size());//D 918 LOG (llevDebug, "%d objects in mortal queue\n", lastmortals);//D
919 }
857} 920}
858 921
859object::object () 922object::object ()
860{ 923{
861 SET_FLAG (this, FLAG_REMOVED); 924 SET_FLAG (this, FLAG_REMOVED);
862 925
863 expmul = 1.0; 926 expmul = 1.0;
864 face = blank_face; 927 face = blank_face;
865 attacked_by_count = -1;
866} 928}
867 929
868object::~object () 930object::~object ()
869{ 931{
870 free_key_values (this); 932 free_key_values (this);
871} 933}
872 934
873void object::link () 935void object::link ()
874{ 936{
875 count = ++ob_count; 937 count = ++ob_count;
938 uuid = gen_uuid ();
876 939
877 prev = 0; 940 prev = 0;
878 next = objects; 941 next = object::first;
879 942
880 if (objects) 943 if (object::first)
881 objects->prev = this; 944 object::first->prev = this;
882 945
883 objects = this; 946 object::first = this;
884} 947}
885 948
886void object::unlink () 949void object::unlink ()
887{ 950{
888 count = 0; 951 //count = 0;//D
952 if (!prev && !next) return;//D
953
954 if (this == object::first)
955 object::first = next;
889 956
890 /* Remove this object from the list of used objects */ 957 /* Remove this object from the list of used objects */
891 if (prev)
892 {
893 prev->next = next; 958 if (prev) prev->next = next;
959 if (next) next->prev = prev;
960
894 prev = 0; 961 prev = 0;
895 }
896
897 if (next)
898 {
899 next->prev = prev;
900 next = 0; 962 next = 0;
901 }
902
903 if (this == objects)
904 objects = next;
905} 963}
906 964
907object *object::create () 965object *object::create ()
908{ 966{
909 object *op;
910
911 if (freed.empty ())
912 op = new object; 967 object *op = new object;
913 else
914 {
915 // highly annoying, but the only way to get it stable right now
916 op = freed.back ();
917 freed.pop_back ();
918 op->~object ();
919 new ((void *) op) object;
920 }
921
922 op->link (); 968 op->link ();
923 return op; 969 return op;
924} 970}
925 971
926/* 972/*
992 op = tmp; 1038 op = tmp;
993 } 1039 }
994 } 1040 }
995 } 1041 }
996 1042
1043 // clear those pointers that likely might have circular references to us
997 owner = 0; 1044 owner = 0;
1045 enemy = 0;
1046 attacked_by = 0;
998 1047
999 /* Remove object from the active list */ 1048 /* Remove object from the active list */
1000 speed = 0; 1049 speed = 0;
1001 update_ob_speed (this); 1050 update_ob_speed (this);
1002 1051
1014sub_weight (object *op, signed long weight) 1063sub_weight (object *op, signed long weight)
1015{ 1064{
1016 while (op != NULL) 1065 while (op != NULL)
1017 { 1066 {
1018 if (op->type == CONTAINER) 1067 if (op->type == CONTAINER)
1019 {
1020 weight = (signed long) (weight * (100 - op->stats.Str) / 100); 1068 weight = (signed long) (weight * (100 - op->stats.Str) / 100);
1021 } 1069
1022 op->carrying -= weight; 1070 op->carrying -= weight;
1023 op = op->env; 1071 op = op->env;
1024 } 1072 }
1025} 1073}
1026 1074
1034 */ 1082 */
1035 1083
1036void 1084void
1037remove_ob (object *op) 1085remove_ob (object *op)
1038{ 1086{
1087 object *tmp, *last = 0;
1039 object * 1088 object *otmp;
1040 tmp, *
1041 last = NULL;
1042 object *
1043 otmp;
1044 1089
1045 tag_t 1090 tag_t tag;
1046 tag;
1047 int
1048 check_walk_off; 1091 int check_walk_off;
1049 mapstruct * 1092 mapstruct *m;
1050 m;
1051 1093
1052 sint16 1094 sint16 x, y;
1053 x,
1054 y;
1055 1095
1056 if (QUERY_FLAG (op, FLAG_REMOVED)) 1096 if (QUERY_FLAG (op, FLAG_REMOVED))
1057 return; 1097 return;
1058 1098
1059 SET_FLAG (op, FLAG_REMOVED); 1099 SET_FLAG (op, FLAG_REMOVED);
1222 * This function goes through all objects below and including top, and 1262 * This function goes through all objects below and including top, and
1223 * merges op to the first matching object. 1263 * merges op to the first matching object.
1224 * If top is NULL, it is calculated. 1264 * If top is NULL, it is calculated.
1225 * 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
1226 */ 1266 */
1227
1228object * 1267object *
1229merge_ob (object *op, object *top) 1268merge_ob (object *op, object *top)
1230{ 1269{
1231 if (!op->nrof) 1270 if (!op->nrof)
1232 return 0; 1271 return 0;
1248 free_object (op); 1287 free_object (op);
1249 return top; 1288 return top;
1250 } 1289 }
1251 } 1290 }
1252 1291
1253 return NULL; 1292 return 0;
1254} 1293}
1255 1294
1256/* 1295/*
1257 * 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
1258 * job preparing multi-part monsters 1297 * job preparing multi-part monsters
1585 remove_ob (tmp); 1624 remove_ob (tmp);
1586 free_object (tmp); 1625 free_object (tmp);
1587 } 1626 }
1588 } 1627 }
1589 1628
1590 tmp1 = arch_to_object (find_archetype (arch_string)); 1629 tmp1 = arch_to_object (archetype::find (arch_string));
1591 1630
1592 tmp1->x = op->x; 1631 tmp1->x = op->x;
1593 tmp1->y = op->y; 1632 tmp1->y = op->y;
1594 insert_ob_in_map (tmp1, op->map, op, 0); 1633 insert_ob_in_map (tmp1, op->map, op, 0);
1595} 1634}
2653 2692
2654 if (tempfile == NULL) 2693 if (tempfile == NULL)
2655 { 2694 {
2656 LOG (llevError, "Error - Unable to access load object temp file\n"); 2695 LOG (llevError, "Error - Unable to access load object temp file\n");
2657 return NULL; 2696 return NULL;
2658 }; 2697 }
2698
2659 fprintf (tempfile, obstr); 2699 fprintf (tempfile, obstr);
2660 fclose (tempfile); 2700 fclose (tempfile);
2661 2701
2662 op = get_object (); 2702 op = get_object ();
2663 2703

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines