--- deliantra/server/common/living.C 2006/09/12 02:06:19 1.10 +++ deliantra/server/common/living.C 2007/04/29 18:34:57 1.43 @@ -1,25 +1,26 @@ /* - CrossFire, A Multiplayer game for X-windows - - Copyright (C) 2002 Mark Wedel & Crossfire Development Team - Copyright (C) 1992 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. - - 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 crossfire-devel@real-time.com -*/ + * CrossFire, A Multiplayer game + * + * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team + * Copyright (C) 2002 Mark Wedel & Crossfire Development Team + * Copyright (C) 1992 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. + * + * 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 + */ #include #include @@ -160,11 +161,7 @@ #define MAX_EXP_IN_OBJ levels[settings.max_level]/(MAX_EXP_CAT - 1) -#ifndef WIN32 -extern uint64 *levels; -#else extern sint64 *levels; -#endif #define MAX_SAVE_LEVEL 110 @@ -197,53 +194,52 @@ "You're feeling clumsy!", "You feel less healthy", "You suddenly begin to lose your memory!", - "Your face gets distorted!", "Watch out, your mind is going!", - "Your spirit feels drained!" + "Your spirit feels drained!", + "Your face gets distorted!", }; const char *const restore_msg[NUM_STATS] = { "You feel your strength return.", "You feel your agility return.", "You feel your health return.", + "You feel your memory return.", "You feel your wisdom return.", + "You feel your spirits return.", "You feel your charisma return.", - "You feel your memory return.", - "You feel your spirits return." }; const char *const gain_msg[NUM_STATS] = { "You feel stronger.", "You feel more agile.", "You feel healthy.", + "You feel smarter.", "You feel wiser.", + "You feel more potent.", "You seem to look better.", - "You feel smarter.", - "You feel more potent." }; const char *const lose_msg[NUM_STATS] = { "You feel weaker!", "You feel clumsy!", "You feel less healthy!", + "You feel stupid!", "You lose some of your memory!", + "You feel less potent!", "You look ugly!", - "You feel stupid!", - "You feel less potent!" }; const char *const statname[NUM_STATS] = { - "strength", "dexterity", "constitution", "wisdom", "charisma", "intelligence", "power" + "strength", "dexterity", "constitution", "intelligence", "wisdom", "power", "charisma" }; const char *const short_stat_name[NUM_STATS] = { - "Str", "Dex", "Con", "Wis", "Cha", "Int", "Pow" + "Str", "Dex", "Con", "Int", "Wis", "Pow", "Cha" }; /* * sets Str/Dex/con/Wis/Cha/Int/Pow in stats to value, depending on * what attr is (STR to POW). */ - void -set_attr_value (living * stats, int attr, sint8 value) +set_attr_value (living *stats, int attr, sint8 value) { switch (attr) { @@ -275,12 +271,12 @@ * Like set_attr_value(), but instead the value (which can be negative) * is added to the specified stat. */ - void -change_attr_value (living * stats, int attr, sint8 value) +change_attr_value (living *stats, int attr, sint8 value) { if (value == 0) return; + switch (attr) { case STR: @@ -314,25 +310,19 @@ */ sint8 -get_attr_value (const living * stats, int attr) +get_attr_value (const living *stats, int attr) { switch (attr) { - case STR: - return (stats->Str); - case DEX: - return (stats->Dex); - case CON: - return (stats->Con); - case WIS: - return (stats->Wis); - case CHA: - return (stats->Cha); - case INT: - return (stats->Int); - case POW: - return (stats->Pow); + case STR: return stats->Str; + case DEX: return stats->Dex; + case CON: return stats->Con; + case WIS: return stats->Wis; + case CHA: return stats->Cha; + case INT: return stats->Int; + case POW: return stats->Pow; } + return 0; } @@ -342,7 +332,7 @@ */ void -check_stat_bounds (living * stats) +check_stat_bounds (living *stats) { int i, v; @@ -384,9 +374,9 @@ /* remember what object was like before it was changed. note that * refop is a local copy of op only to be used for detecting changes - * found by fix_player. refop is not a real object + * found by update_stats. refop is not a real object */ - object_pod refop = *op; + object_copy refop = *op; if (op->type == PLAYER) { @@ -414,6 +404,7 @@ { nstat = 20 + get_attr_value (&(op->arch->clone.stats), j); } + if (nstat != ostat) { set_attr_value (&(op->contr->orig_stats), j, nstat); @@ -425,12 +416,14 @@ potion_max = 1; } } + /* This section of code ups the characters normal stats also. I am not * sure if this is strictly necessary, being that fix_player probably * recalculates this anyway. */ for (j = 0; j < NUM_STATS; j++) change_attr_value (&(op->stats), j, flag * get_attr_value (&(tmp->stats), j)); + check_stat_bounds (&(op->stats)); } /* end of potion handling code */ } @@ -454,7 +447,7 @@ * to multiple items. if fix_player always has to be called after * change_ability then might as well call it from here */ - fix_player (op); + op->update_stats (); /* Fix player won't add the bows ability to the player, so don't * print out message if this is a bow. @@ -464,21 +457,25 @@ success = 1; DIFF_MSG (flag, "Your hands begin to glow red.", "Your hands stop glowing red."); } + if (QUERY_FLAG (op, FLAG_LIFESAVE) != QUERY_FLAG (&refop, FLAG_LIFESAVE)) { success = 1; DIFF_MSG (flag, "You feel very protected.", "You don't feel protected anymore."); } + if (QUERY_FLAG (op, FLAG_REFL_MISSILE) != QUERY_FLAG (&refop, FLAG_REFL_MISSILE)) { success = 1; DIFF_MSG (flag, "A magic force shimmers around you.", "The magic force fades away."); } + if (QUERY_FLAG (op, FLAG_REFL_SPELL) != QUERY_FLAG (&refop, FLAG_REFL_SPELL)) { success = 1; DIFF_MSG (flag, "You feel more safe now, somehow.", "Suddenly you feel less safe, somehow."); } + /* movement type has changed. We don't care about cases where * user has multiple items giving the same type appled like we * used to - that is more work than what we gain, plus messages @@ -536,11 +533,13 @@ success = 1; DIFF_MSG (flag, "You walk more quietly.", "You walk more noisily."); } + if (QUERY_FLAG (op, FLAG_MAKE_INVIS) != QUERY_FLAG (&refop, FLAG_MAKE_INVIS)) { success = 1; DIFF_MSG (flag, "You become transparent.", "You can see yourself."); } + /* blinded you can tell if more blinded since blinded player has minimal * vision */ @@ -657,7 +656,7 @@ } } - if (tmp->type != EXPERIENCE && !potion_max) + if (!potion_max) { for (j = 0; j < NUM_STATS; j++) { @@ -668,6 +667,7 @@ } } } + return success; } @@ -677,18 +677,18 @@ */ void -drain_stat (object *op) +object::drain_stat () { - drain_specific_stat (op, RANDOM () % NUM_STATS); + drain_specific_stat (rndm (NUM_STATS)); } void -drain_specific_stat (object *op, int deplete_stats) +object::drain_specific_stat (int deplete_stats) { object *tmp; archetype *at; - at = find_archetype (ARCH_DEPLETION); + at = archetype::find (ARCH_DEPLETION); if (!at) { LOG (llevError, "Couldn't find archetype depletion.\n"); @@ -696,73 +696,72 @@ } else { - tmp = present_arch_in_ob (at, op); + tmp = present_arch_in_ob (at, this); + if (!tmp) { tmp = arch_to_object (at); - tmp = insert_ob_in_ob (tmp, op); + tmp = insert_ob_in_ob (tmp, this); SET_FLAG (tmp, FLAG_APPLIED); } } - new_draw_info (NDI_UNIQUE, 0, op, drain_msg[deplete_stats]); + new_draw_info (NDI_UNIQUE, 0, this, drain_msg[deplete_stats]); change_attr_value (&tmp->stats, deplete_stats, -1); - fix_player (op); + update_stats (); } /* * A value of 0 indicates timeout, otherwise change the luck of the object. * via an applied bad_luck object. */ - void -change_luck (object *op, int value) +object::change_luck (int value) { - object *tmp; - archetype *at; - int new_luck; - - at = find_archetype ("luck"); + archetype *at = archetype::find ("luck"); if (!at) LOG (llevError, "Couldn't find archetype luck.\n"); else { - tmp = present_arch_in_ob (at, op); + object *tmp = present_arch_in_ob (at, this); + if (!tmp) { if (!value) return; + tmp = arch_to_object (at); - tmp = insert_ob_in_ob (tmp, op); + tmp = insert_ob_in_ob (tmp, this); SET_FLAG (tmp, FLAG_APPLIED); } + if (value) { /* Limit the luck value of the bad luck object to +/-100. This * (arbitrary) value prevents overflows (both in the bad luck object and * in op itself). */ - new_luck = tmp->stats.luck + value; + int new_luck = tmp->stats.luck + value; + if (new_luck >= -100 && new_luck <= 100) { - op->stats.luck += value; + stats.luck += value; tmp->stats.luck = new_luck; } } else { if (!tmp->stats.luck) - { - return; - } + return; + /* Randomly change the players luck. Basically, we move it * back neutral (if greater>0, subtract, otherwise add) */ - if (RANDOM () % (FABS (tmp->stats.luck)) >= RANDOM () % 30) + if (rndm (abs (tmp->stats.luck)) >= rndm (30)) { int diff = tmp->stats.luck > 0 ? -1 : 1; - op->stats.luck += diff; + stats.luck += diff; tmp->stats.luck += diff; } } @@ -772,47 +771,47 @@ /* * Subtracts stat-bonuses given by the class which the player has chosen. */ - void -remove_statbonus (object *op) +object::remove_statbonus () { - op->stats.Str -= op->arch->clone.stats.Str; - op->stats.Dex -= op->arch->clone.stats.Dex; - op->stats.Con -= op->arch->clone.stats.Con; - op->stats.Wis -= op->arch->clone.stats.Wis; - op->stats.Pow -= op->arch->clone.stats.Pow; - op->stats.Cha -= op->arch->clone.stats.Cha; - op->stats.Int -= op->arch->clone.stats.Int; - op->contr->orig_stats.Str -= op->arch->clone.stats.Str; - op->contr->orig_stats.Dex -= op->arch->clone.stats.Dex; - op->contr->orig_stats.Con -= op->arch->clone.stats.Con; - op->contr->orig_stats.Wis -= op->arch->clone.stats.Wis; - op->contr->orig_stats.Pow -= op->arch->clone.stats.Pow; - op->contr->orig_stats.Cha -= op->arch->clone.stats.Cha; - op->contr->orig_stats.Int -= op->arch->clone.stats.Int; + stats.Str -= arch->clone.stats.Str; + stats.Dex -= arch->clone.stats.Dex; + stats.Con -= arch->clone.stats.Con; + stats.Wis -= arch->clone.stats.Wis; + stats.Pow -= arch->clone.stats.Pow; + stats.Cha -= arch->clone.stats.Cha; + stats.Int -= arch->clone.stats.Int; + + contr->orig_stats.Str -= arch->clone.stats.Str; + contr->orig_stats.Dex -= arch->clone.stats.Dex; + contr->orig_stats.Con -= arch->clone.stats.Con; + contr->orig_stats.Wis -= arch->clone.stats.Wis; + contr->orig_stats.Pow -= arch->clone.stats.Pow; + contr->orig_stats.Cha -= arch->clone.stats.Cha; + contr->orig_stats.Int -= arch->clone.stats.Int; } /* * Adds stat-bonuses given by the class which the player has chosen. */ - void -add_statbonus (object *op) +object::add_statbonus () { - op->stats.Str += op->arch->clone.stats.Str; - op->stats.Dex += op->arch->clone.stats.Dex; - op->stats.Con += op->arch->clone.stats.Con; - op->stats.Wis += op->arch->clone.stats.Wis; - op->stats.Pow += op->arch->clone.stats.Pow; - op->stats.Cha += op->arch->clone.stats.Cha; - op->stats.Int += op->arch->clone.stats.Int; - op->contr->orig_stats.Str += op->arch->clone.stats.Str; - op->contr->orig_stats.Dex += op->arch->clone.stats.Dex; - op->contr->orig_stats.Con += op->arch->clone.stats.Con; - op->contr->orig_stats.Wis += op->arch->clone.stats.Wis; - op->contr->orig_stats.Pow += op->arch->clone.stats.Pow; - op->contr->orig_stats.Cha += op->arch->clone.stats.Cha; - op->contr->orig_stats.Int += op->arch->clone.stats.Int; + stats.Str += arch->clone.stats.Str; + stats.Dex += arch->clone.stats.Dex; + stats.Con += arch->clone.stats.Con; + stats.Wis += arch->clone.stats.Wis; + stats.Pow += arch->clone.stats.Pow; + stats.Cha += arch->clone.stats.Cha; + stats.Int += arch->clone.stats.Int; + + contr->orig_stats.Str += arch->clone.stats.Str; + contr->orig_stats.Dex += arch->clone.stats.Dex; + contr->orig_stats.Con += arch->clone.stats.Con; + contr->orig_stats.Wis += arch->clone.stats.Wis; + contr->orig_stats.Pow += arch->clone.stats.Pow; + contr->orig_stats.Cha += arch->clone.stats.Cha; + contr->orig_stats.Int += arch->clone.stats.Int; } /* @@ -821,14 +820,12 @@ * and players; the "player" in the name is purely an archaic inheritance. * This functions starts from base values (archetype or player object) * and then adjusts them according to what the player has equipped. + * + * July 95 - inserted stuff to handle new skills/exp system - b.t. + * spell system split, grace points now added to system --peterm */ - -/* July 95 - inserted stuff to handle new skills/exp system - b.t. - spell system split, grace points now added to system --peterm - */ - void -fix_player (object *op) +object::update_stats () { int i, j; float f, max = 9, added_speed = 0, bonus_speed = 0, sp_tmp, speed_reduce_from_disease = 1; @@ -836,79 +833,79 @@ int best_wc = 0, best_ac = 0, wc = 0, ac = 0; int prot[NROFATTACKS], vuln[NROFATTACKS], potion_resist[NROFATTACKS]; object *grace_obj = NULL, *mana_obj = NULL, *wc_obj = NULL, *tmp; + float old_speed = speed; /* First task is to clear all the values back to their original values */ - if (op->type == PLAYER) + if (type == PLAYER) { for (i = 0; i < NUM_STATS; i++) - { - set_attr_value (&(op->stats), i, get_attr_value (&(op->contr->orig_stats), i)); - } + set_attr_value (&(stats), i, get_attr_value (&(contr->orig_stats), i)); + if (settings.spell_encumbrance == TRUE) - op->contr->encumbrance = 0; + contr->encumbrance = 0; - op->attacktype = 0; - op->contr->digestion = 0; - op->contr->gen_hp = 0; - op->contr->gen_sp = 0; - op->contr->gen_grace = 0; - op->contr->gen_sp_armour = 10; - op->contr->item_power = 0; + attacktype = 0; + + contr->digestion = 0; + contr->gen_hp = 0; + contr->gen_sp = 0; + contr->gen_grace = 0; + contr->gen_sp_armour = 10; + contr->item_power = 0; /* Don't clobber all the range_ values. range_golem otherwise * gets reset for no good reason, and we don't want to reset * range_magic (what spell is readied). These three below * well get filled in based on what the player has equipped. */ - op->contr->ranges[range_bow] = NULL; - op->contr->ranges[range_misc] = NULL; - op->contr->ranges[range_skill] = NULL; + contr->ranges[range_bow] = 0; + contr->ranges[range_misc] = 0; + contr->ranges[range_skill] = 0; } - memcpy (op->body_used, op->body_info, sizeof (op->body_info)); - op->slaying = 0; + memcpy (body_used, body_info, sizeof (body_info)); + + slaying = 0; - if (!QUERY_FLAG (op, FLAG_WIZ)) + if (!QUERY_FLAG (this, FLAG_WIZ)) { - CLEAR_FLAG (op, FLAG_XRAYS); - CLEAR_FLAG (op, FLAG_MAKE_INVIS); + CLEAR_FLAG (this, FLAG_XRAYS); + CLEAR_FLAG (this, FLAG_MAKE_INVIS); } - CLEAR_FLAG (op, FLAG_LIFESAVE); - CLEAR_FLAG (op, FLAG_STEALTH); - CLEAR_FLAG (op, FLAG_BLIND); - if (!QUERY_FLAG (&op->arch->clone, FLAG_REFL_SPELL)) - CLEAR_FLAG (op, FLAG_REFL_SPELL); - if (!QUERY_FLAG (&op->arch->clone, FLAG_REFL_MISSILE)) - CLEAR_FLAG (op, FLAG_REFL_MISSILE); - if (!QUERY_FLAG (&op->arch->clone, FLAG_UNDEAD)) - CLEAR_FLAG (op, FLAG_UNDEAD); - if (!QUERY_FLAG (&op->arch->clone, FLAG_SEE_IN_DARK)) - CLEAR_FLAG (op, FLAG_SEE_IN_DARK); - - op->path_attuned = op->arch->clone.path_attuned; - op->path_repelled = op->arch->clone.path_repelled; - op->path_denied = op->arch->clone.path_denied; - op->glow_radius = op->arch->clone.glow_radius; - op->move_type = op->arch->clone.move_type; - op->chosen_skill = NULL; + CLEAR_FLAG (this, FLAG_LIFESAVE); + CLEAR_FLAG (this, FLAG_STEALTH); + CLEAR_FLAG (this, FLAG_BLIND); + + if (!QUERY_FLAG (&arch->clone, FLAG_REFL_SPELL )) CLEAR_FLAG (this, FLAG_REFL_SPELL); + if (!QUERY_FLAG (&arch->clone, FLAG_REFL_MISSILE)) CLEAR_FLAG (this, FLAG_REFL_MISSILE); + if (!QUERY_FLAG (&arch->clone, FLAG_UNDEAD )) CLEAR_FLAG (this, FLAG_UNDEAD); + if (!QUERY_FLAG (&arch->clone, FLAG_SEE_IN_DARK )) CLEAR_FLAG (this, FLAG_SEE_IN_DARK); + + path_attuned = arch->clone.path_attuned; + path_repelled = arch->clone.path_repelled; + path_denied = arch->clone.path_denied; + glow_radius = arch->clone.glow_radius; + move_type = arch->clone.move_type; + + chosen_skill = NULL; /* initializing resistances from the values in player/monster's * archetype clone */ - memcpy (&op->resist, &op->arch->clone.resist, sizeof (op->resist)); + memcpy (&resist, &arch->clone.resist, sizeof (resist)); for (i = 0; i < NROFATTACKS; i++) { - if (op->resist[i] > 0) - prot[i] = op->resist[i], vuln[i] = 0; + if (resist[i] > 0) + prot[i] = resist[i], vuln[i] = 0; else - vuln[i] = -(op->resist[i]), prot[i] = 0; + vuln[i] = -(resist[i]), prot[i] = 0; potion_resist[i] = 0; } - wc = op->arch->clone.stats.wc; - op->stats.dam = op->arch->clone.stats.dam; + wc = arch->clone.stats.wc; + stats.dam = arch->clone.stats.dam; /* for players which cannot use armour, they gain AC -1 per 3 levels, * plus a small amount of physical resist, those poor suckers. ;) @@ -917,37 +914,34 @@ * basically, if a server updates its max level, these playes may find * that their protection from physical goes down */ - if (!QUERY_FLAG (op, FLAG_USE_ARMOUR) && op->type == PLAYER) + if (!QUERY_FLAG (this, FLAG_USE_ARMOUR) && type == PLAYER) { - ac = MAX (-10, op->arch->clone.stats.ac - op->level / 3); - prot[ATNR_PHYSICAL] += ((100 - prot[AT_PHYSICAL]) * (80 * op->level / settings.max_level)) / 100; + ac = MAX (-10, arch->clone.stats.ac - level / 3); + prot[ATNR_PHYSICAL] += ((100 - prot[AT_PHYSICAL]) * (80 * level / settings.max_level)) / 100; } else - ac = op->arch->clone.stats.ac; + ac = arch->clone.stats.ac; - op->stats.luck = op->arch->clone.stats.luck; - op->speed = op->arch->clone.speed; + stats.luck = arch->clone.stats.luck; + speed = arch->clone.speed; /* OK - we've reset most all the objects attributes to sane values. * now go through and make adjustments for what the player has equipped. */ - - for (tmp = op->inv; tmp != NULL; tmp = tmp->below) + for (tmp = inv; tmp; tmp = tmp->below) { /* See note in map.c:update_position about making this additive * since light sources are never applied, need to put check here. */ - if (tmp->glow_radius > op->glow_radius) - op->glow_radius = tmp->glow_radius; + if (tmp->glow_radius > glow_radius) + glow_radius = tmp->glow_radius; /* This happens because apply_potion calls change_abil with the potion - * applied so we can tell the player what chagned. But change_abil + * applied so we can tell the player what changed. But change_abil * then calls this function. */ if (QUERY_FLAG (tmp, FLAG_APPLIED) && tmp->type == POTION) - { - continue; - } + continue; /* For some things, we don't care what is equipped */ if (tmp->type == SKILL) @@ -960,6 +954,7 @@ else if (tmp->level > mana_obj->level) mana_obj = tmp; } + if (IS_GRACE_SKILL (tmp->subtype)) { if (!grace_obj) @@ -978,56 +973,60 @@ * because the skill shouldn't count against body positions being used * up, etc. */ - if ((QUERY_FLAG (tmp, FLAG_APPLIED) && tmp->type != CONTAINER && tmp->type != CLOSE_CON) || - (tmp->type == SKILL && tmp->subtype == SK_PRAYING)) + if ((QUERY_FLAG (tmp, FLAG_APPLIED) + && tmp->type != CONTAINER + && tmp->type != CLOSE_CON) + || (tmp->type == SKILL + && tmp->subtype == SK_PRAYING)) { - if (op->type == PLAYER) + if (type == PLAYER) { if (tmp->type == BOW) - op->contr->ranges[range_bow] = tmp; + contr->ranges[range_bow] = tmp; if (tmp->type == WAND || tmp->type == ROD || tmp->type == HORN) - op->contr->ranges[range_misc] = tmp; + contr->ranges[range_misc] = tmp; for (i = 0; i < NUM_STATS; i++) - change_attr_value (&(op->stats), i, get_attr_value (&(tmp->stats), i)); + change_attr_value (&stats, i, get_attr_value (&tmp->stats, i)); /* these are the items that currently can change digestion, regeneration, * spell point recovery and mana point recovery. Seems sort of an arbitary * list, but other items store other info into stats array. */ - if ((tmp->type == EXPERIENCE) || (tmp->type == WEAPON) || - (tmp->type == ARMOUR) || (tmp->type == HELMET) || - (tmp->type == SHIELD) || (tmp->type == RING) || - (tmp->type == BOOTS) || (tmp->type == GLOVES) || - (tmp->type == AMULET) || (tmp->type == GIRDLE) || - (tmp->type == BRACERS) || (tmp->type == CLOAK) || (tmp->type == DISEASE) || (tmp->type == FORCE) || (tmp->type == SKILL)) + if ((tmp->type == WEAPON) || (tmp->type == BOW) || + (tmp->type == ARMOUR) || (tmp->type == HELMET) || + (tmp->type == SHIELD) || (tmp->type == RING) || + (tmp->type == BOOTS) || (tmp->type == GLOVES) || + (tmp->type == AMULET) || (tmp->type == GIRDLE) || + (tmp->type == BRACERS) || (tmp->type == CLOAK) || + (tmp->type == DISEASE) || (tmp->type == FORCE) || + (tmp->type == SKILL)) { - op->contr->digestion += tmp->stats.food; - op->contr->gen_hp += tmp->stats.hp; - op->contr->gen_sp += tmp->stats.sp; - op->contr->gen_grace += tmp->stats.grace; - op->contr->gen_sp_armour += tmp->gen_sp_armour; - op->contr->item_power += tmp->item_power; + contr->digestion += tmp->stats.food; + contr->gen_hp += tmp->stats.hp; + contr->gen_sp += tmp->stats.sp; + contr->gen_grace += tmp->stats.grace; + contr->gen_sp_armour += tmp->gen_sp_armour; + contr->item_power += tmp->item_power; } } /* if this is a player */ /* Update slots used for items */ if (QUERY_FLAG (tmp, FLAG_APPLIED)) - { - for (i = 0; i < NUM_BODY_LOCATIONS; i++) - op->body_used[i] += tmp->body_info[i]; - } + for (i = 0; i < NUM_BODY_LOCATIONS; i++) + body_used[i] += tmp->body_info[i]; if (tmp->type == SYMPTOM) { - speed_reduce_from_disease = tmp->last_sp / 100.0; + speed_reduce_from_disease = tmp->last_sp / 100.f; + if (speed_reduce_from_disease == 0) speed_reduce_from_disease = 1; } /* Pos. and neg. protections are counted seperate (-> pro/vuln). - * (Negative protections are calculated extactly like positive.) + * (Negative protections are calculated exactly like positive.) * Resistance from potions are treated special as well. If there's * more than one potion-effect, the bigger prot.-value is taken. */ @@ -1036,7 +1035,7 @@ for (i = 0; i < NROFATTACKS; i++) { /* Potential for cursed potions, in which case we just can use - * a straight MAX, as potion_resist is initialized to zero. + * a straight MAX, as potion_resist is initialised to zero. */ if (tmp->type == POTION_EFFECT) { @@ -1046,55 +1045,48 @@ potion_resist[i] = tmp->resist[i]; } else if (tmp->resist[i] > 0) - prot[i] += ((100 - prot[i]) * tmp->resist[i]) / 100; + prot[i] += ((100 - prot[i]) * tmp->resist[i]) / 100; else if (tmp->resist[i] < 0) - vuln[i] += ((100 - vuln[i]) * (-tmp->resist[i])) / 100; + vuln[i] += ((100 - vuln[i]) * -tmp->resist[i]) / 100; } } /* There may be other things that should not adjust the attacktype */ if (tmp->type != BOW && tmp->type != SYMPTOM) - op->attacktype |= tmp->attacktype; + attacktype |= tmp->attacktype; - op->path_attuned |= tmp->path_attuned; - op->path_repelled |= tmp->path_repelled; - op->path_denied |= tmp->path_denied; - op->stats.luck += tmp->stats.luck; - op->move_type |= tmp->move_type; - - if (QUERY_FLAG (tmp, FLAG_LIFESAVE)) - SET_FLAG (op, FLAG_LIFESAVE); - if (QUERY_FLAG (tmp, FLAG_REFL_SPELL)) - SET_FLAG (op, FLAG_REFL_SPELL); - if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE)) - SET_FLAG (op, FLAG_REFL_MISSILE); - if (QUERY_FLAG (tmp, FLAG_STEALTH)) - SET_FLAG (op, FLAG_STEALTH); - if (QUERY_FLAG (tmp, FLAG_XRAYS)) - SET_FLAG (op, FLAG_XRAYS); - if (QUERY_FLAG (tmp, FLAG_BLIND)) - SET_FLAG (op, FLAG_BLIND); - if (QUERY_FLAG (tmp, FLAG_SEE_IN_DARK)) - SET_FLAG (op, FLAG_SEE_IN_DARK); + path_attuned |= tmp->path_attuned; + path_repelled |= tmp->path_repelled; + path_denied |= tmp->path_denied; + move_type |= tmp->move_type; + stats.luck += tmp->stats.luck; + + if (QUERY_FLAG (tmp, FLAG_LIFESAVE )) SET_FLAG (this, FLAG_LIFESAVE); + if (QUERY_FLAG (tmp, FLAG_REFL_SPELL )) SET_FLAG (this, FLAG_REFL_SPELL); + if (QUERY_FLAG (tmp, FLAG_REFL_MISSILE)) SET_FLAG (this, FLAG_REFL_MISSILE); + if (QUERY_FLAG (tmp, FLAG_STEALTH )) SET_FLAG (this, FLAG_STEALTH); + if (QUERY_FLAG (tmp, FLAG_XRAYS )) SET_FLAG (this, FLAG_XRAYS); + if (QUERY_FLAG (tmp, FLAG_BLIND )) SET_FLAG (this, FLAG_BLIND); + if (QUERY_FLAG (tmp, FLAG_SEE_IN_DARK )) SET_FLAG (this, FLAG_SEE_IN_DARK); - if (QUERY_FLAG (tmp, FLAG_UNDEAD) && !QUERY_FLAG (&op->arch->clone, FLAG_UNDEAD)) - SET_FLAG (op, FLAG_UNDEAD); + if (QUERY_FLAG (tmp, FLAG_UNDEAD) && !QUERY_FLAG (&arch->clone, FLAG_UNDEAD)) + SET_FLAG (this, FLAG_UNDEAD); if (QUERY_FLAG (tmp, FLAG_MAKE_INVIS)) { - SET_FLAG (op, FLAG_MAKE_INVIS); - op->invisible = 1; + SET_FLAG (this, FLAG_MAKE_INVIS); + invisible = 1; } if (tmp->stats.exp && tmp->type != SKILL) { if (tmp->stats.exp > 0) { - added_speed += (float) tmp->stats.exp / 3.0; - bonus_speed += 1.0 + (float) tmp->stats.exp / 3.0; + added_speed += tmp->stats.exp / 3.f; + bonus_speed += 1.f + tmp->stats.exp / 3.f; } else - added_speed += (float) tmp->stats.exp; + added_speed += tmp->stats.exp; } switch (tmp->type) @@ -1108,51 +1100,56 @@ if (IS_COMBAT_SKILL (tmp->subtype)) wc_obj = tmp; - if (op->chosen_skill) - LOG (llevDebug, "fix_player, op %s has multiple skills applied\n", &op->name); + if (chosen_skill) + LOG (llevDebug, "fix_player, op %s has multiple skills applied\n", &name); - op->chosen_skill = tmp; + chosen_skill = tmp; if (tmp->stats.dam > 0) { /* skill is a 'weapon' */ - if (!QUERY_FLAG (op, FLAG_READY_WEAPON)) - weapon_speed = (int) WEAPON_SPEED (tmp); + if (!QUERY_FLAG (this, FLAG_READY_WEAPON)) + weapon_speed = WEAPON_SPEED (tmp); + if (weapon_speed < 0) weapon_speed = 0; + weapon_weight = tmp->weight; - op->stats.dam += tmp->stats.dam * (1 + (op->chosen_skill->level / 9)); + stats.dam += tmp->stats.dam * (1 + (chosen_skill->level / 9)); + if (tmp->magic) - op->stats.dam += tmp->magic; + stats.dam += tmp->magic; } if (tmp->stats.wc) wc -= (tmp->stats.wc + tmp->magic); - if (tmp->slaying != NULL) - op->slaying = tmp->slaying; + if (tmp->slaying) + slaying = tmp->slaying; if (tmp->stats.ac) ac -= (tmp->stats.ac + tmp->magic); - if (settings.spell_encumbrance == TRUE && op->type == PLAYER) - op->contr->encumbrance += (int) 3 *tmp->weight / 1000; - if (op->type == PLAYER) - op->contr->ranges[range_skill] = op; + if (settings.spell_encumbrance == TRUE && type == PLAYER) + contr->encumbrance += (int) 3 *tmp->weight / 1000; + + if (type == PLAYER) + contr->ranges[range_skill] = this; + break; case SKILL_TOOL: - if (op->chosen_skill) - { - LOG (llevDebug, "fix_player, op %s has multiple skills applied\n", &op->name); - } - op->chosen_skill = tmp; - if (op->type == PLAYER) - op->contr->ranges[range_skill] = op; + if (chosen_skill) + LOG (llevDebug, "fix_player, op %s has multiple skills applied\n", &name); + + chosen_skill = tmp; + + if (type == PLAYER) + contr->ranges[range_skill] = this; break; case SHIELD: - if (settings.spell_encumbrance == TRUE && op->type == PLAYER) - op->contr->encumbrance += (int) tmp->weight / 2000; + if (settings.spell_encumbrance == TRUE && type == PLAYER) + contr->encumbrance += (int) tmp->weight / 2000; case RING: case AMULET: case GIRDLE: @@ -1161,36 +1158,45 @@ case GLOVES: case CLOAK: if (tmp->stats.wc) - wc -= (tmp->stats.wc + tmp->magic); + wc -= tmp->stats.wc + tmp->magic; + if (tmp->stats.dam) - op->stats.dam += (tmp->stats.dam + tmp->magic); + stats.dam += tmp->stats.dam + tmp->magic; + if (tmp->stats.ac) - ac -= (tmp->stats.ac + tmp->magic); + ac -= tmp->stats.ac + tmp->magic; + break; case WEAPON: - wc -= (tmp->stats.wc + tmp->magic); + wc -= tmp->stats.wc + tmp->magic; + if (tmp->stats.ac && tmp->stats.ac + tmp->magic > 0) ac -= tmp->stats.ac + tmp->magic; - op->stats.dam += (tmp->stats.dam + tmp->magic); + + stats.dam += tmp->stats.dam + tmp->magic; weapon_weight = tmp->weight; - weapon_speed = ((int) WEAPON_SPEED (tmp) * 2 - tmp->magic) / 2; + weapon_speed = (WEAPON_SPEED (tmp) * 2 - tmp->magic) / 2; + if (weapon_speed < 0) weapon_speed = 0; - op->slaying = tmp->slaying; + + slaying = tmp->slaying; + /* If there is desire that two handed weapons should do * extra strength damage, this is where the code should * go. */ - op->current_weapon = tmp; - if (settings.spell_encumbrance == TRUE && op->type == PLAYER) - op->contr->encumbrance += (int) 3 *tmp->weight / 1000; + + current_weapon = tmp; + if (type == PLAYER && settings.spell_encumbrance) + contr->encumbrance += tmp->weight * 3 / 1000; break; case ARMOUR: /* Only the best of these three are used: */ - if (settings.spell_encumbrance == TRUE && op->type == PLAYER) - op->contr->encumbrance += (int) tmp->weight / 1000; + if (settings.spell_encumbrance == TRUE && type == PLAYER) + contr->encumbrance += tmp->weight / 1000; case BRACERS: case FORCE: @@ -1204,6 +1210,7 @@ else wc += tmp->stats.wc + tmp->magic; } + if (tmp->stats.ac) { if (best_ac < tmp->stats.ac + tmp->magic) @@ -1214,12 +1221,16 @@ else /* To nullify the below effect */ ac += tmp->stats.ac + tmp->magic; } + if (tmp->stats.wc) wc -= (tmp->stats.wc + tmp->magic); + if (tmp->stats.ac) ac -= (tmp->stats.ac + tmp->magic); - if (ARMOUR_SPEED (tmp) && ARMOUR_SPEED (tmp) / 10.0 < max) - max = ARMOUR_SPEED (tmp) / 10.0; + + if (ARMOUR_SPEED (tmp) && ARMOUR_SPEED (tmp) / 10.f < max) + max = ARMOUR_SPEED (tmp) / 10.f; + break; } /* switch tmp->type */ } /* item is equipped */ @@ -1237,18 +1248,19 @@ */ for (i = 0; i < NROFATTACKS; i++) { - op->resist[i] = prot[i] - vuln[i]; - if (potion_resist[i] && ((potion_resist[i] > op->resist[i]) || (potion_resist[i] < 0))) - op->resist[i] = potion_resist[i]; + resist[i] = prot[i] - vuln[i]; + + if (potion_resist[i] && ((potion_resist[i] > resist[i]) || (potion_resist[i] < 0))) + resist[i] = potion_resist[i]; } /* Figure out the players sp/mana/hp totals. */ - if (op->type == PLAYER) + if (type == PLAYER) { int pl_level; - check_stat_bounds (&(op->stats)); - pl_level = op->level; + check_stat_bounds (&(stats)); + pl_level = level; if (pl_level < 1) pl_level = 1; /* safety, we should always get 1 levels worth of hp! */ @@ -1256,78 +1268,78 @@ /* You basically get half a con bonus/level. But we do take into account rounding, * so if your bonus is 7, you still get 7 worth of bonus every 2 levels. */ - for (i = 1, op->stats.maxhp = 0; i <= pl_level && i <= 10; i++) + for (i = 1, stats.maxhp = 0; i <= pl_level && i <= 10; i++) { - j = op->contr->levhp[i] + con_bonus[op->stats.Con] / 2; - if (i % 2 && con_bonus[op->stats.Con] % 2) + j = contr->levhp[i] + con_bonus[stats.Con] / 2; + + if (i % 2 && con_bonus[stats.Con] % 2) { - if (con_bonus[op->stats.Con] > 0) + if (con_bonus[stats.Con] > 0) j++; else j--; } - op->stats.maxhp += j > 1 ? j : 1; /* always get at least 1 hp/level */ + + stats.maxhp += j > 1 ? j : 1; /* always get at least 1 hp/level */ } - for (i = 11; i <= op->level; i++) - op->stats.maxhp += 2; + for (i = 11; i <= level; i++) + stats.maxhp += 2; - if (op->stats.hp > op->stats.maxhp) - op->stats.hp = op->stats.maxhp; + if (stats.hp > stats.maxhp) + stats.hp = stats.maxhp; /* Sp gain is controlled by the level of the player's * relevant experience object (mana_obj, see above) */ /* following happen when skills system is not used */ if (!mana_obj) - mana_obj = op; + mana_obj = this; + if (!grace_obj) - grace_obj = op; + grace_obj = this; + /* set maxsp */ - if (!mana_obj || !mana_obj->level || op->type != PLAYER) - mana_obj = op; + if (!mana_obj || !mana_obj->level || type != PLAYER) + mana_obj = this; - if (mana_obj == op && op->type == PLAYER) - { - op->stats.maxsp = 1; - } + if (mana_obj == this && type == PLAYER) + stats.maxsp = 1; else { - sp_tmp = 0.0; + sp_tmp = 0.f; + for (i = 1; i <= mana_obj->level && i <= 10; i++) { float stmp; /* Got some extra bonus at first level */ if (i < 2) - { - stmp = op->contr->levsp[i] + ((2.0 * (float) sp_bonus[op->stats.Pow] + (float) sp_bonus[op->stats.Int]) / 6.0); - } + stmp = contr->levsp[i] + (2.f * sp_bonus[stats.Pow] + sp_bonus[stats.Int]) / 6.f; else - { - stmp = (float) op->contr->levsp[i] + (2.0 * (float) sp_bonus[op->stats.Pow] + (float) sp_bonus[op->stats.Int]) / 12.0; - } - if (stmp < 1.0) - stmp = 1.0; + stmp = contr->levsp[i] + (2.f * sp_bonus[stats.Pow] + sp_bonus[stats.Int]) / 12.f; + + if (stmp < 1.f) + stmp = 1.f; + sp_tmp += stmp; } - op->stats.maxsp = (int) sp_tmp; + + stats.maxsp = (sint16)sp_tmp; for (i = 11; i <= mana_obj->level; i++) - op->stats.maxsp += 2; + stats.maxsp += 2; } /* Characters can get their sp supercharged via rune of transferrance */ - if (op->stats.sp > op->stats.maxsp * 2) - op->stats.sp = op->stats.maxsp * 2; + if (stats.sp > stats.maxsp * 2) + stats.sp = stats.maxsp * 2; /* set maxgrace, notice 3-4 lines below it depends on both Wis and Pow */ - if (!grace_obj || !grace_obj->level || op->type != PLAYER) - grace_obj = op; + if (!grace_obj || !grace_obj->level || type != PLAYER) + grace_obj = this; - if (grace_obj == op && op->type == PLAYER) - { - op->stats.maxgrace = 1; - } + if (grace_obj == this && type == PLAYER) + stats.maxgrace = 1; else { /* store grace in a float - this way, the divisions below don't create @@ -1335,41 +1347,38 @@ * becomes big jumps when the sums of the bonuses jump to the next * step of 8 - with floats, even fractional ones are useful. */ - sp_tmp = 0.0; - for (i = 1, op->stats.maxgrace = 0; i <= grace_obj->level && i <= 10; i++) + sp_tmp = 0.f; + for (i = 1, stats.maxgrace = 0; i <= grace_obj->level && i <= 10; i++) { - float grace_tmp = 0.0; + float grace_tmp = 0.f; /* Got some extra bonus at first level */ if (i < 2) - { - grace_tmp = op->contr->levgrace[i] + (((float) grace_bonus[op->stats.Pow] + - 2.0 * (float) grace_bonus[op->stats.Wis]) / 6.0); - } + grace_tmp = contr->levgrace[i] + (grace_bonus[stats.Pow] + 2.f * grace_bonus[stats.Wis]) / 6.f; else - { - grace_tmp = (float) op->contr->levgrace[i] - + ((float) grace_bonus[op->stats.Pow] + 2.0 * (float) grace_bonus[op->stats.Wis]) / 12.0; - } - if (grace_tmp < 1.0) - grace_tmp = 1.0; + grace_tmp = contr->levgrace[i] + (grace_bonus[stats.Pow] + 2.f * grace_bonus[stats.Wis]) / 12.f; + + if (grace_tmp < 1.f) + grace_tmp = 1.f; + sp_tmp += grace_tmp; } - op->stats.maxgrace = (int) sp_tmp; + + stats.maxgrace = (sint16)sp_tmp; /* two grace points per level after 11 */ for (i = 11; i <= grace_obj->level; i++) - op->stats.maxgrace += 2; + stats.maxgrace += 2; } /* No limit on grace vs maxgrace */ - if (op->contr->braced) + if (contr->braced) { ac += 2; wc += 4; } else - ac -= dex_bonus[op->stats.Dex]; + ac -= dex_bonus[stats.Dex]; /* In new exp/skills system, wc bonuses are related to * the players level in a relevant exp object (wc_obj) @@ -1383,90 +1392,97 @@ * monster bonus the same as before. -b.t. */ - if (op->type == PLAYER && wc_obj && wc_obj->level > 1) + if (type == PLAYER && wc_obj && wc_obj->level > 1) { - wc -= (wc_obj->level + thaco_bonus[op->stats.Str]); + wc -= wc_obj->level + thaco_bonus[stats.Str]; + for (i = 1; i < wc_obj->level; i++) { /* addtional wc every 6 levels */ if (!(i % 6)) wc--; + /* addtional dam every 4 levels. */ - if (!(i % 4) && (dam_bonus[op->stats.Str] >= 0)) - op->stats.dam += (1 + (dam_bonus[op->stats.Str] / 5)); + if (!(i % 4) && dam_bonus[stats.Str] >= 0) + stats.dam += 1 + dam_bonus[stats.Str] / 5; } } else - wc -= (op->level + thaco_bonus[op->stats.Str]); + wc -= level + thaco_bonus[stats.Str]; + + stats.dam += dam_bonus[stats.Str]; + + if (stats.dam < 1) + stats.dam = 1; - op->stats.dam += dam_bonus[op->stats.Str]; + speed = 1.f + speed_bonus[stats.Dex]; - if (op->stats.dam < 1) - op->stats.dam = 1; + if (settings.search_items && contr->search_str[0]) + speed -= 1; - op->speed = 1.0 + speed_bonus[op->stats.Dex]; - if (settings.search_items && op->contr->search_str[0]) - op->speed -= 1; - if (op->attacktype == 0) - op->attacktype = op->arch->clone.attacktype; + if (attacktype == 0) + attacktype = arch->clone.attacktype; } /* End if player */ if (added_speed >= 0) - op->speed += added_speed / 10.0; + speed += added_speed / 10.f; else /* Something wrong here...: */ - op->speed /= (float) (1.0 - added_speed); + speed /= 1.f - added_speed; /* Max is determined by armour */ - if (op->speed > max) - op->speed = max; + if (speed > max) + speed = max; - if (op->type == PLAYER) + if (type == PLAYER) { /* f is a number the represents the number of kg above (positive num) * or below (negative number) that the player is carrying. If above * weight limit, then player suffers a speed reduction based on how * much above he is, and what is max carry is */ - f = (op->carrying / 1000) - max_carry[op->stats.Str]; + f = (carrying / 1000) - max_carry[stats.Str]; if (f > 0) - op->speed = op->speed / (1.0 + f / max_carry[op->stats.Str]); + speed = speed / (1.f + f / max_carry[stats.Str]); } - op->speed += bonus_speed / 10.0; /* Not affected by limits */ + speed += bonus_speed / 10.f; /* Not affected by limits */ /* Put a lower limit on speed. Note with this speed, you move once every * 100 ticks or so. This amounts to once every 12 seconds of realtime. */ - op->speed = op->speed * speed_reduce_from_disease; + speed = speed * speed_reduce_from_disease; - if (op->speed < 0.01 && op->type == PLAYER) - op->speed = 0.01; + if (speed < 0.01f && type == PLAYER) + speed = 0.01f; - if (op->type == PLAYER) + if (type == PLAYER) { - float M, W, s, D, K, S, M2; - /* (This formula was made by vidarl@ifi.uio.no) * Note that we never used these values again - basically * all of these could be subbed into one big equation, but * that would just be a real pain to read. */ - M = (max_carry[op->stats.Str] - 121) / 121.0; - M2 = max_carry[op->stats.Str] / 100.0; - W = weapon_weight / 20000.0; - s = 2 - weapon_speed / 10.0; - D = (op->stats.Dex - 14) / 14.0; - K = 1 + M / 3.0 - W / (3 * M2) + op->speed / 5.0 + D / 2.0; - K *= (4 + op->level) / (float) (6 + op->level) * 1.2; - if (K <= 0) - K = 0.01; - S = op->speed / (K * s); - op->contr->weapon_sp = S; + float M = (max_carry[stats.Str] - 121) / 121.f; + float M2 = max_carry[stats.Str] / 100.f; + float W = weapon_weight / 20000.f; + float s = 2 - weapon_speed / 10.f; + float D = (stats.Dex - 14) / 14.f; + float K = 1 + M / 3.f - W / (3 * M2) + speed / 5.f + D / 2.f; + + K *= (4 + level) *1.2f / (6 + level); + + if (K <= 0.f) + K = 0.01f; + + float S = speed / (K * s); + + contr->weapon_sp = S; } + /* I want to limit the power of small monsters with big weapons: */ - if (op->type != PLAYER && op->arch != NULL && op->stats.dam > op->arch->clone.stats.dam * 3) - op->stats.dam = op->arch->clone.stats.dam * 3; + if (type != PLAYER && arch && stats.dam > arch->clone.stats.dam * 3) + stats.dam = arch->clone.stats.dam * 3; /* Prevent overflows of wc - best you can get is ABS(120) - this * should be more than enough - remember, AC is also in 8 bits, @@ -1476,13 +1492,15 @@ wc = 120; else if (wc < -120) wc = -120; - op->stats.wc = wc; + + stats.wc = wc; if (ac > 120) ac = 120; else if (ac < -120) ac = -120; - op->stats.ac = ac; + + stats.ac = ac; /* if for some reason the creature doesn't have any move type, * give them walking as a default. @@ -1490,18 +1508,26 @@ * old behaviour - if your flying, your not walking - just * one or the other. */ - if (op->move_type == 0) - op->move_type = MOVE_WALK; - else if (op->move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) - op->move_type &= ~MOVE_WALK; + if (move_type == 0) + move_type = MOVE_WALK; + else if (move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) + move_type &= ~MOVE_WALK; - update_ob_speed (op); + if (speed != old_speed) + set_speed (speed); /* It is quite possible that a player's spell costing might have changed, * so we will check that now. */ - if (op->type == PLAYER) - esrv_update_spells (op->contr); + if (type == PLAYER) + { + esrv_update_stats (contr); + esrv_update_spells (contr); + } + + // update the mapspace, if we are on a map + if (!flag [FLAG_REMOVED] && map) + map->at (x, y).flags_ = 0; } /* @@ -1511,12 +1537,16 @@ * merely checks that all stats are 1 or more, and returns * false otherwise. */ - int allowed_class (const object *op) { - return op->stats.Dex > 0 && op->stats.Str > 0 && op->stats.Con > 0 && - op->stats.Int > 0 && op->stats.Wis > 0 && op->stats.Pow > 0 && op->stats.Cha > 0; + return op->stats.Dex > 0 + && op->stats.Str > 0 + && op->stats.Con > 0 + && op->stats.Int > 0 + && op->stats.Wis > 0 + && op->stats.Pow > 0 + && op->stats.Cha > 0; } /* @@ -1597,16 +1627,16 @@ char buf[MAX_BUF]; /* tmp. string buffer */ /* now grab the 'dragon_ability'-forces from the player's inventory */ - for (tmp = who->inv; tmp != NULL; tmp = tmp->below) - { - if (tmp->type == FORCE) - { - if (strcmp (tmp->arch->name, "dragon_ability_force") == 0) - abil = tmp; - if (strcmp (tmp->arch->name, "dragon_skin_force") == 0) - skin = tmp; - } - } + shstr_cmp dragon_ability_force ("dragon_ability_force"); + shstr_cmp dragon_skin_force ("dragon_skin_force"); + + for (tmp = who->inv; tmp; tmp = tmp->below) + if (tmp->type == FORCE) + if (tmp->arch->name == dragon_ability_force) + abil = tmp; + else if (tmp->arch->name == dragon_skin_force) + skin = tmp; + /* if the force is missing -> bail out */ if (abil == NULL) return; @@ -1667,11 +1697,14 @@ skill_obj->stats.exp = 0; skill_obj->level = 1; insert_ob_in_ob (skill_obj, op); + if (op->contr) { - op->contr->last_skill_ob[skill_obj->subtype] = skill_obj; - op->contr->last_skill_exp[skill_obj->subtype] = -1; + op->contr->last_skill_ob [skill_obj->subtype] = skill_obj; + if (op->contr->ns) + op->contr->ns->last_skill_exp[skill_obj->subtype] = -1;//TODO: should be made superfluous } + return skill_obj; } @@ -1706,7 +1739,7 @@ who->contr->levgrace[who->level] = die_roll (2, 2, who, PREFER_HIGH) - 1; } - fix_player (who); + who->update_stats (); if (op->level > 1) { if (op->type != PLAYER) @@ -1721,7 +1754,7 @@ else if (op->level > 1 && op->stats.exp < level_exp (op->level, who->expmul)) { op->level--; - fix_player (who); + who->update_stats (); if (op->type != PLAYER) { sprintf (buf, "You are now level %d in the %s skill.", op->level, &op->name); @@ -1729,7 +1762,9 @@ } player_lvl_adj (who, op); /* To decrease more levels */ } + /* check if the spell data has changed */ + esrv_update_stats (who->contr); esrv_update_spells (who->contr); } @@ -1743,6 +1778,7 @@ { if (level > settings.max_level) return (sint64) (expmul * levels[settings.max_level]); + return (sint64) (expmul * levels[level]); } @@ -1773,7 +1809,6 @@ op->perm_exp = MAX_EXPERIENCE; } - /* Add experience to a player - exp should only be positive. * Updates permanent exp for the skill we are adding to. * skill_name is the skill to add exp to. Skill name can be @@ -1781,7 +1816,6 @@ * total, but not any particular skill. * flag is what to do if the player doesn't have the skill: */ - static void add_player_exp (object *op, sint64 exp, const char *skill_name, int flag) { @@ -1936,6 +1970,7 @@ player_lvl_adj (op, tmp); } } + if (flag != SK_SUBTRACT_SKILL_EXP) { del_exp = check_exp_loss (op, exp); @@ -1944,8 +1979,6 @@ } } - - /* change_exp() - changes experience to a player/monster. This * does bounds checking to make sure we don't overflow the max exp. * @@ -1955,17 +1988,11 @@ * flag is what to do if player doesn't have the skill. * these last two values are only used for players. */ - void change_exp (object *op, sint64 exp, const char *skill_name, int flag) { - #ifdef EXP_DEBUG -# ifndef WIN32 - LOG (llevDebug, "change_exp() called for %s, exp = %lld\n", query_name (op), exp); -# else - LOG (llevDebug, "change_exp() called for %s, exp = %I64d\n", query_name (op), exp); -# endif + LOG (llevDebug, "change_exp() called for %s, exp = %" PRId64 "\n", query_name (op), exp); #endif /* safety */ @@ -2014,8 +2041,7 @@ * a particular skill, so we don't need to pass that * along. */ - subtract_player_exp (op, FABS (exp), skill_name, flag); - + subtract_player_exp (op, abs (exp), skill_name, flag); } } @@ -2023,7 +2049,6 @@ * settings death_penalty_percentage and death_penalty_levels, and by the * amount of permenent experience, whichever gives the lowest loss. */ - void apply_death_exp_penalty (object *op) { @@ -2078,5 +2103,6 @@ if ((random_roll (1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) return 0; + return 1; }