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.327 by root, Fri Apr 16 02:32:25 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 {
488 if (carrying != sum)//D 503 if (carrying != sum && carrying)//D
489 LOG (llevDebug, "updating weight 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
494 if (object *pl = visible_to ()) 509 if (object *pl = visible_to ())
653object::instantiate () 668object::instantiate ()
654{ 669{
655 if (!uuid.seq) // HACK 670 if (!uuid.seq) // HACK
656 uuid = UUID::gen (); 671 uuid = UUID::gen ();
657 672
658 // 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
659 if (flag [FLAG_RANDOM_SPEED] && speed) 674 if (flag [FLAG_RANDOM_SPEED] && speed)
660 speed_left = - speed - rndm (); // TODO animation 675 speed_left = - speed - rndm (); // TODO animation
661 else 676 else
662 speed_left = -1.; 677 speed_left = -1.;
663 678
1144 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
1145 if (object *pl = visible_to ()) 1160 if (object *pl = visible_to ())
1146 esrv_del_item (pl->contr, count); 1161 esrv_del_item (pl->contr, count);
1147 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
1148 1163
1149 adjust_weight (env, -total_weight ()); 1164 adjust_weight (env, total_weight (), 0);
1150 1165
1151 object *pl = in_player (); 1166 object *pl = in_player ();
1152 1167
1153 /* we set up values so that it could be inserted into 1168 /* we set up values so that it could be inserted into
1154 * 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
1168 1183
1169 if (pl && pl->is_player ()) 1184 if (pl && pl->is_player ())
1170 { 1185 {
1171 if (expect_false (pl->contr->combat_ob == this)) 1186 if (expect_false (pl->contr->combat_ob == this))
1172 { 1187 {
1173 pl->apply (pl->contr->combat_ob, AP_UNAPPLY); 1188 pl->apply (pl->contr->combat_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1174 pl->contr->combat_ob = 0; 1189 pl->contr->combat_ob = 0;
1175 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob); 1190 if (pl->contr->ranged_ob) pl->apply (pl->contr->ranged_ob);
1176 } 1191 }
1177 1192
1178 if (expect_false (pl->contr->ranged_ob == this)) 1193 if (expect_false (pl->contr->ranged_ob == this))
1179 { 1194 {
1180 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY); 1195 pl->apply (pl->contr->ranged_ob, AP_UNAPPLY | AP_IGNORE_CURSE);
1181 pl->contr->ranged_ob = 0; 1196 pl->contr->ranged_ob = 0;
1182 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob); 1197 if (pl->contr->combat_ob) pl->apply (pl->contr->combat_ob);
1183 } 1198 }
1184 1199
1185 pl->contr->queue_stats_update (); 1200 pl->contr->queue_stats_update ();
1572 */ 1587 */
1573 1588
1574 /* 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 */
1575 if (!(flag & INS_NO_WALK_ON) && op->is_head ()) 1590 if (!(flag & INS_NO_WALK_ON) && op->is_head ())
1576 { 1591 {
1577 if (check_move_on (op, originator)) 1592 if (check_move_on (op, originator, flag))
1578 return 0; 1593 return 0;
1579 1594
1580 /* 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
1581 * walk on's. 1596 * walk on's.
1582 */ 1597 */
1583 for (object *tmp = op->more; tmp; tmp = tmp->more) 1598 for (object *tmp = op->more; tmp; tmp = tmp->more)
1584 if (check_move_on (tmp, originator)) 1599 if (check_move_on (tmp, originator, flag))
1585 return 0; 1600 return 0;
1586 } 1601 }
1587 1602
1588 return op; 1603 return op;
1589} 1604}
1655 1670
1656 nr = min (nr, nrof); 1671 nr = min (nr, nrof);
1657 1672
1658 if (nrof > nr) 1673 if (nrof > nr)
1659 { 1674 {
1675 sint64 oweight = total_weight ();
1676
1660 nrof -= nr; 1677 nrof -= nr;
1661 adjust_weight (env, -weight * max (1, nr)); // carrying == 0
1662 1678
1663 if (object *pl = visible_to ()) 1679 if (object *pl = visible_to ())
1664 esrv_update_item (UPD_NROF, pl, this); 1680 esrv_update_item (UPD_NROF, pl, this);
1681
1682 adjust_weight (env, oweight, total_weight ());
1665 1683
1666 return true; 1684 return true;
1667 } 1685 }
1668 else 1686 else
1669 { 1687 {
1744 if (op->nrof) 1762 if (op->nrof)
1745 for (object *tmp = inv; tmp; tmp = tmp->below) 1763 for (object *tmp = inv; tmp; tmp = tmp->below)
1746 if (object::can_merge (tmp, op)) 1764 if (object::can_merge (tmp, op))
1747 { 1765 {
1748 /* return the original object and remove inserted object 1766 /* return the original object and remove inserted object
1749 (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
1750 tmp->nrof += op->nrof; 1772 tmp->nrof += op->nrof;
1751 1773
1752 if (object *pl = tmp->visible_to ()) 1774 if (object *pl = tmp->visible_to ())
1753 esrv_update_item (UPD_NROF, pl, tmp); 1775 esrv_update_item (UPD_NROF, pl, tmp);
1754 1776
1755 adjust_weight (this, op->total_weight ()); 1777 adjust_weight (this, oweight, tmp->weight * tmp->nrof);
1756 1778
1757 op->destroy (); 1779 op->destroy ();
1758 op = tmp; 1780 op = tmp;
1759 goto inserted; 1781 goto inserted;
1760 } 1782 }
1776 op->flag [FLAG_REMOVED] = 0; 1798 op->flag [FLAG_REMOVED] = 0;
1777 1799
1778 if (object *pl = op->visible_to ()) 1800 if (object *pl = op->visible_to ())
1779 esrv_send_item (pl, op); 1801 esrv_send_item (pl, op);
1780 1802
1781 adjust_weight (this, op->total_weight ()); 1803 adjust_weight (this, 0, op->total_weight ());
1782 1804
1783inserted: 1805inserted:
1784 /* 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 */
1785 if (op->glow_radius && is_on_map ()) 1807 if (op->glow_radius && is_on_map ())
1786 { 1808 {
1815 * 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
1816 * 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
1817 * on top. 1839 * on top.
1818 */ 1840 */
1819int 1841int
1820check_move_on (object *op, object *originator) 1842check_move_on (object *op, object *originator, int flags)
1821{ 1843{
1822 if (op->flag [FLAG_NO_APPLY]) 1844 if (op->flag [FLAG_NO_APPLY])
1823 return 0; 1845 return 0;
1824 1846
1825 object *tmp; 1847 object *tmp;
1884 1906
1885 /* Basically same logic as above, except now for actual apply. */ 1907 /* Basically same logic as above, except now for actual apply. */
1886 if ((!op->move_type && tmp->move_on & MOVE_WALK) || 1908 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)) 1909 ((op->move_type & tmp->move_on) && (op->move_type & ~tmp->move_on & ~tmp->move_block) == 0))
1888 { 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
1889 move_apply (tmp, op, originator); 1916 move_apply (tmp, op, originator);
1890 1917
1891 if (op->destroyed ()) 1918 if (op->destroyed ())
1892 return 1; 1919 return 1;
1893 1920
2218{ 2245{
2219 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);
2220} 2247}
2221 2248
2222/* 2249/*
2223 * 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
2224 * an object which has subtracted the x and y coordinates of another 2251 * for running into direct [dx, dy].
2225 * object, needs to travel toward it. 2252 * (the opposite of crossfire's find_dir_2!)
2226 */ 2253 */
2227int 2254int
2228find_dir_2 (int x, int y) 2255find_dir_2 (int x, int y)
2229{ 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
2230 int q; 2300 int q;
2231 2301
2232 if (y) 2302 if (y)
2233 q = x * 100 / y; 2303 q = 128 * x / y;
2234 else if (x) 2304 else if (x)
2235 q = -300 * x; 2305 q = -512 * x; // to make it > 309
2236 else 2306 else
2237 return 0; 2307 return 0;
2238 2308
2239 if (y > 0) 2309 if (y > 0)
2240 { 2310 {
2241 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
2242 return 3; 2316 return 3;
2243 if (q < -41) 2317 }
2244 return 2; 2318 else
2245 if (q < 41) 2319 {
2246 return 1; 2320 if (q < -309) return 3;
2247 if (q < 242) 2321 if (q < -52) return 2;
2248 return 8; 2322 if (q < 52) return 1;
2323 if (q < 309) return 8;
2324
2249 return 7; 2325 return 7;
2250 } 2326 }
2251 2327#endif
2252 if (q < -242)
2253 return 7;
2254 if (q < -41)
2255 return 6;
2256 if (q < 41)
2257 return 5;
2258 if (q < 242)
2259 return 4;
2260
2261 return 3;
2262} 2328}
2263 2329
2264/* 2330/*
2265 * dirdiff(dir1, dir2) returns how many 45-degrees differences there is 2331 * dirdiff(dir1, dir2) returns how many 45-degrees differences there is
2266 * between two directions (which are expected to be absolute (see absdir()) 2332 * between two directions (which are expected to be absolute (see absdir())
2267 */ 2333 */
2268int 2334int
2269dirdiff (int dir1, int dir2) 2335dirdiff (int dir1, int dir2)
2270{ 2336{
2271 int d;
2272
2273 d = abs (dir1 - dir2); 2337 int d = abs (dir1 - dir2);
2274 if (d > 4)
2275 d = 8 - d;
2276 2338
2277 return d; 2339 return d > 4 ? 8 - d : d;
2278} 2340}
2279 2341
2280/* peterm: 2342/* peterm:
2281 * 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.
2282 * Basically, this is a table of directions, and what directions 2344 * Basically, this is a table of directions, and what directions
2755 return contr->mark; 2817 return contr->mark;
2756 else 2818 else
2757 return 0; 2819 return 0;
2758} 2820}
2759 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