--- deliantra/server/common/object.C 2007/05/03 10:39:46 1.144 +++ deliantra/server/common/object.C 2007/05/18 01:01:01 1.156 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -451,15 +452,70 @@ this->owner = owner; } -void -object::set_weapon (object *ob) +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; + return true; + + if (chosen_skill) + chosen_skill->flag [FLAG_APPLIED] = false; current_weapon = ob; - new_draw_info_format (NDI_UNIQUE, 0, this, "You switch to your %s.", &ob->name); + 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 @@ -551,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 (); } @@ -1182,7 +1239,7 @@ { assert (!op->flag [FLAG_FREED]); - object *tmp, *top, *floor = NULL; + object *top, *floor = NULL; op->remove (); @@ -1208,15 +1265,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); @@ -1233,7 +1283,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; @@ -1412,7 +1462,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; @@ -1420,7 +1470,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; } @@ -1611,9 +1661,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; } @@ -1954,19 +2004,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 @@ -2091,7 +2128,7 @@ MoveType blocked, move_type; - if (exclude && exclude->head) + if (exclude && exclude->head_ () != exclude) { exclude = exclude->head; move_type = exclude->move_type; @@ -2124,7 +2161,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) @@ -2329,17 +2366,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;