--- deliantra/server/common/living.C 2007/08/07 21:58:25 1.74 +++ deliantra/server/common/living.C 2008/05/02 20:16:24 1.83 @@ -1,11 +1,11 @@ /* - * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. + * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team + * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team * Copyright (©) 1992,2007 Frank Tore Johansen * - * Crossfire TRT is free software: you can redistribute it and/or modify + * Deliantra 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. @@ -18,11 +18,10 @@ * 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 + * The authors can be reached via e-mail to */ #include -#include /* Handy little macro that adds exp and keeps it within bounds. Since * we are now using 64 bit values, I'm not all concerned about overflow issues @@ -286,11 +285,11 @@ char message[MAX_BUF]; int potion_max = 0; - /* 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 update_stats. refop is not a real object - */ - object_copy refop = *op; + object::flags_t prev_flag = op->flag; + MoveType prev_move_type = op->move_type; + sint16 prev_resist [NROFATTACKS]; // clumsy + assert (sizeof (prev_resist) == sizeof (op->resist)); + memcpy (prev_resist, op->resist, sizeof (prev_resist)); if (op->type == PLAYER) { @@ -368,19 +367,19 @@ 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)) + if (op->flag [FLAG_LIFESAVE] != prev_flag [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)) + if (op->flag [FLAG_REFL_MISSILE] != prev_flag [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)) + if (op->flag [FLAG_REFL_SPELL] != prev_flag [FLAG_REFL_SPELL]) { success = 1; DIFF_MSG (flag, "You feel more safe now, somehow.", "Suddenly you feel less safe, somehow."); @@ -392,7 +391,7 @@ * can be misleading (a little higher could be miscontrued from * from fly high) */ - if (tmp->move_type && op->move_type != refop.move_type) + if (tmp->move_type && op->move_type != prev_move_type) { success = 1; @@ -423,8 +422,8 @@ /* becoming UNDEAD... a special treatment for this flag. Only those not * originally undead may change their status */ - if (!QUERY_FLAG (op->arch, FLAG_UNDEAD)) - if (QUERY_FLAG (op, FLAG_UNDEAD) != QUERY_FLAG (&refop, FLAG_UNDEAD)) + if (!op->arch->flag [FLAG_UNDEAD]) + if (op->flag [FLAG_UNDEAD] != prev_flag [FLAG_UNDEAD]) { success = 1; if (flag > 0) @@ -439,13 +438,13 @@ } } - if (QUERY_FLAG (op, FLAG_STEALTH) != QUERY_FLAG (&refop, FLAG_STEALTH)) + if (op->flag [FLAG_STEALTH] != prev_flag [FLAG_STEALTH]) { 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)) + if (op->flag [FLAG_MAKE_INVIS] != prev_flag [FLAG_MAKE_INVIS]) { success = 1; DIFF_MSG (flag, "You become transparent.", "You can see yourself."); @@ -454,12 +453,12 @@ /* blinded you can tell if more blinded since blinded player has minimal * vision */ - if (QUERY_FLAG (tmp, FLAG_BLIND)) + if (tmp->flag [FLAG_BLIND]) { success = 1; if (flag > 0) { - if (QUERY_FLAG (op, FLAG_WIZ)) + if (op->flag [FLAG_WIZ]) new_draw_info (NDI_UNIQUE, 0, op, "Your mortal self is blinded."); else { @@ -471,7 +470,7 @@ } else { - if (QUERY_FLAG (op, FLAG_WIZ)) + if (op->flag [FLAG_WIZ]) new_draw_info (NDI_UNIQUE, 0, op, "Your mortal self can now see again."); else { @@ -483,7 +482,7 @@ } } - if (QUERY_FLAG (op, FLAG_SEE_IN_DARK) != QUERY_FLAG (&refop, FLAG_SEE_IN_DARK)) + if (op->flag [FLAG_SEE_IN_DARK] != prev_flag [FLAG_SEE_IN_DARK]) { success = 1; if (op->type == PLAYER) @@ -491,12 +490,12 @@ DIFF_MSG (flag, "Your vision is better in the dark.", "You see less well in the dark."); } - if (QUERY_FLAG (op, FLAG_XRAYS) != QUERY_FLAG (&refop, FLAG_XRAYS)) + if (op->flag [FLAG_XRAYS] != prev_flag [FLAG_XRAYS]) { success = 1; if (flag > 0) { - if (QUERY_FLAG (op, FLAG_WIZ)) + if (op->flag [FLAG_WIZ]) new_draw_info (NDI_UNIQUE, 0, op, "Your vision becomes a little clearer."); else { @@ -507,7 +506,7 @@ } else { - if (QUERY_FLAG (op, FLAG_WIZ)) + if (op->flag [FLAG_WIZ]) new_draw_info (NDI_UNIQUE, 0, op, "Your vision becomes a bit out of focus."); else { @@ -555,13 +554,14 @@ if (i == ATNR_PHYSICAL) continue; /* Don't display about armour */ - if (op->resist[i] != refop.resist[i]) + if (op->resist [i] != prev_resist [i]) { success = 1; - if (op->resist[i] > refop.resist[i]) - sprintf (message, "Your resistance to %s rises to %d%%.", change_resist_msg[i], op->resist[i]); + + if (op->resist [i] > prev_resist [i]) + sprintf (message, "Your resistance to %s rises to %d%%.", change_resist_msg [i], op->resist [i]); else - sprintf (message, "Your resistance to %s drops to %d%%.", change_resist_msg[i], op->resist[i]); + sprintf (message, "Your resistance to %s drops to %d%%.", change_resist_msg [i], op->resist [i]); new_draw_info (NDI_UNIQUE | NDI_BLUE, 0, op, message); } @@ -759,19 +759,19 @@ void object::update_stats () { - int i, j; float f, max_speed = 9, added_speed = 0, bonus_speed = 0, speed_reduce_from_disease = 1; int weapon_weight = 0, weapon_speed = 0; 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, *tmp; float old_speed = speed; + int stat_sum [NUM_STATS]; /* First task is to clear all the values back to their original values */ if (type == PLAYER) { - for (i = 0; i < NUM_STATS; i++) - stats.stat (i) = contr->orig_stats.stat (i); + for (int i = 0; i < NUM_STATS; i++) + stat_sum [i] = contr->orig_stats.stat (i); if (settings.spell_encumbrance == TRUE) contr->encumbrance = 0; @@ -819,7 +819,7 @@ */ memcpy (&resist, &arch->resist, sizeof (resist)); - for (i = 0; i < NROFATTACKS; i++) + for (int i = 0; i < NROFATTACKS; i++) { if (resist[i] > 0) prot[i] = resist[i], vuln[i] = 0; @@ -916,12 +916,11 @@ continue; for (int i = 0; i < NUM_STATS; i++) - if (expect_false (tmp->stats.stat (i))) - stats.stat (i) = clamp (stats.stat (i) + tmp->stats.stat (i), MIN_STAT, MAX_STAT); + stat_sum [i] = stat_sum [i] + tmp->stats.stat (i); if (digest_types [tmp->type]) { - contr->digestion = clamp (int (contr->digestion) + tmp->stats.food, MIN_DIGESTION, MAX_DIGESTION); + contr->digestion += tmp->stats.food; contr->gen_hp += tmp->stats.hp; contr->gen_sp += tmp->stats.sp; contr->gen_grace += tmp->stats.grace; @@ -936,16 +935,12 @@ /* Update slots used for items */ if (QUERY_FLAG (tmp, FLAG_APPLIED)) - for (i = 0; i < NUM_BODY_LOCATIONS; i++) + for (int i = 0; i < NUM_BODY_LOCATIONS; i++) slot[i].used += tmp->slot[i].info; if (tmp->type == SYMPTOM) - { - speed_reduce_from_disease = tmp->last_sp / 100.f; - - if (speed_reduce_from_disease == 0) - speed_reduce_from_disease = 1; - } + speed_reduce_from_disease = + min (speed_reduce_from_disease, tmp->last_sp ? tmp->last_sp / 100.f : 1.f); /* Pos. and neg. protections are counted seperate (-> pro/vuln). * (Negative protections are calculated exactly like positive.) @@ -954,7 +949,7 @@ */ if (tmp->type != POTION) { - for (i = 0; i < NROFATTACKS; i++) + for (int i = 0; i < NROFATTACKS; i++) { /* Potential for cursed potions, in which case we just can use * a straight MAX, as potion_resist is initialised to zero. @@ -1169,7 +1164,7 @@ * If there is a cursed (and no uncursed) potion in effect, we take * 'total resistance = vulnerability from cursed potion'. */ - for (i = 0; i < NROFATTACKS; i++) + for (int i = 0; i < NROFATTACKS; i++) { resist[i] = prot[i] - vuln[i]; @@ -1177,9 +1172,15 @@ resist[i] = potion_resist[i]; } - /* Figure out the players sp/mana/hp totals. */ if (type == PLAYER) { + // clamp various player stats + for (int i = 0; i < NUM_STATS; ++i) + stats.stat (i) = clamp (stat_sum [i], MIN_STAT, MAX_STAT); + + contr->digestion = clamp (contr->digestion, MIN_DIGESTION, MAX_DIGESTION); + + /* Figure out the players sp/mana/hp totals. */ int pl_level; check_stat_bounds (&(stats)); @@ -1191,9 +1192,10 @@ /* 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, stats.maxhp = 0; i <= pl_level && i <= 10; i++) + stats.maxhp = 0; + for (int i = 1; i <= min (10, pl_level); i++) { - j = contr->levhp[i] + con_bonus[stats.Con] / 2; + int j = contr->levhp[i] + con_bonus[stats.Con] / 2; if (i % 2 && con_bonus[stats.Con] % 2) if (con_bonus[stats.Con] > 0) @@ -1204,8 +1206,7 @@ stats.maxhp += j > 1 ? j : 1; /* always get at least 1 hp/level */ } - for (i = 11; i <= level; i++) - stats.maxhp += 2; + stats.maxhp += 2 * max (0, level - 10); if (stats.hp > stats.maxhp) stats.hp = stats.maxhp; @@ -1230,7 +1231,7 @@ { float sp_tmp = 0.f; - for (i = 1; i <= min (10, mana_obj->level); i++) + for (int i = 1; i <= min (10, mana_obj->level); i++) { float stmp; @@ -1264,7 +1265,7 @@ */ float sp_tmp = 0.f; - for (i = 1; i <= min (10, grace_obj->level); i++) + for (int i = 1; i <= min (10, grace_obj->level); i++) { float grace_tmp = 0.f; @@ -1308,7 +1309,7 @@ { wc -= wc_obj->level + thaco_bonus[stats.Str]; - for (i = 1; i < wc_obj->level; i++) + for (int i = 1; i < wc_obj->level; i++) { /* additional wc every 6 levels */ if (!(i % 6)) @@ -1351,20 +1352,22 @@ * weight limit, then player suffers a speed reduction based on how * much above he is, and what is max carry is */ - f = (carrying / 1000) - max_carry[stats.Str]; - if (f > 0) + float f = (carrying / 1000) - max_carry[stats.Str]; + if (f > 0.f) speed = speed / (1.f + f / max_carry[stats.Str]); } speed += bonus_speed / 10.f; /* Not affected by limits */ + speed *= speed_reduce_from_disease; /* 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. + * 25 ticks or so. This amounts to once every 3 seconds of realtime. */ - speed = speed * speed_reduce_from_disease; + if (speed < 0.04f && type == PLAYER) + speed = 0.04f; - if (speed < 0.01f && type == PLAYER) - speed = 0.01f; + if (speed != old_speed) + set_speed (speed); if (type == PLAYER) { @@ -1406,9 +1409,6 @@ else if (move_type & (MOVE_FLY_LOW | MOVE_FLY_HIGH)) move_type &= ~MOVE_WALK; - 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. */ @@ -1478,10 +1478,10 @@ if (atnr_is_dragon_enabled (abil->stats.exp) && abil->resist[abil->stats.exp] >= level) atnr = abil->stats.exp; - level = (int) (level / 5.); + level = (int) (level / 25.); /* now set the new title */ - if (pl->contr != NULL) + if (pl->contr) { if (level == 0) sprintf (pl->contr->title, "%s hatchling", attacks[atnr]);