--- deliantra/server/common/object.C 2007/03/15 14:23:02 1.136 +++ deliantra/server/common/object.C 2007/05/12 16:06:42 1.147 @@ -1,5 +1,5 @@ /* - * CrossFire, A Multiplayer game for X-windows + * CrossFire, A Multiplayer game * * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team * Copyright (C) 2001 Mark Wedel & Crossfire Development Team @@ -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,13 +452,54 @@ this->owner = owner; } +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 your applied items all at once, but the %s is too much. " + "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."); + + return true; +} + /* Zero the key_values on op, decrementing the shared-string * refcounts and freeing the links. */ static void free_key_values (object *op) { - for (key_value *i = op->key_values; i != 0;) + for (key_value *i = op->key_values; i; ) { key_value *next = i->next; delete i; @@ -467,40 +510,24 @@ op->key_values = 0; } -/* - * copy_to first frees everything allocated by the dst object, - * and then copies the contents of itself into the second - * object, allocating what needs to be allocated. Basically, any - * data that is malloc'd needs to be re-malloc/copied. Otherwise, - * if the first object is freed, the pointers in the new object - * will point at garbage. - */ -void -object::copy_to (object *dst) +object & +object::operator =(const object &src) { - bool is_freed = QUERY_FLAG (dst, FLAG_FREED); - bool is_removed = QUERY_FLAG (dst, FLAG_REMOVED); - - *(object_copy *)dst = *this; + bool is_freed = flag [FLAG_FREED]; + bool is_removed = flag [FLAG_REMOVED]; - if (is_freed) - SET_FLAG (dst, FLAG_FREED); + *(object_copy *)this = src; - if (is_removed) - SET_FLAG (dst, FLAG_REMOVED); - - if (speed < 0) - dst->speed_left = speed_left - rndm (); + flag [FLAG_FREED] = is_freed; + flag [FLAG_REMOVED] = is_removed; /* Copy over key_values, if any. */ - if (key_values) + if (src.key_values) { key_value *tail = 0; - key_value *i; + key_values = 0; - dst->key_values = 0; - - for (i = key_values; i; i = i->next) + for (key_value *i = src.key_values; i; i = i->next) { key_value *new_link = new key_value; @@ -509,9 +536,9 @@ new_link->value = i->value; /* Try and be clever here, too. */ - if (!dst->key_values) + if (!key_values) { - dst->key_values = new_link; + key_values = new_link; tail = new_link; } else @@ -521,6 +548,23 @@ } } } +} + +/* + * copy_to first frees everything allocated by the dst object, + * and then copies the contents of itself into the second + * object, allocating what needs to be allocated. Basically, any + * data that is malloc'd needs to be re-malloc/copied. Otherwise, + * if the first object is freed, the pointers in the new object + * will point at garbage. + */ +void +object::copy_to (object *dst) +{ + *dst = *this; + + if (speed < 0) + dst->speed_left = speed_left - rndm (); dst->set_speed (dst->speed); } @@ -538,7 +582,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 (); } @@ -836,15 +881,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 (); @@ -1113,6 +1150,29 @@ return 0; } +void +object::expand_tail () +{ + if (more) + return; + + object *prev = this; + + for (archetype *at = arch->more; at; at = at->more) + { + object *op = arch_to_object (at); + + op->name = name; + op->name_pl = name_pl; + op->title = title; + + op->head = this; + prev->more = op; + + prev = op; + } +} + /* * same as insert_ob_in_map except it handles separate coordinates and does a clean * job preparing multi-part monsters. @@ -1152,31 +1212,23 @@ object * insert_ob_in_map (object *op, maptile *m, object *originator, int flag) { - object *tmp, *top, *floor = NULL; - - if (QUERY_FLAG (op, FLAG_FREED)) - { - LOG (llevError, "Trying to insert freed object!\n"); - return NULL; - } + assert (!op->flag [FLAG_FREED]); - if (!QUERY_FLAG (op, FLAG_REMOVED)) - LOG (llevError, "Trying to insert already inserted object %s\n", op->debug_desc ()); + object *tmp, *top, *floor = NULL; op->remove (); - if (!m) - { - char *dump = dump_object (op); - LOG (llevError, "Trying to insert in null-map!\n%s\n", dump); - free (dump); - return op; - } +#if 0 + if (!m->active != !op->active) + if (m->active) + op->activate_recursive (); + else + op->deactivate_recursive (); +#endif if (out_of_map (m, op->x, op->y)) { - char *dump = dump_object (op); - LOG (llevError, "Trying to insert object outside the map.\n%s\n", dump); + LOG (llevError, "Trying to insert object outside the map.\n%s\n", op->debug_desc ()); #ifdef MANY_CORES /* Better to catch this here, as otherwise the next use of this object * is likely to cause a crash. Better to find out where it is getting @@ -1184,7 +1236,6 @@ */ abort (); #endif - free (dump); return op; } @@ -1431,11 +1482,10 @@ insert_ob_in_map (tmp1, op->map, op, 0); } -// XXX: function not returning object* object * object::insert_at (object *where, object *originator, int flags) { - where->map->insert (this, where->x, where->y, originator, flags); + return where->map->insert (this, where->x, where->y, originator, flags); } /* @@ -1485,7 +1535,6 @@ * * Return value: 'op' if something is left, NULL if the amount reached 0 */ - object * decrease_ob_nr (object *op, uint32 i) { @@ -1570,7 +1619,6 @@ * add_weight(object, weight) adds the specified weight to an object, * and also updates how much the environment(s) is/are carrying. */ - void add_weight (object *op, signed long weight) { @@ -1612,7 +1660,6 @@ * The function returns now pointer to inserted item, and return value can * be != op, if items are merged. -Tero */ - object * object::insert (object *op) { @@ -2582,15 +2629,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 *