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.354 by root, Mon Oct 29 23:55:52 2012 UTC vs.
Revision 1.364 by root, Sat Sep 16 22:17:42 2017 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,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 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
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] = { 76const char *wall_suffix[16] = {
77 "0", 77 "0",
78 "1_3", 78 "1_3",
79 "1_4", 79 "1_4",
80 "2_1_2", 80 "2_1_2",
81 "1_2", 81 "1_2",
82 "2_2_4", 82 "2_2_4",
83 "2_2_1", 83 "2_2_1",
84 "3_1", 84 "3_1",
85 "1_1", 85 "1_1",
86 "2_2_3", 86 "2_2_3",
87 "2_2_2", 87 "2_2_2",
88 "3_3", 88 "3_3",
89 "2_1_1", 89 "2_1_1",
90 "3_4", 90 "3_4",
91 "3_2", 91 "3_2",
92 "4" 92 "4"
93}; 93};
94 94
95static void 95static void
96write_uuid (uval64 skip, bool sync) 96write_uuid (uval64 skip, bool sync)
97{ 97{
235static bool 235static bool
236compare_ob_value_lists_one (const object *wants, const object *has) 236compare_ob_value_lists_one (const object *wants, const object *has)
237{ 237{
238 /* n-squared behaviour (see kv.get), but I'm hoping both 238 /* n-squared behaviour (see kv.get), but I'm hoping both
239 * 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
240 * different structure or at least keep the lists sorted... 240 * different structure or at least keep the lists sorted...
241 */ 241 */
242 242
243 /* For each field in wants, */ 243 /* For each field in wants, */
244 for (key_value *kv = wants->kv.first; kv; kv = kv->next) 244 for (key_value *kv = wants->kv.first; kv; kv = kv->next)
245 if (has->kv.get (kv->key) != kv->value) 245 if (has->kv.get (kv->key) != kv->value)
351 /* inventory ok - still need to check rest of this object to see 351 /* inventory ok - still need to check rest of this object to see
352 * if it is valid. 352 * if it is valid.
353 */ 353 */
354 } 354 }
355 355
356 /* Don't merge objects that are applied. With the new 'body' code, 356 /* Don't merge objects that are applied. With the new 'body' code,
357 * it is possible for most any character to have more than one of 357 * it is possible for most any character to have more than one of
358 * some items equipped, and we don't want those to merge. 358 * some items equipped, and we don't want those to merge.
359 */ 359 */
360 if (ob1->flag [FLAG_APPLIED] || ob2->flag [FLAG_APPLIED]) 360 if (ob1->flag [FLAG_APPLIED] || ob2->flag [FLAG_APPLIED])
361 return 0; 361 return 0;
362 362
363 /* Note sure why the following is the case - either the object has to 363 /* Not sure why the following is the case - either the object has to
364 * be animated or have a very low speed. Is this an attempted monster 364 * be animated or have a very low speed. Is this an attempted monster
365 * check? 365 * check?
366 */ 366 */
367 if (!ob1->flag [FLAG_ANIMATE] && ob1->has_active_speed ()) 367 if (!ob1->flag [FLAG_ANIMATE] && ob1->has_active_speed ())
368 return 0; 368 return 0;
369 369
446 446
447 return 0; 447 return 0;
448} 448}
449 449
450// adjust weight per container type ("of holding") 450// adjust weight per container type ("of holding")
451static uint32 451static weight_t
452weight_adjust_for (object *op, uint32 weight) 452weight_adjust_for (object *op, weight_t weight)
453{ 453{
454 return op->type == CONTAINER 454 if (op->type == CONTAINER)
455 ? weight - weight * op->stats.Str / 100 455 weight -= weight * op->stats.Str / 100;
456 : weight; 456
457 return weight;
457} 458}
458 459
459/* 460/*
460 * subtracts, then adds, the specified weight to an object, 461 * subtracts, then adds, the specified weight to an object,
461 * and also updates how much the environment(s) is/are carrying. 462 * and also updates how much the environment(s) is/are carrying.
462 */ 463 */
463static void 464static void
464adjust_weight (object *op, sint32 sub, sint32 add) 465adjust_weight (object *op, weight_t sub, weight_t add)
465{ 466{
466 while (op) 467 while (op)
467 { 468 {
468 sint32 ocarrying = op->carrying; 469 weight_t carrying = (weight_t)op->carrying
470 - weight_adjust_for (op, sub)
471 + weight_adjust_for (op, add);
469 472
470 op->carrying -= weight_adjust_for (op, sub); 473 sub = op->carrying;
471 op->carrying += weight_adjust_for (op, add); 474 op->carrying = carrying;
475 add = op->carrying;
472 476
473 if (object *pl = op->visible_to ()) 477 if (object *pl = op->visible_to ())
474 if (pl != op) // player is handled lazily 478 if (pl != op) // player is handled lazily
475 esrv_update_item (UPD_WEIGHT, pl, op); 479 esrv_update_item (UPD_WEIGHT, pl, op);
476 480
477 sub = ocarrying;
478 add = op->carrying;
479
480 op = op->env; 481 op = op->env;
481 } 482 }
482} 483}
483 484
484/* 485/*
487 * containers are carrying, and sums it up. 488 * containers are carrying, and sums it up.
488 */ 489 */
489void 490void
490object::update_weight () 491object::update_weight ()
491{ 492{
492 sint32 sum = 0; 493 weight_t sum = 0;
493 494
494 for (object *op = inv; op; op = op->below) 495 for (object *op = inv; op; op = op->below)
495 { 496 {
496 op->update_weight (); 497 op->update_weight ();
497 498
635 speed_left = -1.; 636 speed_left = -1.;
636 637
637 /* copy the body_info to the body_used - this is only really 638 /* copy the body_info to the body_used - this is only really
638 * need for monsters, but doesn't hurt to do it for everything. 639 * need for monsters, but doesn't hurt to do it for everything.
639 * by doing so, when a monster is created, it has good starting 640 * by doing so, when a monster is created, it has good starting
640 * values for the body_used info, so when items are created 641 * values for the body_used info, so when items are created
641 * for it, they can be properly equipped. 642 * for it, they can be properly equipped.
642 */ 643 */
643 for (int i = NUM_BODY_LOCATIONS; i--; ) 644 for (int i = NUM_BODY_LOCATIONS; i--; )
644 slot[i].used = slot[i].info; 645 slot[i].used = slot[i].info;
645 646
752 || (op->flag [FLAG_DAMNED] && !(m.flags_ & P_NO_CLERIC)) 753 || (op->flag [FLAG_DAMNED] && !(m.flags_ & P_NO_CLERIC))
753 || (m.move_on | op->move_on ) != m.move_on 754 || (m.move_on | op->move_on ) != m.move_on
754 || (m.move_off | op->move_off ) != m.move_off 755 || (m.move_off | op->move_off ) != m.move_off
755 || (m.move_slow | op->move_slow) != m.move_slow 756 || (m.move_slow | op->move_slow) != m.move_slow
756 /* This isn't perfect, but I don't expect a lot of objects to 757 /* This isn't perfect, but I don't expect a lot of objects to
757 * have move_allow right now. 758 * have move_allow right now.
758 */ 759 */
759 || ((m.move_block | op->move_block) & ~op->move_allow) != m.move_block 760 || ((m.move_block | op->move_block) & ~op->move_allow) != m.move_block
760 m.invalidate (); 761 m.invalidate ();
761#else 762#else
762 // the above is not strong enough a test to skip updating. los maybe? TODO (schmorp) 763 // the above is not strong enough a test to skip updating. los maybe? TODO (schmorp)
842 op->activate_recursive (); 843 op->activate_recursive ();
843} 844}
844 845
845/* This function removes object 'op' from the list of active 846/* This function removes object 'op' from the list of active
846 * objects. 847 * objects.
847 * This should only be used for style maps or other such 848 * This should only be used for style maps or other such
848 * reference maps where you don't want an object that isn't 849 * reference maps where you don't want an object that isn't
849 * in play chewing up cpu time getting processed. 850 * in play chewing up cpu time getting processed.
850 * The reverse of this is to call update_ob_speed, which 851 * The reverse of this is to call update_ob_speed, which
851 * will do the right thing based on the speed of the object. 852 * will do the right thing based on the speed of the object.
852 */ 853 */
1087 flag [FLAG_REMOVED] = true; 1088 flag [FLAG_REMOVED] = true;
1088 1089
1089 if (more) 1090 if (more)
1090 more->remove (); 1091 more->remove ();
1091 1092
1092 /* 1093 /*
1093 * In this case, the object to be removed is in someones 1094 * In this case, the object to be removed is in someones
1094 * inventory. 1095 * inventory.
1095 */ 1096 */
1096 if (env) 1097 if (env)
1097 { 1098 {
1402 * We've already dealt with merging if appropriate. 1403 * We've already dealt with merging if appropriate.
1403 * Generally, we want to put the new object on top. But if 1404 * Generally, we want to put the new object on top. But if
1404 * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last 1405 * flag contains INS_ABOVE_FLOOR_ONLY, once we find the last
1405 * floor, we want to insert above that and no further. 1406 * floor, we want to insert above that and no further.
1406 * Also, if there are spell objects on this space, we stop processing 1407 * Also, if there are spell objects on this space, we stop processing
1407 * once we get to them. This reduces the need to traverse over all of 1408 * once we get to them. This reduces the need to traverse over all of
1408 * them when adding another one - this saves quite a bit of cpu time 1409 * them when adding another one - this saves quite a bit of cpu time
1409 * when lots of spells are cast in one area. Currently, it is presumed 1410 * when lots of spells are cast in one area. Currently, it is presumed
1410 * that flying non pickable objects are spell objects. 1411 * that flying non pickable objects are spell objects.
1411 */ 1412 */
1412 for (object *tmp = ms.bot; tmp; tmp = tmp->above) 1413 for (object *tmp = ms.bot; tmp; tmp = tmp->above)
1538 1539
1539 return op; 1540 return op;
1540} 1541}
1541 1542
1542/* this function inserts an object in the map, but if it 1543/* this function inserts an object in the map, but if it
1543 * finds an object of its own type, it'll remove that one first. 1544 * finds an object of its own type, it'll remove that one first.
1544 * op is the object to insert it under: supplies x and the map. 1545 * op is the object to insert it under: supplies x and the map.
1545 */ 1546 */
1546void 1547void
1547replace_insert_ob_in_map (shstr_tmp archname, object *op) 1548replace_insert_ob_in_map (shstr_tmp archname, object *op)
1548{ 1549{
1580 if (!items // testing !items ensures we can drop at least one item 1581 if (!items // testing !items ensures we can drop at least one item
1581 || (items < m->max_items 1582 || (items < m->max_items
1582 && ms.volume () < m->max_volume)) 1583 && ms.volume () < m->max_volume))
1583 return true; 1584 return true;
1584 1585
1585 if (originator && originator->is_player ()) 1586 if (originator)
1586 originator->contr->failmsgf ( 1587 originator->failmsgf (
1587 "No matter how hard you try, you just cannot put the %s here H<Try to remove some items from the floor first.>", 1588 "No matter how hard you try, you just cannot put the %s here! H<Try to remove some items from the floor first.>",
1588 query_name () 1589 query_name ()
1589 ); 1590 );
1590 1591
1591 return false; 1592 return false;
1592} 1593}
1606 1607
1607 nr = min (nr, nrof); 1608 nr = min (nr, nrof);
1608 1609
1609 if (nrof > nr) 1610 if (nrof > nr)
1610 { 1611 {
1611 sint64 oweight = total_weight (); 1612 weight_t oweight = total_weight ();
1612 1613
1613 nrof -= nr; 1614 nrof -= nr;
1614 1615
1615 if (object *pl = visible_to ()) 1616 if (object *pl = visible_to ())
1616 esrv_update_item (UPD_NROF, pl, this); 1617 esrv_update_item (UPD_NROF, pl, this);
1677/* 1678/*
1678 * env->insert (op) 1679 * env->insert (op)
1679 * This function inserts the object op in the linked list 1680 * This function inserts the object op in the linked list
1680 * inside the object environment. 1681 * inside the object environment.
1681 * 1682 *
1682 * The function returns now pointer to inserted item, and return value can 1683 * The function returns now pointer to inserted item, and return value can
1683 * be != op, if items are merged. -Tero 1684 * be != op, if items are merged. -Tero
1684 */ 1685 */
1685object * 1686object *
1686object::insert (object *op) 1687object::insert (object *op)
1687{ 1688{
1700 if (object::can_merge (tmp, op)) 1701 if (object::can_merge (tmp, op))
1701 { 1702 {
1702 /* return the original object and remove inserted object 1703 /* return the original object and remove inserted object
1703 (client prefers the original object) */ 1704 (client prefers the original object) */
1704 1705
1705 // carring must be 0 for mergable objects 1706 // carrying must be 0 for mergable objects
1706 sint64 oweight = tmp->weight * tmp->nrof; 1707 weight_t oweight = weight_t (tmp->weight) * tmp->nrof;
1707 1708
1708 tmp->nrof += op->nrof; 1709 tmp->nrof += op->nrof;
1709 1710
1710 if (object *pl = tmp->visible_to ()) 1711 if (object *pl = tmp->visible_to ())
1711 esrv_update_item (UPD_NROF, pl, tmp); 1712 esrv_update_item (UPD_NROF, pl, tmp);
1712 1713
1713 adjust_weight (this, oweight, tmp->weight * tmp->nrof); 1714 adjust_weight (this, oweight, weight_t (tmp->weight) * tmp->nrof);
1714 1715
1715 op->destroy (); 1716 op->destroy ();
1716 op = tmp; 1717 op = tmp;
1717 goto inserted; 1718 goto inserted;
1718 } 1719 }
1807 */ 1808 */
1808 if ((op->move_type & ~move_on & ~move_block) != 0 && (op->move_type & ~move_slow & ~move_block) != 0) 1809 if ((op->move_type & ~move_on & ~move_block) != 0 && (op->move_type & ~move_slow & ~move_block) != 0)
1809 return 0; 1810 return 0;
1810 1811
1811 /* The objects have to be checked from top to bottom. 1812 /* The objects have to be checked from top to bottom.
1812 * Hence, we first go to the top: 1813 * Hence, we first go to the top:
1813 */ 1814 */
1814 for (object *next, *tmp = ms.top; tmp; tmp = next) 1815 for (object *next, *tmp = ms.top; tmp; tmp = next)
1815 { 1816 {
1816 next = tmp->below; 1817 next = tmp->below;
1817 1818
2001 * inform the caller. However, insert_ob_in_map will update as 2002 * inform the caller. However, insert_ob_in_map will update as
2002 * necessary, so the caller shouldn't need to do any special work. 2003 * necessary, so the caller shouldn't need to do any special work.
2003 * Note - updated to take an object instead of archetype - this is necessary 2004 * Note - updated to take an object instead of archetype - this is necessary
2004 * because arch_blocked (now ob_blocked) needs to know the movement type 2005 * because arch_blocked (now ob_blocked) needs to know the movement type
2005 * to know if the space in question will block the object. We can't use 2006 * to know if the space in question will block the object. We can't use
2006 * the archetype because that isn't correct if the monster has been 2007 * the archetype because that isn't correct if the monster has been
2007 * customized, changed states, etc. 2008 * customized, changed states, etc.
2008 */ 2009 */
2009int 2010int
2010find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop) 2011find_free_spot (const object *ob, maptile *m, int x, int y, int start, int stop)
2011{ 2012{
2034 continue; 2035 continue;
2035 } 2036 }
2036 2037
2037 /* Basically, if we find a wall on a space, we cut down the search size. 2038 /* Basically, if we find a wall on a space, we cut down the search size.
2038 * In this way, we won't return spaces that are on another side of a wall. 2039 * In this way, we won't return spaces that are on another side of a wall.
2039 * This mostly work, but it cuts down the search size in all directions - 2040 * This mostly work, but it cuts down the search size in all directions -
2040 * if the space being examined only has a wall to the north and empty 2041 * if the space being examined only has a wall to the north and empty
2041 * spaces in all the other directions, this will reduce the search space 2042 * spaces in all the other directions, this will reduce the search space
2042 * to only the spaces immediately surrounding the target area, and 2043 * to only the spaces immediately surrounding the target area, and
2043 * won't look 2 spaces south of the target space. 2044 * won't look 2 spaces south of the target space.
2044 */ 2045 */
2074 */ 2075 */
2075int 2076int
2076find_first_free_spot (const object *ob, maptile *m, int x, int y) 2077find_first_free_spot (const object *ob, maptile *m, int x, int y)
2077{ 2078{
2078 for (int i = 0; i < SIZEOFFREE; i++) 2079 for (int i = 0; i < SIZEOFFREE; i++)
2079 if (!ob->blocked (m, x + freearr_x[i], y + freearr_y[i])) 2080 if (!ob->blocked (m, x + DIRX (i), y + DIRY (i)))
2080 return i; 2081 return i;
2081 2082
2082 return -1; 2083 return -1;
2083} 2084}
2084 2085
2095 2096
2096 while (--end) 2097 while (--end)
2097 swap (arr [end], arr [rndm (end + 1)]); 2098 swap (arr [end], arr [rndm (end + 1)]);
2098} 2099}
2099 2100
2100/* new function to make monster searching more efficient, and effective! 2101/* new function to make monster searching more efficient, and effective!
2101 * This basically returns a randomized array (in the passed pointer) of 2102 * This basically returns a randomized array (in the passed pointer) of
2102 * the spaces to find monsters. In this way, it won't always look for 2103 * the spaces to find monsters. In this way, it won't always look for
2103 * monsters to the north first. However, the size of the array passed 2104 * monsters to the north first. However, the size of the array passed
2104 * covers all the spaces, so within that size, all the spaces within 2105 * covers all the spaces, so within that size, all the spaces within
2105 * the 3x3 area will be searched, just not in a predictable order. 2106 * the 3x3 area will be searched, just not in a predictable order.
2349 int mflags; 2350 int mflags;
2350 2351
2351 if (dir < 0) 2352 if (dir < 0)
2352 return 0; /* exit condition: invalid direction */ 2353 return 0; /* exit condition: invalid direction */
2353 2354
2354 dx = x + freearr_x[dir]; 2355 dx = x + DIRX (dir);
2355 dy = y + freearr_y[dir]; 2356 dy = y + DIRY (dir);
2356 2357
2357 mflags = get_map_flags (m, &m, dx, dy, &dx, &dy); 2358 mflags = get_map_flags (m, &m, dx, dy, &dx, &dy);
2358 2359
2359 /* This functional arguably was incorrect before - it was 2360 /* This functional arguably was incorrect before - it was
2360 * checking for P_WALL - that was basically seeing if 2361 * checking for P_WALL - that was basically seeing if
2433 2434
2434 return 0; 2435 return 0;
2435} 2436}
2436 2437
2437/* Zero the key_values on op, decrementing the shared-string 2438/* Zero the key_values on op, decrementing the shared-string
2438 * refcounts and freeing the links. 2439 * refcounts and freeing the links.
2439 */ 2440 */
2440void 2441void
2441key_values::clear () 2442key_values::clear ()
2442{ 2443{
2443 for (key_value *kvp = first; kvp; ) 2444 for (key_value *kvp = first; kvp; )
2718//+GPL 2719//+GPL
2719 2720
2720object * 2721object *
2721object::force_find (shstr_tmp name) 2722object::force_find (shstr_tmp name)
2722{ 2723{
2723 /* cycle through his inventory to look for the MARK we want to 2724 /* cycle through his inventory to look for the MARK we want to
2724 * place 2725 * place
2725 */ 2726 */
2726 for (object *tmp = inv; tmp; tmp = tmp->below) 2727 for (object *tmp = inv; tmp; tmp = tmp->below)
2727 if (tmp->type == FORCE && tmp->slaying == name) 2728 if (tmp->type == FORCE && tmp->slaying == name)
2728 return splay (tmp); 2729 return splay (tmp);
2729 2730

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines