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.334 by root, Fri Apr 23 09:22:46 2010 UTC vs.
Revision 1.353 by root, Fri Jan 27 22:00:39 2012 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,2012 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 }
426 446
427 return 0; 447 return 0;
428} 448}
429 449
430// adjust weight per container type ("of holding") 450// adjust weight per container type ("of holding")
431static sint32 451static uint32
432weight_adjust_for (object *op, sint32 weight) 452weight_adjust_for (object *op, uint32 weight)
433{ 453{
434 return op->type == CONTAINER 454 return op->type == CONTAINER
435 ? lerp (weight, 0, 100, 0, 100 - op->stats.Str) 455 ? weight - weight * op->stats.Str / 100
436 : weight; 456 : weight;
437} 457}
438 458
439/* 459/*
440 * adjust_weight(object, weight) adds the specified weight to an object, 460 * subtracts, then adds, the specified weight to an object,
441 * and also updates how much the environment(s) is/are carrying. 461 * and also updates how much the environment(s) is/are carrying.
442 */ 462 */
443static void 463static void
444adjust_weight (object *op, sint32 weight) 464adjust_weight (object *op, sint32 sub, sint32 add)
445{ 465{
446 while (op) 466 while (op)
447 { 467 {
448 // adjust by actual difference to account for rounding errors 468 sint32 ocarrying = op->carrying;
449 // i.e. (w2 - w1) / f != w2 / f - w1 / f and the latter is correct
450 weight = weight_adjust_for (op, op->carrying + weight)
451 - weight_adjust_for (op, op->carrying);
452 469
453 if (!weight) 470 op->carrying -= weight_adjust_for (op, sub);
454 return; 471 op->carrying += weight_adjust_for (op, add);
455
456 op->carrying += weight;
457 472
458 if (object *pl = op->visible_to ()) 473 if (object *pl = op->visible_to ())
459 if (pl != op) // player is handled lazily 474 if (pl != op) // player is handled lazily
460 esrv_update_item (UPD_WEIGHT, pl, op); 475 esrv_update_item (UPD_WEIGHT, pl, op);
461 476
477 sub = ocarrying;
478 add = op->carrying;
479
462 op = op->env; 480 op = op->env;
463 } 481 }
464} 482}
465 483
466/* 484/*
473{ 491{
474 sint32 sum = 0; 492 sint32 sum = 0;
475 493
476 for (object *op = inv; op; op = op->below) 494 for (object *op = inv; op; op = op->below)
477 { 495 {
478 if (op->inv)
479 op->update_weight (); 496 op->update_weight ();
480 497
481 sum += op->total_weight (); 498 sum += weight_adjust_for (this, op->total_weight ());
482 } 499 }
483
484 sum = weight_adjust_for (this, sum);
485 500
486 if (sum != carrying) 501 if (sum != carrying)
487 { 502 {
488 if (carrying != sum)//D 503 if (carrying != sum && carrying)//D
489 LOG (llevDebug, "updating carrying got %ld, expected %ld (%s)\n", 504 LOG (llevDebug, "updating carrying got %ld, expected %ld (%s)\n",
490 (long long)sum, (long long)carrying, debug_desc ()); 505 (long long)sum, (long long)carrying, debug_desc ());
491 506
492 carrying = sum; 507 carrying = sum;
493 508
582 LOG (llevError | logBacktrace, "tried to set owner of %s to %s\n", debug_desc (), owner->debug_desc ()); 597 LOG (llevError | logBacktrace, "tried to set owner of %s to %s\n", debug_desc (), owner->debug_desc ());
583 return; 598 return;
584 } 599 }
585 600
586 this->owner = owner; 601 this->owner = owner;
587}
588
589/* Zero the key_values on op, decrementing the shared-string
590 * refcounts and freeing the links.
591 */
592static void
593free_key_values (object *op)
594{
595 for (key_value *i = op->key_values; i; )
596 {
597 key_value *next = i->next;
598 delete i;
599
600 i = next;
601 }
602
603 op->key_values = 0;
604} 602}
605 603
606/* 604/*
607 * copy_to first frees everything allocated by the dst object, 605 * copy_to first frees everything allocated by the dst object,
608 * and then copies the contents of itself into the second 606 * and then copies the contents of itself into the second
614void 612void
615object::copy_to (object *dst) 613object::copy_to (object *dst)
616{ 614{
617 dst->remove (); 615 dst->remove ();
618 *(object_copy *)dst = *this; 616 *(object_copy *)dst = *this;
617
618 // maybe move to object_copy?
619 dst->kv = kv;
620
619 dst->flag [FLAG_REMOVED] = true; 621 dst->flag [FLAG_REMOVED] = true;
620
621 /* Copy over key_values, if any. */
622 if (key_values)
623 {
624 key_value *tail = 0;
625 dst->key_values = 0;
626
627 for (key_value *i = key_values; i; i = i->next)
628 {
629 key_value *new_link = new key_value;
630
631 new_link->next = 0;
632 new_link->key = i->key;
633 new_link->value = i->value;
634
635 /* Try and be clever here, too. */
636 if (!dst->key_values)
637 {
638 dst->key_values = new_link;
639 tail = new_link;
640 }
641 else
642 {
643 tail->next = new_link;
644 tail = new_link;
645 }
646 }
647 }
648
649 dst->activate (); 622 dst->activate ();
650} 623}
651 624
652void 625void
653object::instantiate () 626object::instantiate ()
654{ 627{
655 if (!uuid.seq) // HACK 628 if (!uuid.seq) // HACK
656 uuid = UUID::gen (); 629 uuid = UUID::gen ();
657 630
658 // 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
659 if (flag [FLAG_RANDOM_SPEED] && speed) 632 if (flag [FLAG_RANDOM_SPEED] && speed)
660 speed_left = - speed - rndm (); // TODO animation 633 speed_left = - speed - rndm (); // TODO animation
661 else 634 else
662 speed_left = -1.; 635 speed_left = -1.;
663 636
764 } 737 }
765 738
766 mapspace &m = op->ms (); 739 mapspace &m = op->ms ();
767 740
768 if (!(m.flags_ & P_UPTODATE)) 741 if (!(m.flags_ & P_UPTODATE))
769 /* nop */; 742 m.update_up (); // nothing to do except copy up
770 else if (action == UP_OBJ_INSERT) 743 else if (action == UP_OBJ_INSERT)
771 { 744 {
772#if 0 745#if 0
773 // this is likely overkill, TODO: revisit (schmorp) 746 // this is likely overkill, TODO: revisit (schmorp)
774 if ((op->flag [FLAG_BLOCKSVIEW] && !(m.flags_ & P_BLOCKSVIEW)) 747 if ((op->flag [FLAG_BLOCKSVIEW] && !(m.flags_ & P_BLOCKSVIEW))
795 * that is being removed. 768 * that is being removed.
796 */ 769 */
797 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE) 770 else if (action == UP_OBJ_CHANGE || action == UP_OBJ_REMOVE)
798 m.invalidate (); 771 m.invalidate ();
799 else if (action == UP_OBJ_FACE) 772 else if (action == UP_OBJ_FACE)
800 /* Nothing to do for that case */ ; 773 m.update_up (); // nothing to do for that case, except copy up
801 else 774 else
802 LOG (llevError, "update_object called with invalid action: %d\n", action); 775 LOG (llevError, "update_object called with invalid action: %d\n", action);
803 776
804 if (op->more) 777 if (op->more)
805 update_object (op->more, action); 778 update_object (op->more, action);
816 789
817object::~object () 790object::~object ()
818{ 791{
819 unlink (); 792 unlink ();
820 793
821 free_key_values (this); 794 kv.clear ();
822} 795}
823 796
824void object::link () 797void object::link ()
825{ 798{
826 assert (!index);//D 799 assert (!index);//D
925 * if some form of movement is allowed, let objects 898 * if some form of movement is allowed, let objects
926 * drop on that space. 899 * drop on that space.
927 */ 900 */
928 if (!drop_to_ground 901 if (!drop_to_ground
929 || !map 902 || !map
930 || map->in_memory != MAP_ACTIVE 903 || !map->linkable ()
931 || map->no_drop 904 || map->no_drop
932 || ms ().move_block == MOVE_ALL) 905 || ms ().move_block == MOVE_ALL)
933 { 906 {
934 while (inv) 907 while (inv)
935 inv->destroy (); 908 inv->destroy ();
1032 1005
1033 freelist = li; 1006 freelist = li;
1034 ++free_count; 1007 ++free_count;
1035} 1008}
1036 1009
1037static struct freed_map : maptile
1038{
1039 freed_map ()
1040 : maptile (3, 3)
1041 {
1042 path = "<freed objects map>";
1043 name = "/internal/freed_objects_map";
1044 no_drop = 1;
1045 no_reset = 1;
1046
1047 in_memory = MAP_ACTIVE;
1048 }
1049
1050 ~freed_map ()
1051 {
1052 destroy ();
1053 }
1054} freed_map; // freed objects are moved here to avoid crashes
1055
1056void 1010void
1057object::do_destroy () 1011object::do_destroy ()
1058{ 1012{
1059 if (flag [FLAG_IS_LINKED]) 1013 if (flag [FLAG_IS_LINKED])
1060 remove_link (); 1014 remove_link ();
1144 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed 1098 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed
1145 if (object *pl = visible_to ()) 1099 if (object *pl = visible_to ())
1146 esrv_del_item (pl->contr, count); 1100 esrv_del_item (pl->contr, count);
1147 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed 1101 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed
1148 1102
1149 adjust_weight (env, -total_weight ()); 1103 adjust_weight (env, total_weight (), 0);
1150 1104
1151 object *pl = in_player (); 1105 object *pl = in_player ();
1152 1106
1153 /* we set up values so that it could be inserted into 1107 /* we set up values so that it could be inserted into
1154 * the map, but we don't actually do that - it is up 1108 * the map, but we don't actually do that - it is up
1168 1122
1169 if (pl && pl->is_player ()) 1123 if (pl && pl->is_player ())
1170 { 1124 {
1171 if (expect_false (pl->contr->combat_ob == this)) 1125 if (expect_false (pl->contr->combat_ob == this))
1172 { 1126 {
1173 pl->apply (pl->contr->combat_ob, AP_UNAPPLY); 1127 pl->apply (pl->contr->combat_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1174 pl->contr->combat_ob = 0; 1128 pl->contr->combat_ob = 0;
1175 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob); 1129 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob);
1176 } 1130 }
1177 1131
1178 if (expect_false (pl->contr->ranged_ob == this)) 1132 if (expect_false (pl->contr->ranged_ob == this))
1179 { 1133 {
1180 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY); 1134 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1181 pl->contr->ranged_ob = 0; 1135 pl->contr->ranged_ob = 0;
1182 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob); 1136 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob);
1183 } 1137 }
1184 1138
1185 pl->contr->queue_stats_update (); 1139 pl->contr->queue_stats_update ();
1225 1179
1226 above = 0; 1180 above = 0;
1227 below = 0; 1181 below = 0;
1228 1182
1229 ms.invalidate (); 1183 ms.invalidate ();
1230
1231 if (map->in_memory == MAP_SAVING)
1232 return;
1233 1184
1234 int check_walk_off = !flag [FLAG_NO_APPLY]; 1185 int check_walk_off = !flag [FLAG_NO_APPLY];
1235 1186
1236 if (object *pl = ms.player ()) 1187 if (object *pl = ms.player ())
1237 { 1188 {
1372{ 1323{
1373 op->remove (); 1324 op->remove ();
1374 1325
1375 if (m == &freed_map)//D TODO: remove soon 1326 if (m == &freed_map)//D TODO: remove soon
1376 {//D 1327 {//D
1377 LOG (llevError | logBacktrace, "tries to insret object on freed objects map: %s", op->debug_desc ());//D 1328 LOG (llevError | logBacktrace, "tries to insert object on freed objects map: %s", op->debug_desc ());//D
1378 }//D 1329 }//D
1379 1330
1380 /* Ideally, the caller figures this out. However, it complicates a lot 1331 /* Ideally, the caller figures this out. However, it complicates a lot
1381 * of areas of callers (eg, anything that uses find_free_spot would now 1332 * of areas of callers (eg, anything that uses find_free_spot would now
1382 * need extra work 1333 * need extra work
1655 1606
1656 nr = min (nr, nrof); 1607 nr = min (nr, nrof);
1657 1608
1658 if (nrof > nr) 1609 if (nrof > nr)
1659 { 1610 {
1611 sint64 oweight = total_weight ();
1612
1660 nrof -= nr; 1613 nrof -= nr;
1661 adjust_weight (env, -weight * max (1, nr)); // carrying == 0
1662 1614
1663 if (object *pl = visible_to ()) 1615 if (object *pl = visible_to ())
1664 esrv_update_item (UPD_NROF, pl, this); 1616 esrv_update_item (UPD_NROF, pl, this);
1617
1618 adjust_weight (env, oweight, total_weight ());
1665 1619
1666 return true; 1620 return true;
1667 } 1621 }
1668 else 1622 else
1669 { 1623 {
1744 if (op->nrof) 1698 if (op->nrof)
1745 for (object *tmp = inv; tmp; tmp = tmp->below) 1699 for (object *tmp = inv; tmp; tmp = tmp->below)
1746 if (object::can_merge (tmp, op)) 1700 if (object::can_merge (tmp, op))
1747 { 1701 {
1748 /* return the original object and remove inserted object 1702 /* return the original object and remove inserted object
1749 (client needs the original object) */ 1703 (client prefers the original object) */
1704
1705 // carring must be 0 for mergable objects
1706 sint64 oweight = tmp->weight * tmp->nrof;
1707
1750 tmp->nrof += op->nrof; 1708 tmp->nrof += op->nrof;
1751 1709
1752 if (object *pl = tmp->visible_to ()) 1710 if (object *pl = tmp->visible_to ())
1753 esrv_update_item (UPD_NROF, pl, tmp); 1711 esrv_update_item (UPD_NROF, pl, tmp);
1754 1712
1755 adjust_weight (this, op->total_weight ()); 1713 adjust_weight (this, oweight, tmp->weight * tmp->nrof);
1756 1714
1757 op->destroy (); 1715 op->destroy ();
1758 op = tmp; 1716 op = tmp;
1759 goto inserted; 1717 goto inserted;
1760 } 1718 }
1776 op->flag [FLAG_REMOVED] = 0; 1734 op->flag [FLAG_REMOVED] = 0;
1777 1735
1778 if (object *pl = op->visible_to ()) 1736 if (object *pl = op->visible_to ())
1779 esrv_send_item (pl, op); 1737 esrv_send_item (pl, op);
1780 1738
1781 adjust_weight (this, op->total_weight ()); 1739 adjust_weight (this, 0, op->total_weight ());
1782 1740
1783inserted: 1741inserted:
1784 /* reset the light list and los of the players on the map */ 1742 /* reset the light list and los of the players on the map */
1785 if (op->glow_radius && is_on_map ()) 1743 if (op->glow_radius && is_on_map ())
1786 { 1744 {
1884 1842
1885 /* Basically same logic as above, except now for actual apply. */ 1843 /* Basically same logic as above, except now for actual apply. */
1886 if ((!op->move_type && tmp->move_on & MOVE_WALK) || 1844 if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1887 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) 1845 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1888 { 1846 {
1889 if (tmp->type == EXIT && (flags & INS_NO_AUTO_EXIT)) //TODO: temporary, fix exits instead 1847 if ((flags & INS_NO_AUTO_EXIT)
1848 && (tmp->type == EXIT || tmp->type == TELEPORTER
1849 || tmp->type == HOLE || tmp->type == TRAPDOOR)) //TODO: temporary, fix exits instead
1890 continue; 1850 continue;
1891 1851
1892 move_apply (tmp, op, originator); 1852 move_apply (tmp, op, originator);
1893 1853
1894 if (op->destroyed ()) 1854 if (op->destroyed ())
2048 */ 2008 */
2049int 2009int
2050find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop) 2010find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
2051{ 2011{
2052 int altern[SIZEOFFREE]; 2012 int altern[SIZEOFFREE];
2053 int index = 0, flag; 2013 int index = 0;
2054 2014
2055 for (int i = start; i < stop; i++) 2015 for (int i = start; i < stop; i++)
2056 { 2016 {
2057 mapxy pos (m, x, y); pos.move (i); 2017 mapxy pos (m, x, y); pos.move (i);
2058 2018
2170 * there is capable of. 2130 * there is capable of.
2171 */ 2131 */
2172int 2132int
2173find_dir (maptile *m, int x, int y, object *exclude) 2133find_dir (maptile *m, int x, int y, object *exclude)
2174{ 2134{
2175 int max = SIZEOFFREE, mflags; 2135 int max = SIZEOFFREE;
2176 MoveType move_type; 2136 MoveType move_type;
2177 2137
2178 if (exclude && exclude->head_ () != exclude) 2138 if (exclude && exclude->head_ () != exclude)
2179 { 2139 {
2180 exclude = exclude->head; 2140 exclude = exclude->head;
2431 return /*who->flag [FLAG_WIZ]|| */ 2391 return /*who->flag [FLAG_WIZ]|| */
2432 (item->weight > 0 && !item->flag [FLAG_NO_PICK] && 2392 (item->weight > 0 && !item->flag [FLAG_NO_PICK] &&
2433 !item->flag [FLAG_ALIVE] && !item->invisible && (who->is_player () || item->weight < who->weight / 3)); 2393 !item->flag [FLAG_ALIVE] && !item->invisible && (who->is_player () || item->weight < who->weight / 3));
2434} 2394}
2435 2395
2396//-GPL
2397
2436/* 2398/*
2437 * create clone from object to another 2399 * create clone from object to another
2438 */ 2400 */
2439object * 2401object *
2440object::deep_clone () 2402object::deep_clone ()
2470 return tmp; 2432 return tmp;
2471 2433
2472 return 0; 2434 return 0;
2473} 2435}
2474 2436
2437/* Zero the key_values on op, decrementing the shared-string
2438 * refcounts and freeing the links.
2439 */
2440void
2441key_values::clear ()
2442{
2443 for (key_value *kvp = first; kvp; )
2444 {
2445 key_value *next = kvp->next;
2446 delete kvp;
2447 kvp = next;
2448 }
2449
2450 first = 0;
2451}
2452
2475shstr_tmp 2453shstr_tmp
2476object::kv_get (shstr_tmp key) const 2454key_values::get (shstr_tmp key) const
2477{ 2455{
2478 for (key_value *kv = key_values; kv; kv = kv->next) 2456 for (key_value *kv = first; kv; kv = kv->next)
2479 if (kv->key == key) 2457 if (kv->key == key)
2480 return kv->value; 2458 return kv->value;
2481 2459
2482 return shstr (); 2460 return shstr ();
2483} 2461}
2484 2462
2485void 2463void
2464key_values::add (shstr_tmp key, shstr_tmp value)
2465{
2466 key_value *kv = new key_value;
2467
2468 kv->next = first;
2469 kv->key = key;
2470 kv->value = value;
2471
2472 first = kv;
2473}
2474
2475void
2486object::kv_set (shstr_tmp key, shstr_tmp value) 2476key_values::set (shstr_tmp key, shstr_tmp value)
2487{ 2477{
2488 for (key_value *kv = key_values; kv; kv = kv->next) 2478 for (key_value *kv = first; kv; kv = kv->next)
2489 if (kv->key == key) 2479 if (kv->key == key)
2490 { 2480 {
2491 kv->value = value; 2481 kv->value = value;
2492 return; 2482 return;
2493 } 2483 }
2494 2484
2495 key_value *kv = new key_value; 2485 add (key, value);
2496
2497 kv->next = key_values;
2498 kv->key = key;
2499 kv->value = value;
2500
2501 key_values = kv;
2502} 2486}
2503 2487
2504void 2488void
2505object::kv_del (shstr_tmp key) 2489key_values::del (shstr_tmp key)
2506{ 2490{
2507 for (key_value **kvp = &key_values; *kvp; kvp = &(*kvp)->next) 2491 for (key_value **kvp = &first; *kvp; kvp = &(*kvp)->next)
2508 if ((*kvp)->key == key) 2492 if ((*kvp)->key == key)
2509 { 2493 {
2510 key_value *kv = *kvp; 2494 key_value *kv = *kvp;
2511 *kvp = (*kvp)->next; 2495 *kvp = (*kvp)->next;
2512 delete kv; 2496 delete kv;
2513 return; 2497 return;
2514 } 2498 }
2499}
2500
2501void
2502key_values::reverse ()
2503{
2504 key_value *prev = 0;
2505 key_value *head = first;
2506
2507 while (head)
2508 {
2509 key_value *node = head;
2510 head = head->next;
2511 node->next = prev;
2512 prev = node;
2513 }
2514
2515 first = prev;
2516}
2517
2518key_values &
2519key_values::operator =(const key_values &kv)
2520{
2521 clear ();
2522
2523 for (key_value *kvp = kv.first; kvp; kvp = kvp->next)
2524 add (kvp->key, kvp->value);
2525
2526 reverse ();
2515} 2527}
2516 2528
2517object::depth_iterator::depth_iterator (object *container) 2529object::depth_iterator::depth_iterator (object *container)
2518: iterator_base (container) 2530: iterator_base (container)
2519{ 2531{
2602object::region () const 2614object::region () const
2603{ 2615{
2604 return map ? map->region (x, y) 2616 return map ? map->region (x, y)
2605 : region::default_region (); 2617 : region::default_region ();
2606} 2618}
2619
2620//+GPL
2607 2621
2608void 2622void
2609object::open_container (object *new_container) 2623object::open_container (object *new_container)
2610{ 2624{
2611 if (container == new_container) 2625 if (container == new_container)
2669 } 2683 }
2670// else if (!old_container->env && contr && contr->ns) 2684// else if (!old_container->env && contr && contr->ns)
2671// contr->ns->floorbox_reset (); 2685// contr->ns->floorbox_reset ();
2672} 2686}
2673 2687
2688//-GPL
2689
2690// prefetch some flat area around the player
2691static void
2692prefetch_surrounding_area (object *op, maptile *map, int range)
2693{
2694 for (maprect *rect = map->split_to_tiles (mapwalk_buf,
2695 op->x - range , op->y - range ,
2696 op->x + range + 1, op->y + range + 1);
2697 rect->m;
2698 ++rect)
2699 {
2700 rect->m->touch ();
2701 rect->m->activate ();
2702 }
2703}
2704
2705// prefetch a generous area around the player, also up and down
2706void
2707object::prefetch_surrounding_maps ()
2708{
2709 prefetch_surrounding_area (this, map, 40);
2710
2711 if (maptile *m = map->tile_available (TILE_DOWN))
2712 prefetch_surrounding_area (this, m, 20);
2713
2714 if (maptile *m = map->tile_available (TILE_UP))
2715 prefetch_surrounding_area (this, m, 20);
2716}
2717
2718//+GPL
2719
2674object * 2720object *
2675object::force_find (shstr_tmp name) 2721object::force_find (shstr_tmp name)
2676{ 2722{
2677 /* cycle through his inventory to look for the MARK we want to 2723 /* cycle through his inventory to look for the MARK we want to
2678 * place 2724 * place
2682 return splay (tmp); 2728 return splay (tmp);
2683 2729
2684 return 0; 2730 return 0;
2685} 2731}
2686 2732
2687//-GPL
2688
2689void 2733void
2690object::force_set_timer (int duration) 2734object::force_set_timer (int duration)
2691{ 2735{
2692 this->duration = 1; 2736 this->duration = 1;
2693 this->speed_left = -1.f; 2737 this->speed_left = -1.f;
2699object::force_add (shstr_tmp name, int duration) 2743object::force_add (shstr_tmp name, int duration)
2700{ 2744{
2701 if (object *force = force_find (name)) 2745 if (object *force = force_find (name))
2702 force->destroy (); 2746 force->destroy ();
2703 2747
2704 object *force = get_archetype (FORCE_NAME); 2748 object *force = archetype::get (FORCE_NAME);
2705 2749
2706 force->slaying = name; 2750 force->slaying = name;
2707 force->force_set_timer (duration); 2751 force->force_set_timer (duration);
2708 force->flag [FLAG_APPLIED] = true; 2752 force->flag [FLAG_APPLIED] = true;
2709 2753
2793 return contr->mark; 2837 return contr->mark;
2794 else 2838 else
2795 return 0; 2839 return 0;
2796} 2840}
2797 2841
2842// put marked object first in the inventory
2843// this is used by identify-like spells so players can influence
2844// the order a bit.
2845void
2846object::splay_marked ()
2847{
2848 if (object *marked = mark ())
2849 splay (marked);
2850}
2851

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines