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.325 by root, Wed Apr 14 21:36:31 2010 UTC vs.
Revision 1.343 by root, Sat Apr 23 04:56:46 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));
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 */
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)
451 - weight_adjust_for (op, op->carrying - weight);
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 {
503 if (carrying != sum && carrying)//D
504 LOG (llevDebug, "updating carrying got %ld, expected %ld (%s)\n",
505 (long long)sum, (long long)carrying, debug_desc ());
506
488 carrying = sum; 507 carrying = sum;
489 508
490 if (object *pl = visible_to ()) 509 if (object *pl = visible_to ())
491 if (pl != this) // player is handled lazily 510 if (pl != this) // player is handled lazily
492 esrv_update_item (UPD_WEIGHT, pl, this); 511 esrv_update_item (UPD_WEIGHT, pl, this);
649object::instantiate () 668object::instantiate ()
650{ 669{
651 if (!uuid.seq) // HACK 670 if (!uuid.seq) // HACK
652 uuid = UUID::gen (); 671 uuid = UUID::gen ();
653 672
654 // TODO: unclean state changes, should nt be done in copy_to AND instantiate 673 // TODO: unclean state changes, should not be done in copy_to AND instantiate
655 if (flag [FLAG_RANDOM_SPEED] && speed) 674 if (flag [FLAG_RANDOM_SPEED] && speed)
656 speed_left = - speed - rndm (); // TODO animation 675 speed_left = - speed - rndm (); // TODO animation
657 else 676 else
658 speed_left = -1.; 677 speed_left = -1.;
659 678
1031} 1050}
1032 1051
1033static struct freed_map : maptile 1052static struct freed_map : maptile
1034{ 1053{
1035 freed_map () 1054 freed_map ()
1055 : maptile (3, 3)
1036 { 1056 {
1037 path = "<freed objects map>"; 1057 path = "<freed objects map>";
1038 name = "/internal/freed_objects_map"; 1058 name = "/internal/freed_objects_map";
1039 width = 3;
1040 height = 3;
1041 no_drop = 1; 1059 no_drop = 1;
1042 no_reset = 1; 1060 no_reset = 1;
1043 1061
1044 alloc ();
1045 in_memory = MAP_ACTIVE; 1062 in_memory = MAP_ACTIVE;
1046 } 1063 }
1047 1064
1048 ~freed_map () 1065 ~freed_map ()
1049 { 1066 {
1142 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed 1159 flag [FLAG_REMOVED] = false; // hack around the issue of visible_to checking flag_removed
1143 if (object *pl = visible_to ()) 1160 if (object *pl = visible_to ())
1144 esrv_del_item (pl->contr, count); 1161 esrv_del_item (pl->contr, count);
1145 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed 1162 flag [FLAG_REMOVED] = true; // hack around the issue of visible_to checking flag_removed
1146 1163
1147 adjust_weight (env, -total_weight ()); 1164 adjust_weight (env, total_weight (), 0);
1148 1165
1149 object *pl = in_player (); 1166 object *pl = in_player ();
1150 1167
1151 /* we set up values so that it could be inserted into 1168 /* we set up values so that it could be inserted into
1152 * the map, but we don't actually do that - it is up 1169 * the map, but we don't actually do that - it is up
1166 1183
1167 if (pl && pl->is_player ()) 1184 if (pl && pl->is_player ())
1168 { 1185 {
1169 if (expect_false (pl->contr->combat_ob == this)) 1186 if (expect_false (pl->contr->combat_ob == this))
1170 { 1187 {
1171 pl->apply (pl->contr->combat_ob, AP_UNAPPLY); 1188 pl->apply (pl->contr->combat_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1172 pl->contr->combat_ob = 0; 1189 pl->contr->combat_ob = 0;
1173 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob); 1190 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob);
1174 } 1191 }
1175 1192
1176 if (expect_false (pl->contr->ranged_ob == this)) 1193 if (expect_false (pl->contr->ranged_ob == this))
1177 { 1194 {
1178 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY); 1195 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1179 pl->contr->ranged_ob = 0; 1196 pl->contr->ranged_ob = 0;
1180 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob); 1197 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob);
1181 } 1198 }
1182 1199
1183 pl->contr->queue_stats_update (); 1200 pl->contr->queue_stats_update ();
1570 */ 1587 */
1571 1588
1572 /* if this is not the head or flag has been passed, don't check walk on status */ 1589 /* if this is not the head or flag has been passed, don't check walk on status */
1573 if (!(flag & INS_NO_WALK_ON) && op->is_head ()) 1590 if (!(flag & INS_NO_WALK_ON) && op->is_head ())
1574 { 1591 {
1575 if (check_move_on (op, originator)) 1592 if (check_move_on (op, originator, flag))
1576 return 0; 1593 return 0;
1577 1594
1578 /* If we are a multi part object, lets work our way through the check 1595 /* If we are a multi part object, let's work our way through the check
1579 * walk on's. 1596 * walk on's.
1580 */ 1597 */
1581 for (object *tmp = op->more; tmp; tmp = tmp->more) 1598 for (object *tmp = op->more; tmp; tmp = tmp->more)
1582 if (check_move_on (tmp, originator)) 1599 if (check_move_on (tmp, originator, flag))
1583 return 0; 1600 return 0;
1584 } 1601 }
1585 1602
1586 return op; 1603 return op;
1587} 1604}
1653 1670
1654 nr = min (nr, nrof); 1671 nr = min (nr, nrof);
1655 1672
1656 if (nrof > nr) 1673 if (nrof > nr)
1657 { 1674 {
1675 sint64 oweight = total_weight ();
1676
1658 nrof -= nr; 1677 nrof -= nr;
1659 adjust_weight (env, -weight * max (1, nr)); // carrying == 0
1660 1678
1661 if (object *pl = visible_to ()) 1679 if (object *pl = visible_to ())
1662 esrv_update_item (UPD_NROF, pl, this); 1680 esrv_update_item (UPD_NROF, pl, this);
1681
1682 adjust_weight (env, oweight, total_weight ());
1663 1683
1664 return true; 1684 return true;
1665 } 1685 }
1666 else 1686 else
1667 { 1687 {
1742 if (op->nrof) 1762 if (op->nrof)
1743 for (object *tmp = inv; tmp; tmp = tmp->below) 1763 for (object *tmp = inv; tmp; tmp = tmp->below)
1744 if (object::can_merge (tmp, op)) 1764 if (object::can_merge (tmp, op))
1745 { 1765 {
1746 /* return the original object and remove inserted object 1766 /* return the original object and remove inserted object
1747 (client needs the original object) */ 1767 (client prefers the original object) */
1768
1769 // carring must be 0 for mergable objects
1770 sint64 oweight = tmp->weight * tmp->nrof;
1771
1748 tmp->nrof += op->nrof; 1772 tmp->nrof += op->nrof;
1749 1773
1750 if (object *pl = tmp->visible_to ()) 1774 if (object *pl = tmp->visible_to ())
1751 esrv_update_item (UPD_NROF, pl, tmp); 1775 esrv_update_item (UPD_NROF, pl, tmp);
1752 1776
1753 adjust_weight (this, op->total_weight ()); 1777 adjust_weight (this, oweight, tmp->weight * tmp->nrof);
1754 1778
1755 op->destroy (); 1779 op->destroy ();
1756 op = tmp; 1780 op = tmp;
1757 goto inserted; 1781 goto inserted;
1758 } 1782 }
1774 op->flag [FLAG_REMOVED] = 0; 1798 op->flag [FLAG_REMOVED] = 0;
1775 1799
1776 if (object *pl = op->visible_to ()) 1800 if (object *pl = op->visible_to ())
1777 esrv_send_item (pl, op); 1801 esrv_send_item (pl, op);
1778 1802
1779 adjust_weight (this, op->total_weight ()); 1803 adjust_weight (this, 0, op->total_weight ());
1780 1804
1781inserted: 1805inserted:
1782 /* reset the light list and los of the players on the map */ 1806 /* reset the light list and los of the players on the map */
1783 if (op->glow_radius && is_on_map ()) 1807 if (op->glow_radius && is_on_map ())
1784 { 1808 {
1813 * MSW 2001-07-08: Check all objects on space, not just those below 1837 * MSW 2001-07-08: Check all objects on space, not just those below
1814 * object being inserted. insert_ob_in_map may not put new objects 1838 * object being inserted. insert_ob_in_map may not put new objects
1815 * on top. 1839 * on top.
1816 */ 1840 */
1817int 1841int
1818check_move_on (object *op, object *originator) 1842check_move_on (object *op, object *originator, int flags)
1819{ 1843{
1820 if (op->flag [FLAG_NO_APPLY]) 1844 if (op->flag [FLAG_NO_APPLY])
1821 return 0; 1845 return 0;
1822 1846
1823 object *tmp; 1847 object *tmp;
1882 1906
1883 /* Basically same logic as above, except now for actual apply. */ 1907 /* Basically same logic as above, except now for actual apply. */
1884 if ((!op->move_type && tmp->move_on & MOVE_WALK) || 1908 if ((!op->move_type && tmp->move_on & MOVE_WALK) ||
1885 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0)) 1909 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1886 { 1910 {
1911 if ((flags & INS_NO_AUTO_EXIT)
1912 && (tmp->type == EXIT || tmp->type == TELEPORTER
1913 || tmp->type == HOLE || tmp->type == TRAPDOOR)) //TODO: temporary, fix exits instead
1914 continue;
1915
1887 move_apply (tmp, op, originator); 1916 move_apply (tmp, op, originator);
1888 1917
1889 if (op->destroyed ()) 1918 if (op->destroyed ())
1890 return 1; 1919 return 1;
1891 1920
2216{ 2245{
2217 return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y); 2246 return (ob1->x - ob2->x) * (ob1->x - ob2->x) + (ob1->y - ob2->y) * (ob1->y - ob2->y);
2218} 2247}
2219 2248
2220/* 2249/*
2221 * find_dir_2(delta-x,delta-y) will return a direction in which 2250 * find_dir_2(delta-x,delta-y) will return a direction value
2222 * an object which has subtracted the x and y coordinates of another 2251 * for running into direct [dx, dy].
2223 * object, needs to travel toward it. 2252 * (the opposite of crossfire's find_dir_2!)
2224 */ 2253 */
2225int 2254int
2226find_dir_2 (int x, int y) 2255find_dir_2 (int x, int y)
2227{ 2256{
2257#if 1 // new algorithm
2258 // this works by putting x, y into 16 sectors, which
2259 // are not equal sized, but are a better approximation
2260 // then the old algorithm, and then using a mapping
2261 // table to map it into a direction value.
2262 // basically, it maps these comparisons to each bit
2263 // bit #3: x < 0
2264 // bit #2: y < 0
2265 // bit #1: x > y
2266 // bit #0: x > 2y
2267
2268 static const uint8 dir[16] = {
2269 4, 5, 4, 3,
2270 2, 1, 2, 3,
2271 6, 5, 6, 7,
2272 8, 1, 8, 7,
2273 };
2274 int sector = 0;
2275
2276 // this is a bit ugly, but more likely to result in branchless code
2277 sector |= x < 0 ? 8 : 0;
2278 x = x < 0 ? -x : x; // abs
2279
2280 sector |= y < 0 ? 4 : 0;
2281 y = y < 0 ? -y : y; // abs
2282
2283 if (x > y)
2284 {
2285 sector |= 2;
2286
2287 if (x > y * 2)
2288 sector |= 1;
2289 }
2290 else
2291 {
2292 if (y > x * 2)
2293 sector |= 1;
2294 else if (!y)
2295 return 0; // x == 0 here
2296 }
2297
2298 return dir [sector];
2299#else // old algorithm
2228 int q; 2300 int q;
2229 2301
2230 if (y) 2302 if (y)
2231 q = x * 100 / y; 2303 q = 128 * x / y;
2232 else if (x) 2304 else if (x)
2233 q = -300 * x; 2305 q = -512 * x; // to make it > 309
2234 else 2306 else
2235 return 0; 2307 return 0;
2236 2308
2237 if (y > 0) 2309 if (y > 0)
2238 { 2310 {
2239 if (q < -242) 2311 if (q < -309) return 7;
2312 if (q < -52) return 6;
2313 if (q < 52) return 5;
2314 if (q < 309) return 4;
2315
2240 return 3; 2316 return 3;
2241 if (q < -41) 2317 }
2242 return 2; 2318 else
2243 if (q < 41) 2319 {
2244 return 1; 2320 if (q < -309) return 3;
2245 if (q < 242) 2321 if (q < -52) return 2;
2246 return 8; 2322 if (q < 52) return 1;
2323 if (q < 309) return 8;
2324
2247 return 7; 2325 return 7;
2248 } 2326 }
2249 2327#endif
2250 if (q < -242)
2251 return 7;
2252 if (q < -41)
2253 return 6;
2254 if (q < 41)
2255 return 5;
2256 if (q < 242)
2257 return 4;
2258
2259 return 3;
2260} 2328}
2261 2329
2262/* 2330/*
2263 * dirdiff(dir1, dir2) returns how many 45-degrees differences there is 2331 * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2264 * between two directions (which are expected to be absolute (see absdir()) 2332 * between two directions (which are expected to be absolute (see absdir())
2265 */ 2333 */
2266int 2334int
2267dirdiff (int dir1, int dir2) 2335dirdiff (int dir1, int dir2)
2268{ 2336{
2269 int d;
2270
2271 d = abs (dir1 - dir2); 2337 int d = abs (dir1 - dir2);
2272 if (d > 4)
2273 d = 8 - d;
2274 2338
2275 return d; 2339 return d > 4 ? 8 - d : d;
2276} 2340}
2277 2341
2278/* peterm: 2342/* peterm:
2279 * do LOS stuff for ball lightning. Go after the closest VISIBLE monster. 2343 * do LOS stuff for ball lightning. Go after the closest VISIBLE monster.
2280 * Basically, this is a table of directions, and what directions 2344 * Basically, this is a table of directions, and what directions
2753 return contr->mark; 2817 return contr->mark;
2754 else 2818 else
2755 return 0; 2819 return 0;
2756} 2820}
2757 2821
2822// put marked object first in the inventory
2823// this is used by identify-like spells so players can influence
2824// the order a bit.
2825void
2826object::splay_marked ()
2827{
2828 if (object *marked = mark ())
2829 splay (marked);
2830}
2831

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines