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.12 by elmex, Sun Sep 3 14:33:47 2006 UTC vs.
Revision 1.17 by root, Mon Sep 4 17:27:13 2006 UTC

1/* 1/*
2 * static char *rcsid_object_c = 2 * static char *rcsid_object_c =
3 * "$Id: object.C,v 1.12 2006/09/03 14:33:47 elmex Exp $"; 3 * "$Id: object.C,v 1.17 2006/09/04 17:27:13 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};
121 * 111 *
122 * Improvements made with merge: Better checking on potion, and also 112 * Improvements made with merge: Better checking on potion, and also
123 * check weight 113 * check weight
124 */ 114 */
125 115
126int CAN_MERGE(object *ob1, object *ob2) { 116bool
127 117object::can_merge (object *ob1, object *ob2)
118{
128 /* A couple quicksanity checks */ 119 /* A couple quicksanity checks */
129 if ((ob1 == ob2) || (ob1->type != ob2->type)) return 0; 120 if ((ob1 == ob2) || (ob1->type != ob2->type))
130
131 if (ob1->speed != ob2->speed) return 0;
132 /* Note sure why the following is the case - either the object has to
133 * be animated or have a very low speed. Is this an attempted monster
134 * check?
135 */
136 if (!QUERY_FLAG(ob1,FLAG_ANIMATE) && FABS((ob1)->speed) > MIN_ACTIVE_SPEED)
137 return 0; 121 return 0;
138 122
123 if (ob1->speed != ob2->speed)
124 return 0;
125
139 /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that 126 /* Do not merge objects if nrof would overflow. We use 1UL<<31 since that
140 * value could not be stored in a sint32 (which unfortunately sometimes is 127 * value could not be stored in a sint32 (which unfortunately sometimes is
141 * used to store nrof). 128 * used to store nrof).
142 */ 129 */
143 if (ob1->nrof+ob2->nrof >= 1UL<<31) 130 if (ob1->nrof + ob2->nrof >= 1UL << 31)
144 return 0; 131 return 0;
145 132
133 /* If the objects have been identified, set the BEEN_APPLIED flag.
134 * This is to the comparison of the flags below will be OK. We
135 * just can't ignore the been applied or identified flags, as they
136 * are not equal - just if it has been identified, the been_applied
137 * flags lose any meaning.
138 */
139 if (QUERY_FLAG (ob1, FLAG_IDENTIFIED))
140 SET_FLAG (ob1, FLAG_BEEN_APPLIED);
141
142 if (QUERY_FLAG (ob2, FLAG_IDENTIFIED))
143 SET_FLAG (ob2, FLAG_BEEN_APPLIED);
144
145
146 /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something
147 * being locked in inventory should prevent merging.
148 * 0x4 in flags3 is CLIENT_SENT
149 */
150 if ((ob1->arch != ob2->arch) ||
151 (ob1->flags[0] != ob2->flags[0]) ||
152 (ob1->flags[1] != ob2->flags[1]) ||
153 ((ob1->flags[2] & ~0x400000) != (ob2->flags[2] & ~0x400000)) ||
154 ((ob1->flags[3] & ~0x4) != (ob2->flags[3] & ~0x4)) ||
155 (ob1->name != ob2->name) ||
156 (ob1->title != ob2->title) ||
157 (ob1->msg != ob2->msg) ||
158 (ob1->weight != ob2->weight) ||
159 (memcmp (&ob1->resist, &ob2->resist, sizeof (ob1->resist)) != 0) ||
160 (memcmp (&ob1->stats, &ob2->stats, sizeof (ob1->stats)) != 0) ||
161 (ob1->attacktype != ob2->attacktype) ||
162 (ob1->magic != ob2->magic) ||
163 (ob1->slaying != ob2->slaying) ||
164 (ob1->skill != ob2->skill) ||
165 (ob1->value != ob2->value) ||
166 (ob1->animation_id != ob2->animation_id) ||
167 (ob1->client_type != ob2->client_type) ||
168 (ob1->materialname != ob2->materialname) ||
169 (ob1->lore != ob2->lore) ||
170 (ob1->subtype != ob2->subtype) ||
171 (ob1->move_type != ob2->move_type) ||
172 (ob1->move_block != ob2->move_block) ||
173 (ob1->move_allow != ob2->move_allow) ||
174 (ob1->move_on != ob2->move_on) ||
175 (ob1->move_off != ob2->move_off) ||
176 (ob1->move_slow != ob2->move_slow) ||
177 (ob1->move_slow_penalty != ob2->move_slow_penalty))
178 return 0;
179
146 /* This is really a spellbook check - really, we should 180 /* This is really a spellbook check - really, we should
147 * check all objects in the inventory. 181 * check all objects in the inventory.
148 */ 182 */
149 if (ob1->inv || ob2->inv) { 183 if (ob1->inv || ob2->inv)
184 {
150 /* if one object has inventory but the other doesn't, not equiv */ 185 /* if one object has inventory but the other doesn't, not equiv */
151 if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv)) return 0; 186 if ((ob1->inv && !ob2->inv) || (ob2->inv && !ob1->inv))
187 return 0;
152 188
153 /* Now check to see if the two inventory objects could merge */ 189 /* Now check to see if the two inventory objects could merge */
154 if (!CAN_MERGE(ob1->inv, ob2->inv)) return 0; 190 if (!CAN_MERGE (ob1->inv, ob2->inv))
191 return 0;
155 192
156 /* inventory ok - still need to check rest of this object to see 193 /* inventory ok - still need to check rest of this object to see
157 * if it is valid. 194 * if it is valid.
158 */ 195 */
159 } 196 }
160 197
161 /* If the objects have been identified, set the BEEN_APPLIED flag.
162 * This is to the comparison of the flags below will be OK. We
163 * just can't ignore the been applied or identified flags, as they
164 * are not equal - just if it has been identified, the been_applied
165 * flags lose any meaning.
166 */
167 if (QUERY_FLAG(ob1, FLAG_IDENTIFIED))
168 SET_FLAG(ob1, FLAG_BEEN_APPLIED);
169
170 if (QUERY_FLAG(ob2, FLAG_IDENTIFIED))
171 SET_FLAG(ob2, FLAG_BEEN_APPLIED);
172
173
174 /* the 0x400000 on flags2 is FLAG_INV_LOCK. I don't think something
175 * being locked in inventory should prevent merging.
176 * 0x4 in flags3 is CLIENT_SENT
177 */
178 if ((ob1->arch != ob2->arch) ||
179 (ob1->flags[0] != ob2->flags[0]) ||
180 (ob1->flags[1] != ob2->flags[1]) ||
181 ((ob1->flags[2] & ~0x400000) != (ob2->flags[2] & ~ 0x400000)) ||
182 ((ob1->flags[3] & ~0x4) != (ob2->flags[3] & ~0x4)) ||
183 (ob1->name != ob2->name) ||
184 (ob1->title != ob2->title) ||
185 (ob1->msg != ob2->msg) ||
186 (ob1->weight != ob2->weight) ||
187 (memcmp(&ob1->resist, &ob2->resist, sizeof(ob1->resist))!=0) ||
188 (memcmp(&ob1->stats, &ob2->stats, sizeof(ob1->stats))!=0) ||
189 (ob1->attacktype != ob2->attacktype) ||
190 (ob1->magic != ob2->magic) ||
191 (ob1->slaying != ob2->slaying) ||
192 (ob1->skill != ob2->skill) ||
193 (ob1->value != ob2->value) ||
194 (ob1->animation_id != ob2->animation_id) ||
195 (ob1->client_type != ob2->client_type) ||
196 (ob1->materialname != ob2->materialname) ||
197 (ob1->lore != ob2->lore) ||
198 (ob1->subtype != ob2->subtype) ||
199 (ob1->move_type != ob2->move_type) ||
200 (ob1->move_block != ob2->move_block) ||
201 (ob1->move_allow != ob2->move_allow) ||
202 (ob1->move_on != ob2->move_on) ||
203 (ob1->move_off != ob2->move_off) ||
204 (ob1->move_slow != ob2->move_slow) ||
205 (ob1->move_slow_penalty != ob2->move_slow_penalty)
206 )
207 return 0;
208
209 /* Don't merge objects that are applied. With the new 'body' code, 198 /* Don't merge objects that are applied. With the new 'body' code,
210 * it is possible for most any character to have more than one of 199 * it is possible for most any character to have more than one of
211 * some items equipped, and we don't want those to merge. 200 * some items equipped, and we don't want those to merge.
212 */ 201 */
213 if (QUERY_FLAG(ob1, FLAG_APPLIED) || QUERY_FLAG(ob2, FLAG_APPLIED)) 202 if (QUERY_FLAG (ob1, FLAG_APPLIED) || QUERY_FLAG (ob2, FLAG_APPLIED))
214 return 0; 203 return 0;
215 204
205 /* Note sure why the following is the case - either the object has to
206 * be animated or have a very low speed. Is this an attempted monster
207 * check?
208 */
209 if (!QUERY_FLAG (ob1, FLAG_ANIMATE)
210 && FABS ((ob1)->speed) > MIN_ACTIVE_SPEED)
211 return 0;
212
216 switch (ob1->type) { 213 switch (ob1->type)
214 {
217 case SCROLL: 215 case SCROLL:
218 if (ob1->level != ob2->level) return 0; 216 if (ob1->level != ob2->level)
217 return 0;
219 break; 218 break;
220
221 } 219 }
220
222 if (ob1->key_values != NULL || ob2->key_values != NULL) { 221 if (ob1->key_values != NULL || ob2->key_values != NULL)
222 {
223 /* At least one of these has key_values. */ 223 /* At least one of these has key_values. */
224 if ((ob1->key_values == NULL) != (ob2->key_values == NULL)) { 224 if ((ob1->key_values == NULL) != (ob2->key_values == NULL))
225 /* One has fields, but the other one doesn't. */ 225 /* One has fields, but the other one doesn't. */
226 return 0; 226 return 0;
227 } else if (!compare_ob_value_lists(ob1, ob2)) { 227 else if (!compare_ob_value_lists (ob1, ob2))
228 return 0; 228 return 0;
229 } 229 }
230
231 //TODO: generate an event or call into perl for additional checks
232 if (ob1->self || ob2->self)
230 } 233 {
234 ob1->optimise ();
235 ob2->optimise ();
231 236
237 if (ob1->self || ob2->self)
238 return 0;
239 }
240
232 /* Everything passes, must be OK. */ 241 /* Everything passes, must be OK. */
233 return 1; 242 return 1;
234} 243}
235
236/* 244/*
237 * sum_weight() is a recursive function which calculates the weight 245 * sum_weight() is a recursive function which calculates the weight
238 * an object is carrying. It goes through in figures out how much 246 * an object is carrying. It goes through in figures out how much
239 * containers are carrying, and sums it up. 247 * containers are carrying, and sums it up.
240 */ 248 */
388 break; 396 break;
389 397
390 return op; 398 return op;
391} 399}
392 400
393void free_all_object_data(void) { 401void free_all_object_data ()
394#ifdef MEMORY_DEBUG 402{
395 object *op, *next; 403 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} 404}
408 405
409/* 406/*
410 * Returns the object which this object marks as being the owner. 407 * 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 408 * A id-scheme is used to avoid pointing to objects which have been
438 op->owner->refcount--; 435 op->owner->refcount--;
439 436
440 op->owner = NULL; 437 op->owner = NULL;
441 op->ownercount = 0; 438 op->ownercount = 0;
442} 439}
443
444
445 440
446/* 441/*
447 * Sets the owner and sets the skill and exp pointers to owner's current 442 * Sets the owner and sets the skill and exp pointers to owner's current
448 * skill and experience objects. 443 * skill and experience objects.
449 */ 444 */
496 } 491 }
497 set_owner(op, owner); 492 set_owner(op, owner);
498 493
499} 494}
500 495
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 496/* Zero the key_values on op, decrementing the shared-string
520 * refcounts and freeing the links. 497 * refcounts and freeing the links.
521 */ 498 */
522static void free_key_values(object * op) 499static void free_key_values(object * op)
523{ 500{
529 } 506 }
530 507
531 op->key_values = 0; 508 op->key_values = 0;
532} 509}
533 510
511void object::clear ()
512{
513 attachable_base::clear ();
514
515 free_key_values (this);
516
517 name = 0;
518 name_pl = 0;
519 title = 0;
520 race = 0;
521 slaying = 0;
522 skill = 0;
523 msg = 0;
524 lore = 0;
525 custom_name = 0;
526 materialname = 0;
527
528 memset (static_cast<object_pod *>(this), 0, sizeof (object_pod));
529
530 SET_FLAG (this, FLAG_REMOVED);
531}
532
533void object::clone (object *destination)
534{
535 *(object_copy *)destination = *(object_copy *)this;
536 *(object_pod *)destination = *(object_pod *)this;
537
538 if (self || cb)
539 INVOKE_OBJECT (CLONE, this, ARG_OBJECT (destination));
540}
541
534/* 542/*
535 * clear_object() frees everything allocated by an object, and also 543 * clear_object() frees everything allocated by an object, and also
536 * clears all variables and flags to default settings. 544 * clears all variables and flags to default settings.
537 */ 545 */
538 546
539void clear_object(object *op) 547void clear_object (object *op)
540{ 548{
541 op->clear (); 549 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 550
565 op->contr = NULL; 551 op->contr = NULL;
566 op->below = NULL; 552 op->below = NULL;
567 op->above = NULL; 553 op->above = NULL;
568 op->inv = NULL; 554 op->inv = NULL;
574 op->refcount=0; 560 op->refcount=0;
575 op->active_next = NULL; 561 op->active_next = NULL;
576 op->active_prev = NULL; 562 op->active_prev = NULL;
577 /* What is not cleared is next, prev, and count */ 563 /* What is not cleared is next, prev, and count */
578 564
579 op->expmul=1.0; 565 op->expmul = 1.0;
580 op->face = blank_face; 566 op->face = blank_face;
581 op->attacked_by_count = (tag_t) -1; 567 op->attacked_by_count = -1;
582 568
583 if (settings.casting_time) 569 if (settings.casting_time)
584 op->casting_time = -1; 570 op->casting_time = -1;
585} 571}
586 572
591 * data that is malloc'd needs to be re-malloc/copied. Otherwise, 577 * 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 578 * if the first object is freed, the pointers in the new object
593 * will point at garbage. 579 * will point at garbage.
594 */ 580 */
595 581
596void copy_object(object *op2, object *op) 582void copy_object (object *op2, object *op)
597{ 583{
598 int is_freed=QUERY_FLAG(op,FLAG_FREED),is_removed=QUERY_FLAG(op,FLAG_REMOVED); 584 bool is_freed = QUERY_FLAG (op, FLAG_FREED);
585 bool is_removed = QUERY_FLAG (op, FLAG_REMOVED);
599 586
600 op->clear ();
601
602 free_key_values (op);
603
604 *(object_special *)op = *(object_special *)op2;
605 op2->clone (op); 587 op2->clone (op);
606 588
607 if (is_freed) SET_FLAG(op,FLAG_FREED); 589 if (is_freed) SET_FLAG (op, FLAG_FREED);
608 if (is_removed) SET_FLAG(op,FLAG_REMOVED); 590 if (is_removed) SET_FLAG (op, FLAG_REMOVED);
609 591
610 if (op2->speed < 0) 592 if (op2->speed < 0)
611 op->speed_left = op2->speed_left - RANDOM() % 200 / 100.0; 593 op->speed_left = op2->speed_left - RANDOM() % 200 / 100.0;
612 594
613 /* Copy over key_values, if any. */ 595 /* Copy over key_values, if any. */
614 if (op2->key_values != NULL) { 596 if (op2->key_values != NULL)
597 {
615 key_value *tail = NULL; 598 key_value *tail = NULL;
616 key_value *i; 599 key_value *i;
617 600
618 op->key_values = NULL; 601 op->key_values = NULL;
619 602
634 else 617 else
635 { 618 {
636 tail->next = new_link; 619 tail->next = new_link;
637 tail = new_link; 620 tail = new_link;
638 } 621 }
639 } 622 }
640 } 623 }
641 624
642 update_ob_speed (op); 625 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} 626}
675 627
676/* 628/*
677 * get_object() grabs an object from the list of unused objects, makes 629 * get_object() grabs an object from the list of unused objects, makes
678 * sure it is initialised, and returns it. 630 * sure it is initialised, and returns it.
679 * If there are no free objects, expand_objects() is called to get more. 631 * If there are no free objects, expand_objects() is called to get more.
680 */ 632 */
681 633
682object *get_object(void) 634object *get_object ()
683{ 635{
684 object *op; 636 object *op = new object;
685 637
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; 638 op->count = ++ob_count;
700 op->name=NULL; 639
701 op->name_pl=NULL; 640 op->active_next = 0;
702 op->title=NULL; 641 op->active_prev = 0;
703 op->race=NULL; 642
704 op->slaying=NULL;
705 op->skill = NULL;
706 op->lore=NULL;
707 op->msg=NULL;
708 op->materialname=NULL;
709 op->next=objects; 643 op->next = objects;
710 op->prev=NULL; 644 op->prev = 0;
711 op->active_next = NULL; 645
712 op->active_prev = NULL;
713 if(objects!=NULL) 646 if (objects)
714 objects->prev=op; 647 objects->prev = op;
648
715 objects=op; 649 objects = op;
716 clear_object(op); 650
717 SET_FLAG(op,FLAG_REMOVED); 651 SET_FLAG (op, FLAG_REMOVED);
718 nroffreeobjects--; 652
653 op->expmul = 1.0;
654 op->face = blank_face;
655 op->attacked_by_count = -1;
656
719 return op; 657 return op;
720} 658}
721 659
722/* 660/*
723 * If an object with the IS_TURNABLE() flag needs to be turned due 661 * If an object with the IS_TURNABLE() flag needs to be turned due
931 * 869 *
932 * If free_inventory is set, free inventory as well. Else drop items in 870 * If free_inventory is set, free inventory as well. Else drop items in
933 * inventory to the ground. 871 * inventory to the ground.
934 */ 872 */
935 873
874void
936void free_object(object *ob) { 875free_object (object * ob)
876{
937 free_object2(ob, 0); 877 free_object2 (ob, 0);
938} 878}
879
880void
939void free_object2(object *ob, int free_inventory) { 881free_object2 (object * ob, int free_inventory)
882{
940 object *tmp,*op; 883 object *tmp, *op;
941 884
942 ob->clear ();
943
944 if (!QUERY_FLAG(ob,FLAG_REMOVED)) { 885 if (!QUERY_FLAG (ob, FLAG_REMOVED))
886 {
945 LOG(llevDebug,"Free object called with non removed object\n"); 887 LOG (llevDebug, "Free object called with non removed object\n");
946 dump_object(ob); 888 dump_object (ob);
947#ifdef MANY_CORES 889#ifdef MANY_CORES
948 abort(); 890 abort ();
949#endif 891#endif
950 } 892 }
893
951 if(QUERY_FLAG(ob,FLAG_FRIENDLY)) { 894 if (QUERY_FLAG (ob, FLAG_FRIENDLY))
895 {
952 LOG(llevMonster,"Warning: tried to free friendly object.\n"); 896 LOG (llevMonster, "Warning: tried to free friendly object.\n");
953 remove_friendly_object(ob); 897 remove_friendly_object (ob);
954 } 898 }
899
955 if(QUERY_FLAG(ob,FLAG_FREED)) { 900 if (QUERY_FLAG (ob, FLAG_FREED))
901 {
956 dump_object(ob); 902 dump_object (ob);
957 LOG(llevError,"Trying to free freed object.\n%s\n",errmsg); 903 LOG (llevError, "Trying to free freed object.\n%s\n", errmsg);
958 return; 904 return;
959 } 905 }
906
960 if(ob->more!=NULL) { 907 if (ob->more != NULL)
908 {
961 free_object2(ob->more, free_inventory); 909 free_object2 (ob->more, free_inventory);
962 ob->more=NULL; 910 ob->more = NULL;
963 } 911 }
912
964 if (ob->inv) { 913 if (ob->inv)
914 {
965 /* Only if the space blocks everything do we not process - 915 /* Only if the space blocks everything do we not process -
966 * if some form of movemnt is allowed, let objects 916 * if some form of movement is allowed, let objects
967 * drop on that space. 917 * drop on that space.
968 */ 918 */
969 if (free_inventory || ob->map==NULL || ob->map->in_memory!=MAP_IN_MEMORY || 919 if (free_inventory || ob->map == NULL
920 || ob->map->in_memory != MAP_IN_MEMORY
970 (GET_MAP_MOVE_BLOCK(ob->map, ob->x, ob->y) == MOVE_ALL)) 921 || (GET_MAP_MOVE_BLOCK (ob->map, ob->x, ob->y) == MOVE_ALL))
971 { 922 {
972 op=ob->inv; 923 op = ob->inv;
973 while(op!=NULL) { 924
925 while (op != NULL)
926 {
974 tmp=op->below; 927 tmp = op->below;
975 remove_ob(op); 928 remove_ob (op);
976 free_object2(op, free_inventory); 929 free_object2 (op, free_inventory);
977 op=tmp; 930 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 } 931 }
932 }
933 else
934 { /* Put objects in inventory onto this space */
935 op = ob->inv;
936
937 while (op != NULL)
938 {
939 tmp = op->below;
940 remove_ob (op);
941
942 if (QUERY_FLAG (op, FLAG_STARTEQUIP)
943 || QUERY_FLAG (op, FLAG_NO_DROP) || op->type == RUNE
944 || op->type == TRAP || QUERY_FLAG (op, FLAG_IS_A_TEMPLATE))
945 free_object (op);
946 else
947 {
948 op->x = ob->x;
949 op->y = ob->y;
950 insert_ob_in_map (op, ob->map, NULL, 0); /* Insert in same map as the envir */
951 }
952
953 op = tmp;
954 }
955 }
956 }
957
997 /* Remove object from the active list */ 958 /* Remove object from the active list */
998 ob->speed = 0; 959 ob->speed = 0;
999 update_ob_speed(ob); 960 update_ob_speed (ob);
1000 961
1001 SET_FLAG(ob, FLAG_FREED); 962 SET_FLAG (ob, FLAG_FREED);
1002 ob->count = 0; 963 ob->count = 0;
1003 964
1004 /* Remove this object from the list of used objects */ 965 /* Remove this object from the list of used objects */
1005 if(ob->prev==NULL) { 966 if (ob->prev == NULL)
967 {
1006 objects=ob->next; 968 objects = ob->next;
969
1007 if(objects!=NULL) 970 if (objects != NULL)
1008 objects->prev=NULL; 971 objects->prev = NULL;
972 }
973 else
1009 } 974 {
1010 else {
1011 ob->prev->next=ob->next; 975 ob->prev->next = ob->next;
976
1012 if(ob->next!=NULL) 977 if (ob->next != NULL)
1013 ob->next->prev=ob->prev; 978 ob->next->prev = ob->prev;
1014 } 979 }
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 980
1026 free_key_values (ob); 981 free_key_values (ob);
1027 982
1028 /* Now link it with the free_objects list: */ 983 /* Now link it with the free_objects list: */
1029 ob->prev=NULL; 984 ob->prev = 0;
1030 ob->next=free_objects; 985 ob->next = 0;
1031 986
1032 if(free_objects!=NULL) 987 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} 988}
1077 989
1078/* 990/*
1079 * sub_weight() recursively (outwards) subtracts a number from the 991 * sub_weight() recursively (outwards) subtracts a number from the
1080 * weight of an object (and what is carried by it's environment(s)). 992 * weight of an object (and what is carried by it's environment(s)).
2485 fclose(tempfile); 2397 fclose(tempfile);
2486 2398
2487 op=get_object(); 2399 op=get_object();
2488 2400
2489 object_thawer thawer (filename); 2401 object_thawer thawer (filename);
2402
2490 if (thawer) 2403 if (thawer)
2491 load_object(thawer,op,LO_NEWFILE,0); 2404 load_object(thawer,op,0);
2405
2492 LOG(llevDebug," load str completed, object=%s\n", &op->name); 2406 LOG(llevDebug," load str completed, object=%s\n", &op->name);
2493 CLEAR_FLAG(op,FLAG_REMOVED); 2407 CLEAR_FLAG(op,FLAG_REMOVED);
2494 2408
2495 return op; 2409 return op;
2496} 2410}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines