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.337 by root, Thu May 6 21:45:49 2010 UTC vs.
Revision 1.345 by root, Sun May 1 16:58:15 2011 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2001 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the 9 * the terms of the Affero GNU General Public License as published by the
71 9, 10, 13, 14, 17, 18, 21, 22, 71 9, 10, 13, 14, 17, 18, 21, 22,
72 25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45, 48, 72 25, 26, 27, 30, 31, 32, 33, 36, 37, 39, 39, 42, 43, 44, 45, 48,
73 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49 73 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49
74}; 74};
75 75
76const char *wall_suffix[16] = {
77 "0",
78 "1_3",
79 "1_4",
80 "2_1_2",
81 "1_2",
82 "2_2_4",
83 "2_2_1",
84 "3_1",
85 "1_1",
86 "2_2_3",
87 "2_2_2",
88 "3_3",
89 "2_1_1",
90 "3_4",
91 "3_2",
92 "4"
93};
94
76static void 95static void
77write_uuid (uval64 skip, bool sync) 96write_uuid (uval64 skip, bool sync)
78{ 97{
79 CALL_BEGIN (2); 98 CALL_BEGIN (2);
80 CALL_ARG_SV (newSVval64 (skip)); 99 CALL_ARG_SV (newSVval64 (skip));
214 233
215/* Returns TRUE if every key_values in wants has a partner with the same value in has. */ 234/* Returns TRUE if every key_values in wants has a partner with the same value in has. */
216static bool 235static bool
217compare_ob_value_lists_one (const object *wants, const object *has) 236compare_ob_value_lists_one (const object *wants, const object *has)
218{ 237{
219 /* n-squared behaviour (see kv_get), but I'm hoping both 238 /* n-squared behaviour (see kv.get), but I'm hoping both
220 * objects with lists are rare, and lists stay short. If not, use a 239 * objects with lists are rare, and lists stay short. If not, use a
221 * different structure or at least keep the lists sorted... 240 * different structure or at least keep the lists sorted...
222 */ 241 */
223 242
224 /* For each field in wants, */ 243 /* For each field in wants, */
225 for (key_value *kv = wants->key_values; kv; kv = kv->next) 244 for (key_value *kv = wants->kv.first; kv; kv = kv->next)
226 if (has->kv_get (kv->key) != kv->value) 245 if (has->kv.get (kv->key) != kv->value)
227 return false; 246 return false;
228 247
229 /* If we get here, every field in wants has a matching field in has. */ 248 /* If we get here, every field in wants has a matching field in has. */
230 return true; 249 return true;
231} 250}
255 */ 274 */
256bool object::can_merge_slow (object *ob1, object *ob2) 275bool object::can_merge_slow (object *ob1, object *ob2)
257{ 276{
258 /* A couple quick sanity checks */ 277 /* A couple quick sanity checks */
259 if (ob1 == ob2 278 if (ob1 == ob2
260 || ob1->type != ob2->type 279 || ob1->type != ob2->type
261 || ob1->value != ob2->value 280 || ob1->value != ob2->value
262 || ob1->name != ob2->name 281 || ob1->name != ob2->name
282 || ob1->custom_name != ob2->custom_name
263 || fabs (ob1->speed - ob2->speed) >= MIN_ACTIVE_SPEED) 283 || fabs (ob1->speed - ob2->speed) >= MIN_ACTIVE_SPEED)
264 return 0; 284 return 0;
265 285
266 /* Do not merge objects if nrof would overflow, assume nrof 286 /* Do not merge objects if nrof would overflow, assume nrof
267 * is always 0 .. 2**31-1 */ 287 * is always 0 .. 2**31-1 */
353 if (ob1->level != ob2->level) 373 if (ob1->level != ob2->level)
354 return 0; 374 return 0;
355 break; 375 break;
356 } 376 }
357 377
358 if (ob1->key_values || ob2->key_values) 378 if (!ob1->kv.empty () || !ob2->kv.empty ())
359 { 379 {
360 /* At least one of these has key_values. */ 380 /* At least one of these has key_values. */
361 if ((!ob1->key_values) != (!ob2->key_values)) 381 if (ob1->kv.empty () != ob2->kv.empty ())
362 return 0; /* One has fields, but the other one doesn't. */ 382 return 0; /* One has fields, but the other one doesn't. */
363 383
364 if (!compare_ob_value_lists (ob1, ob2)) 384 if (!compare_ob_value_lists (ob1, ob2))
365 return 0; 385 return 0;
366 } 386 }
579 } 599 }
580 600
581 this->owner = owner; 601 this->owner = owner;
582} 602}
583 603
584/* Zero the key_values on op, decrementing the shared-string
585 * refcounts and freeing the links.
586 */
587static void
588free_key_values (object *op)
589{
590 for (key_value *i = op->key_values; i; )
591 {
592 key_value *next = i->next;
593 delete i;
594
595 i = next;
596 }
597
598 op->key_values = 0;
599}
600
601/* 604/*
602 * copy_to first frees everything allocated by the dst object, 605 * copy_to first frees everything allocated by the dst object,
603 * and then copies the contents of itself into the second 606 * and then copies the contents of itself into the second
604 * object, allocating what needs to be allocated. Basically, any 607 * object, allocating what needs to be allocated. Basically, any
605 * data that is malloc'd needs to be re-malloc/copied. Otherwise, 608 * data that is malloc'd needs to be re-malloc/copied. Otherwise,
609void 612void
610object::copy_to (object *dst) 613object::copy_to (object *dst)
611{ 614{
612 dst->remove (); 615 dst->remove ();
613 *(object_copy *)dst = *this; 616 *(object_copy *)dst = *this;
617
618 // maybe move to object_copy?
619 dst->kv = kv;
620
614 dst->flag [FLAG_REMOVED] = true; 621 dst->flag [FLAG_REMOVED] = true;
615
616 /* Copy over key_values, if any. */
617 if (key_values)
618 {
619 key_value *tail = 0;
620 dst->key_values = 0;
621
622 for (key_value *i = key_values; i; i = i->next)
623 {
624 key_value *new_link = new key_value;
625
626 new_link->next = 0;
627 new_link->key = i->key;
628 new_link->value = i->value;
629
630 /* Try and be clever here, too. */
631 if (!dst->key_values)
632 {
633 dst->key_values = new_link;
634 tail = new_link;
635 }
636 else
637 {
638 tail->next = new_link;
639 tail = new_link;
640 }
641 }
642 }
643
644 dst->activate (); 622 dst->activate ();
645} 623}
646 624
647void 625void
648object::instantiate () 626object::instantiate ()
649{ 627{
650 if (!uuid.seq) // HACK 628 if (!uuid.seq) // HACK
651 uuid = UUID::gen (); 629 uuid = UUID::gen ();
652 630
653 // TODO: unclean state changes, should nt be done in copy_to AND instantiate 631 // TODO: unclean state changes, should not be done in copy_to AND instantiate
654 if (flag [FLAG_RANDOM_SPEED] && speed) 632 if (flag [FLAG_RANDOM_SPEED] && speed)
655 speed_left = - speed - rndm (); // TODO animation 633 speed_left = - speed - rndm (); // TODO animation
656 else 634 else
657 speed_left = -1.; 635 speed_left = -1.;
658 636
811 789
812object::~object () 790object::~object ()
813{ 791{
814 unlink (); 792 unlink ();
815 793
816 free_key_values (this); 794 kv.clear ();
817} 795}
818 796
819void object::link () 797void object::link ()
820{ 798{
821 assert (!index);//D 799 assert (!index);//D
1163 1141
1164 if (pl && pl->is_player ()) 1142 if (pl && pl->is_player ())
1165 { 1143 {
1166 if (expect_false (pl->contr->combat_ob == this)) 1144 if (expect_false (pl->contr->combat_ob == this))
1167 { 1145 {
1168 pl->apply (pl->contr->combat_ob, AP_UNAPPLY); 1146 pl->apply (pl->contr->combat_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1169 pl->contr->combat_ob = 0; 1147 pl->contr->combat_ob = 0;
1170 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob); 1148 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob);
1171 } 1149 }
1172 1150
1173 if (expect_false (pl->contr->ranged_ob == this)) 1151 if (expect_false (pl->contr->ranged_ob == this))
1174 { 1152 {
1175 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY); 1153 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1176 pl->contr->ranged_ob = 0; 1154 pl->contr->ranged_ob = 0;
1177 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob); 1155 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob);
1178 } 1156 }
1179 1157
1180 pl->contr->queue_stats_update (); 1158 pl->contr->queue_stats_update ();
1367{ 1345{
1368 op->remove (); 1346 op->remove ();
1369 1347
1370 if (m == &freed_map)//D TODO: remove soon 1348 if (m == &freed_map)//D TODO: remove soon
1371 {//D 1349 {//D
1372 LOG (llevError | logBacktrace, "tries to insret object on freed objects map: %s", op->debug_desc ());//D 1350 LOG (llevError | logBacktrace, "tries to insert object on freed objects map: %s", op->debug_desc ());//D
1373 }//D 1351 }//D
1374 1352
1375 /* Ideally, the caller figures this out. However, it complicates a lot 1353 /* Ideally, the caller figures this out. However, it complicates a lot
1376 * of areas of callers (eg, anything that uses find_free_spot would now 1354 * of areas of callers (eg, anything that uses find_free_spot would now
1377 * need extra work 1355 * need extra work
2474 return tmp; 2452 return tmp;
2475 2453
2476 return 0; 2454 return 0;
2477} 2455}
2478 2456
2457/* Zero the key_values on op, decrementing the shared-string
2458 * refcounts and freeing the links.
2459 */
2460void
2461key_values::clear ()
2462{
2463 for (key_value *kvp = first; kvp; )
2464 {
2465 key_value *next = kvp->next;
2466 delete kvp;
2467 kvp = next;
2468 }
2469
2470 first = 0;
2471}
2472
2479shstr_tmp 2473shstr_tmp
2480object::kv_get (shstr_tmp key) const 2474key_values::get (shstr_tmp key) const
2481{ 2475{
2482 for (key_value *kv = key_values; kv; kv = kv->next) 2476 for (key_value *kv = first; kv; kv = kv->next)
2483 if (kv->key == key) 2477 if (kv->key == key)
2484 return kv->value; 2478 return kv->value;
2485 2479
2486 return shstr (); 2480 return shstr ();
2487} 2481}
2488 2482
2489void 2483void
2484key_values::add (shstr_tmp key, shstr_tmp value)
2485{
2486 key_value *kv = new key_value;
2487
2488 kv->next = first;
2489 kv->key = key;
2490 kv->value = value;
2491
2492 first = kv;
2493}
2494
2495void
2490object::kv_set (shstr_tmp key, shstr_tmp value) 2496key_values::set (shstr_tmp key, shstr_tmp value)
2491{ 2497{
2492 for (key_value *kv = key_values; kv; kv = kv->next) 2498 for (key_value *kv = first; kv; kv = kv->next)
2493 if (kv->key == key) 2499 if (kv->key == key)
2494 { 2500 {
2495 kv->value = value; 2501 kv->value = value;
2496 return; 2502 return;
2497 } 2503 }
2498 2504
2499 key_value *kv = new key_value; 2505 add (key, value);
2500
2501 kv->next = key_values;
2502 kv->key = key;
2503 kv->value = value;
2504
2505 key_values = kv;
2506} 2506}
2507 2507
2508void 2508void
2509object::kv_del (shstr_tmp key) 2509key_values::del (shstr_tmp key)
2510{ 2510{
2511 for (key_value **kvp = &key_values; *kvp; kvp = &(*kvp)->next) 2511 for (key_value **kvp = &first; *kvp; kvp = &(*kvp)->next)
2512 if ((*kvp)->key == key) 2512 if ((*kvp)->key == key)
2513 { 2513 {
2514 key_value *kv = *kvp; 2514 key_value *kv = *kvp;
2515 *kvp = (*kvp)->next; 2515 *kvp = (*kvp)->next;
2516 delete kv; 2516 delete kv;
2517 return; 2517 return;
2518 } 2518 }
2519}
2520
2521void
2522key_values::reverse ()
2523{
2524 key_value *prev = 0;
2525 key_value *head = first;
2526
2527 while (head)
2528 {
2529 key_value *node = head;
2530 head = head->next;
2531 node->next = prev;
2532 prev = node;
2533 }
2534
2535 first = prev;
2536}
2537
2538key_values &
2539key_values::operator =(const key_values &kv)
2540{
2541 clear ();
2542
2543 for (key_value *kvp = kv.first; kvp; kvp = kvp->next)
2544 add (kvp->key, kvp->value);
2545
2546 reverse ();
2519} 2547}
2520 2548
2521object::depth_iterator::depth_iterator (object *container) 2549object::depth_iterator::depth_iterator (object *container)
2522: iterator_base (container) 2550: iterator_base (container)
2523{ 2551{
2703object::force_add (shstr_tmp name, int duration) 2731object::force_add (shstr_tmp name, int duration)
2704{ 2732{
2705 if (object *force = force_find (name)) 2733 if (object *force = force_find (name))
2706 force->destroy (); 2734 force->destroy ();
2707 2735
2708 object *force = get_archetype (FORCE_NAME); 2736 object *force = archetype::get (FORCE_NAME);
2709 2737
2710 force->slaying = name; 2738 force->slaying = name;
2711 force->force_set_timer (duration); 2739 force->force_set_timer (duration);
2712 force->flag [FLAG_APPLIED] = true; 2740 force->flag [FLAG_APPLIED] = true;
2713 2741
2797 return contr->mark; 2825 return contr->mark;
2798 else 2826 else
2799 return 0; 2827 return 0;
2800} 2828}
2801 2829
2830// put marked object first in the inventory
2831// this is used by identify-like spells so players can influence
2832// the order a bit.
2833void
2834object::splay_marked ()
2835{
2836 if (object *marked = mark ())
2837 splay (marked);
2838}
2839

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines