--- deliantra/server/common/object.C 2007/04/21 17:34:22 1.139 +++ deliantra/server/common/object.C 2007/06/13 21:09:39 1.161 @@ -1,25 +1,25 @@ /* - * CrossFire, A Multiplayer game for X-windows + * This file is part of Crossfire TRT, the Multiplayer Online Role Playing Game. * - * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team - * Copyright (C) 2001 Mark Wedel & Crossfire Development Team - * Copyright (C) 1992 Frank Tore Johansen + * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team + * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team + * Copyright (©) 1992,2007 Frank Tore Johansen * - * This program 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 2 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 this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * The authors can be reached via e-mail at + * 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 + * + * The authors can be reached via e-mail to */ /* Eneq(@csd.uu.se): Added weight-modifiers in environment of objects. @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -326,10 +327,11 @@ long sum; object *inv; - for (sum = 0, inv = op->inv; inv != NULL; inv = inv->below) + for (sum = 0, inv = op->inv; inv; inv = inv->below) { if (inv->inv) sum_weight (inv); + sum += inv->carrying + inv->weight * (inv->nrof ? inv->nrof : 1); } @@ -450,6 +452,72 @@ this->owner = owner; } +int +object::slottype () const +{ + if (type == SKILL) + { + if (IS_COMBAT_SKILL (subtype)) return slot_combat; + if (IS_RANGED_SKILL (subtype)) return slot_ranged; + } + else + { + if (slot [body_combat].info) return slot_combat; + if (slot [body_range ].info) return slot_ranged; + } + + return slot_none; +} + +bool +object::change_weapon (object *ob) +{ + if (current_weapon == ob) + return true; + + if (chosen_skill) + chosen_skill->flag [FLAG_APPLIED] = false; + + current_weapon = ob; + chosen_skill = !ob || ob->type == SKILL ? ob : find_skill_by_name (this, ob->skill); + + if (chosen_skill) + chosen_skill->flag [FLAG_APPLIED] = true; + + update_stats (); + + if (ob) + { + // now check wether any body locations became invalid, in which case + // we cannot apply the weapon at the moment. + for (int i = 0; i < NUM_BODY_LOCATIONS; ++i) + if (slot[i].used < 0) + { + current_weapon = chosen_skill = 0; + update_stats (); + + new_draw_info_format (NDI_UNIQUE, 0, this, + "You try to balance all your items at once, " + "but the %s is just too much for your body. " + "[You need to unapply some items first.]", &ob->name); + return false; + } + + //new_draw_info_format (NDI_UNIQUE, 0, this, "You switch to your %s.", &ob->name); + } + else + ;//new_draw_info_format (NDI_UNIQUE, 0, this, "You unwield your weapons."); + + if (ob && !ob->flag [FLAG_APPLIED] && ob->type != SPELL) + { + LOG (llevError | logBacktrace, "%s changed to unapplied weapon %s", + &name, ob->debug_desc ()); + return false; + } + + return true; +} + /* Zero the key_values on op, decrementing the shared-string * refcounts and freeing the links. */ @@ -539,7 +607,8 @@ * values for the body_used info, so when items are created * for it, they can be properly equipped. */ - memcpy (body_used, body_info, sizeof (body_used)); + for (int i = NUM_BODY_LOCATIONS; i--; ) + slot[i].used = slot[i].info; attachable::instantiate (); } @@ -837,15 +906,7 @@ remove_button_link (this); if (flag [FLAG_FRIENDLY]) - { - remove_friendly_object (this); - - if (type == GOLEM - && owner - && owner->type == PLAYER - && owner->contr->ranges[range_golem] == this) - owner->contr->ranges[range_golem] = 0; - } + remove_friendly_object (this); if (!flag [FLAG_REMOVED]) remove (); @@ -1057,11 +1118,6 @@ LOG (llevError, "BUG: remove_ob(): name %s, destroyed leaving object\n", tmp->debug_desc ()); } - /* Eneq(@csd.uu.se): Fixed this to skip tmp->above=tmp */ - //TODO: why is this horrible hacka fix? get rid of this code=bug! (schmorp) - if (tmp->above == tmp) - tmp->above = 0; - last = tmp; } @@ -1122,7 +1178,7 @@ object *prev = this; - for (archetype *at = arch->more; at; at = at->more) + for (archetype *at = (archetype *)arch->more; at; at = (archetype *)at->more) { object *op = arch_to_object (at); @@ -1146,8 +1202,8 @@ { for (object *tmp = op->head_ (); tmp; tmp = tmp->more) { - tmp->x = x + tmp->arch->clone.x; - tmp->y = y + tmp->arch->clone.y; + tmp->x = x + tmp->arch->x; + tmp->y = y + tmp->arch->y; } return insert_ob_in_map (op, m, originator, flag); @@ -1178,7 +1234,7 @@ { assert (!op->flag [FLAG_FREED]); - object *tmp, *top, *floor = NULL; + object *top, *floor = NULL; op->remove (); @@ -1204,15 +1260,8 @@ } if (object *more = op->more) - { - if (!insert_ob_in_map (more, m, originator, flag)) - { - if (!op->head) - LOG (llevError, "BUG: insert_ob_in_map(): inserting op->more killed op\n"); - - return 0; - } - } + if (!insert_ob_in_map (more, m, originator, flag)) + return 0; CLEAR_FLAG (op, FLAG_REMOVED); @@ -1229,7 +1278,7 @@ /* this has to be done after we translate the coordinates. */ if (op->nrof && !(flag & INS_NO_MERGE)) - for (tmp = ms.bot; tmp; tmp = tmp->above) + for (object *tmp = ms.bot; tmp; tmp = tmp->above) if (object::can_merge (op, tmp)) { op->nrof += tmp->nrof; @@ -1408,7 +1457,7 @@ */ /* if this is not the head or flag has been passed, don't check walk on status */ - if (!(flag & INS_NO_WALK_ON) && !op->head) + if (!(flag & INS_NO_WALK_ON) && op->head_ () == op) { if (check_move_on (op, originator)) return 0; @@ -1416,7 +1465,7 @@ /* If we are a multi part object, lets work our way through the check * walk on's. */ - for (tmp = op->more; tmp != NULL; tmp = tmp->more) + for (object *tmp = op->more; tmp; tmp = tmp->more) if (check_move_on (tmp, originator)) return 0; } @@ -1436,7 +1485,7 @@ /* first search for itself and remove any old instances */ for (tmp = op->ms ().bot; tmp; tmp = tmp->above) - if (!strcmp (tmp->arch->name, arch_string)) /* same archetype */ + if (!strcmp (tmp->arch->archname, arch_string)) /* same archetype */ tmp->destroy (); tmp1 = arch_to_object (archetype::find (arch_string)); @@ -1607,9 +1656,9 @@ return op; } - if (where->head) + if (where->head_ () != where) { - LOG (llevDebug, "Warning: Tried to insert object into wrong part of multipart object.\n"); + LOG (llevError | logBacktrace, "Warning: Tried to insert object into wrong part of multipart object.\n"); where = where->head; } @@ -1950,19 +1999,6 @@ } /* - * set_cheat(object) sets the cheat flag (WAS_WIZ) in the object and in - * all it's inventory (recursively). - * If checksums are used, a player will get set_cheat called for - * him/her-self and all object carried by a call to this function. - */ -void -set_cheat (object *op) -{ - SET_FLAG (op, FLAG_WAS_WIZ); - flag_inv (op, FLAG_WAS_WIZ); -} - -/* * find_free_spot(object, map, x, y, start, stop) will search for * a spot at the given map and coordinates which will be able to contain * the given object. start and stop specifies how many squares @@ -2087,7 +2123,7 @@ MoveType blocked, move_type; - if (exclude && exclude->head) + if (exclude && exclude->head_ () != exclude) { exclude = exclude->head; move_type = exclude->move_type; @@ -2120,7 +2156,7 @@ { for (tmp = ms.bot; tmp; tmp = tmp->above) if ((tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER) - && (tmp != exclude || (tmp->head && tmp->head != exclude))) + && (tmp != exclude || (tmp->head_ () != tmp && tmp->head_ () != exclude))) break; if (tmp) @@ -2325,17 +2361,15 @@ object * object_create_clone (object *asrc) { - object *dst = 0, *tmp, *src, *part, *prev, *item; + object *dst = 0, *tmp, *src, *prev, *item; if (!asrc) return 0; - src = asrc; - if (src->head) - src = src->head; + src = asrc->head_ (); prev = 0; - for (part = src; part; part = part->more) + for (object *part = src; part; part = part->more) { tmp = part->clone (); tmp->x -= src->x; @@ -2458,7 +2492,7 @@ * it, we save the empty value so that when we load, * we get this value back again. */ - if (get_ob_key_link (&op->arch->clone, canonical_key)) + if (get_ob_key_link (op->arch, canonical_key)) field->value = 0; else { @@ -2593,15 +2627,10 @@ const char * object::debug_desc () const { - static char info[256 * 4]; - return debug_desc (info); -} + static char info[3][256 * 4]; + static int info_idx; -const char * -object::debug_desc2 () const -{ - static char info[256 * 4]; - return debug_desc (info); + return debug_desc (info [++info_idx % 3]); } struct region *