--- deliantra/server/common/map.C 2007/05/28 21:21:40 1.106 +++ deliantra/server/common/map.C 2007/07/12 18:28:09 1.111 @@ -1,23 +1,22 @@ /* - * This file is part of Crossfire TRT, the Multiplayer Online Role Playing Game. + * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. * * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team * Copyright (©) 2001-2003,2007 Mark Wedel & Crossfire Development Team * Copyright (©) 1992,2007 Frank Tore Johansen * - * Crossfire TRT is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. + * Crossfire TRT is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * The authors can be reached via e-mail to */ @@ -278,9 +277,9 @@ return m1->at (sx, sy).move_block; } - for (tmp = ob->arch; tmp; tmp = tmp->more) + for (tmp = ob->arch; tmp; tmp = (archetype *)tmp->more) { - flag = get_map_flags (m, &m1, x + tmp->clone.x, y + tmp->clone.y, &sx, &sy); + flag = get_map_flags (m, &m1, x + tmp->x, y + tmp->y, &sx, &sy); if (flag & P_OUT_OF_MAP) return P_OUT_OF_MAP; @@ -358,16 +357,28 @@ return; for (mapspace *ms = spaces + size (); ms-- > spaces; ) - for (object *op = ms->bot; op; op = op->above) - { - /* already multipart - don't do anything more */ - if (op->head_ () == op && !op->more && op->arch->more) - { - op->remove (); - op->expand_tail (); - insert (op, op->x, op->y, 0, INS_NO_MERGE | INS_ABOVE_FLOOR_ONLY | INS_NO_WALK_ON); - } - } + { + object *op = ms->bot; + while (op) + { + /* already multipart - don't do anything more */ + if (op->head_ () == op && !op->more && op->arch->more) + { + op->remove (); + op->expand_tail (); + + // FIXME: INS_ON_TOP is just a workaround for the pentagram vs. + // multi-tile monster bug, where INS_ABOVE_FLOOR_ONLY put the monsters + // below the pentagrams... hopefully INS_ON_TOP doesn't break anything + insert (op, op->x, op->y, 0, INS_NO_MERGE | INS_ON_TOP | INS_NO_WALK_ON); + + op = ms->bot; // we are mutating the mapspace too much with INS_ON_TOP + // so we have to reset the iteration through the mapspace + } + else + op = op->above; + } + } } /* @@ -716,6 +727,7 @@ case KW_per_player: thawer.get (per_player); break; case KW_per_party: thawer.get (per_party); break; + case KW_no_reset: thawer.get (no_reset); break; case KW_region: default_region = region::find (thawer.get_str ()); break; case KW_shopitems: shopitems = parse_shop_string (thawer.get_str ()); break; @@ -802,6 +814,7 @@ MAP_OUT (reset_time); MAP_OUT (reset_timeout); MAP_OUT (fixed_resettime); + MAP_OUT (no_reset); MAP_OUT (difficulty); if (default_region) MAP_OUT2 (region, default_region->name); @@ -924,6 +937,74 @@ clear (); } +/* decay and destroy perishable items in a map */ +void +maptile::do_decay_objects () +{ + if (!spaces) + return; + + for (mapspace *ms = spaces + size (); ms-- > spaces; ) + for (object *above, *op = ms->bot; op; op = above) + { + above = op->above; + + bool destroy = 0; + + // do not decay anything above unique floor tiles (yet :) + if (QUERY_FLAG (op, FLAG_IS_FLOOR) && QUERY_FLAG (op, FLAG_UNIQUE)) + break; + + if (QUERY_FLAG (op, FLAG_IS_FLOOR) + || QUERY_FLAG (op, FLAG_OBJ_ORIGINAL) + || QUERY_FLAG (op, FLAG_OBJ_SAVE_ON_OVL) + || QUERY_FLAG (op, FLAG_UNIQUE) + || QUERY_FLAG (op, FLAG_OVERLAY_FLOOR) + || QUERY_FLAG (op, FLAG_UNPAID) + || op->is_alive ()) + ; // do not decay + else if (op->is_weapon ()) + { + op->stats.dam--; + if (op->stats.dam < 0) + destroy = 1; + } + else if (op->is_armor ()) + { + op->stats.ac--; + if (op->stats.ac < 0) + destroy = 1; + } + else if (op->type == FOOD) + { + op->stats.food -= rndm (5, 20); + if (op->stats.food < 0) + destroy = 1; + } + else + { + int mat = op->materials; + + if (mat & M_PAPER + || mat & M_LEATHER + || mat & M_WOOD + || mat & M_ORGANIC + || mat & M_CLOTH + || mat & M_LIQUID + || (mat & M_IRON && rndm (1, 5) == 1) + || (mat & M_GLASS && rndm (1, 2) == 1) + || ((mat & M_STONE || mat & M_ADAMANT) && rndm (1, 10) == 1) + || ((mat & M_SOFT_METAL || mat & M_BONE) && rndm (1, 3) == 1) + || (mat & M_ICE && temp > 32)) + destroy = 1; + } + + /* adjust overall chance below */ + if (destroy && rndm (0, 1)) + op->destroy (); + } +} + /* * Updates every button on the map (by calling update_button() for them). */ @@ -979,7 +1060,7 @@ total_exp += op->stats.exp; if (archetype *at = type_to_archetype (GENERATE_TYPE (op))) - total_exp += at->clone.stats.exp * 8; + total_exp += at->stats.exp * 8; monster_cnt++; }