--- deliantra/server/common/living.C 2006/09/10 16:00:23 1.9
+++ deliantra/server/common/living.C 2007/07/04 18:03:48 1.69
@@ -1,32 +1,26 @@
-
/*
- * static char *rcsid_living_c =
- * "$Id: living.C,v 1.9 2006/09/10 16:00:23 root Exp $";
+ * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
+ *
+ * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT 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
+ * 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.
+ *
+ * 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, see .
+ *
+ * The authors can be reached via e-mail to
*/
-/*
- 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
-*/
-
#include
#include
@@ -166,11 +160,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
@@ -203,160 +193,68 @@
"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)
-{
- switch (attr)
- {
- case STR:
- stats->Str = value;
- break;
- case DEX:
- stats->Dex = value;
- break;
- case CON:
- stats->Con = value;
- break;
- case WIS:
- stats->Wis = value;
- break;
- case POW:
- stats->Pow = value;
- break;
- case CHA:
- stats->Cha = value;
- break;
- case INT:
- stats->Int = value;
- break;
- }
-}
-
-/*
* 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)
-{
- if (value == 0)
- return;
- switch (attr)
- {
- case STR:
- stats->Str += value;
- break;
- case DEX:
- stats->Dex += value;
- break;
- case CON:
- stats->Con += value;
- break;
- case WIS:
- stats->Wis += value;
- break;
- case POW:
- stats->Pow += value;
- break;
- case CHA:
- stats->Cha += value;
- break;
- case INT:
- stats->Int += value;
- break;
- default:
- LOG (llevError, "Invalid attribute in change_attr_value: %d\n", attr);
- }
-}
-
-/*
- * returns the specified stat. See also set_attr_value().
- */
-
-sint8
-get_attr_value (const living * stats, int attr)
+change_attr_value (living *stats, int attr, sint8 value)
{
- 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);
- }
- return 0;
+ stats->stat (attr) += value;
}
/*
* Ensures that all stats (str/dex/con/wis/cha/int) are within the
* 1-30 stat limit.
*/
-
void
-check_stat_bounds (living * stats)
+check_stat_bounds (living *stats)
{
- int i, v;
-
- for (i = 0; i < NUM_STATS; i++)
- if ((v = get_attr_value (stats, i)) > MAX_STAT)
- set_attr_value (stats, i, MAX_STAT);
- else if (v < MIN_STAT)
- set_attr_value (stats, i, MIN_STAT);
+ for (int i = 0; i < NUM_STATS; i++)
+ {
+ sint8 &v = stats->stat (i);
+ v = clamp (v, MIN_STAT, MAX_STAT);
+ }
}
#define ORIG_S(xyz,abc) (op->contr->orig_stats.abc)
@@ -375,7 +273,7 @@
* It is the calling functions responsibilty to check to see if the object
* can be applied or not.
* The main purpose of calling this function is the messages that are
- * displayed - fix_player should really always be called after this when
+ * displayed - update_stats should really always be called after this when
* removing an object - that is because it is impossible to know if some object
* is the only source of an attacktype or spell attunement, so this function
* will clear the bits, but the player may still have some other object
@@ -384,30 +282,28 @@
int
change_abil (object *op, object *tmp)
{
- int flag = QUERY_FLAG (tmp, FLAG_APPLIED) ? 1 : -1, i, j, success = 0;
+ int flag = QUERY_FLAG (tmp, FLAG_APPLIED) ? 1 : -1, success = 0;
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 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)
{
if (tmp->type == POTION)
{
potion_max = 1;
- for (j = 0; j < NUM_STATS; j++)
+ for (int j = 0; j < NUM_STATS; j++)
{
- int nstat, ostat;
-
- ostat = get_attr_value (&(op->contr->orig_stats), j);
- i = get_attr_value (&(tmp->stats), j);
+ int ostat = op->contr->orig_stats.stat (j);
+ int i = tmp->stats.stat (j);
/* nstat is what the stat will be after use of the potion */
- nstat = flag * i + ostat;
+ int nstat = flag * i + ostat;
/* Do some bounds checking. While I don't think any
* potions do so right now, there is the potential for potions
@@ -416,13 +312,12 @@
*/
if (nstat < 1 && i * flag < 0)
nstat = 1;
- else if (nstat > 20 + get_attr_value (&(op->arch->clone.stats), j))
- {
- nstat = 20 + get_attr_value (&(op->arch->clone.stats), j);
- }
+ else if (nstat > 20 + op->arch->stats.stat (j))
+ nstat = 20 + op->arch->stats.stat (j);
+
if (nstat != ostat)
{
- set_attr_value (&(op->contr->orig_stats), j, nstat);
+ op->contr->orig_stats.stat (j) = nstat;
potion_max = 0;
}
else if (i)
@@ -431,38 +326,40 @@
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));
+ for (int j = 0; j < NUM_STATS; j++)
+ change_attr_value (&op->stats, j, flag * tmp->stats.stat (j));
+
+ check_stat_bounds (&op->stats);
} /* end of potion handling code */
}
- /* reset attributes that fix_player doesn't reset since it doesn't search
+ /* reset attributes that update_stats doesn't reset since it doesn't search
* everything to set
*/
if (flag == -1)
{
- op->attacktype &= ~tmp->attacktype;
- op->path_attuned &= ~tmp->path_attuned;
+ op->attacktype &= ~tmp->attacktype;
+ op->path_attuned &= ~tmp->path_attuned;
op->path_repelled &= ~tmp->path_repelled;
- op->path_denied &= ~tmp->path_denied;
+ op->path_denied &= ~tmp->path_denied;
/* Presuming here that creatures only have move_type,
* and not the other move_ fields.
*/
- op->move_type &= ~tmp->move_type;
+ op->move_type &= ~tmp->move_type;
}
/* call fix_player since op object could have whatever attribute due
- * to multiple items. if fix_player always has to be called after
+ * to multiple items. if update_stats 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
+ /* update_stats won't add the bows ability to the player, so don't
* print out message if this is a bow.
*/
if (tmp->attacktype & AT_CONFUSION && tmp->type != BOW)
@@ -470,21 +367,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
@@ -508,9 +409,10 @@
/* double conditional - second case covers if you have move_fly_low -
* in that case, you don't actually land
*/
- DIFF_MSG (flag, "You soar into the air air!.",
+ DIFF_MSG (flag, "You soar into the air!",
(op->move_type & MOVE_FLY_LOW ? "You fly lower in the air" : "You float down to the ground."));
}
+
if (tmp->move_type & MOVE_SWIM)
DIFF_MSG (flag, "You feel ready for a swim", "You no longer feel like swimming");
@@ -521,7 +423,7 @@
/* becoming UNDEAD... a special treatment for this flag. Only those not
* originally undead may change their status
*/
- if (!QUERY_FLAG (&op->arch->clone, FLAG_UNDEAD))
+ if (!QUERY_FLAG (op->arch, FLAG_UNDEAD))
if (QUERY_FLAG (op, FLAG_UNDEAD) != QUERY_FLAG (&refop, FLAG_UNDEAD))
{
success = 1;
@@ -532,7 +434,7 @@
}
else
{
- op->race = op->arch->clone.race;
+ op->race = op->arch->race;
new_draw_info (NDI_UNIQUE, 0, op, "Your lifeforce returns!");
}
}
@@ -542,11 +444,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
*/
@@ -646,7 +550,7 @@
}
/* Messages for changed resistance */
- for (i = 0; i < NROFATTACKS; i++)
+ for (int i = 0; i < NROFATTACKS; i++)
{
if (i == ATNR_PHYSICAL)
continue; /* Don't display about armour */
@@ -663,17 +567,18 @@
}
}
- if (tmp->type != EXPERIENCE && !potion_max)
+ if (!potion_max)
{
- for (j = 0; j < NUM_STATS; j++)
+ for (int j = 0; j < NUM_STATS; j++)
{
- if ((i = get_attr_value (&(tmp->stats), j)) != 0)
+ if (int i = tmp->stats.stat (j))
{
success = 1;
DIFF_MSG (i * flag, gain_msg[j], lose_msg[j]);
}
}
}
+
return success;
}
@@ -681,20 +586,19 @@
* Stat draining by Vick 930307
* (Feeling evil, I made it work as well now. -Frank 8)
*/
-
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");
@@ -702,73 +606,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;
}
}
@@ -778,47 +681,29 @@
/*
* 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;
+ for (int i = 0; i < NUM_STATS; ++i)
+ {
+ sint8 v = arch->stats.stat (i);
+ stats.stat (i) -= v;
+ contr->orig_stats.stat (i) -= v;
+ }
}
/*
* 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;
+ for (int i = 0; i < NUM_STATS; ++i)
+ {
+ sint8 v = arch->stats.stat (i);
+ stats.stat (i) += v;
+ contr->orig_stats.stat (i) += v;
+ }
}
/*
@@ -827,94 +712,85 @@
* 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;
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, *wc_obj = NULL, *tmp;
+ object *grace_obj = NULL, *mana_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));
- }
+ stats.stat (i) = contr->orig_stats.stat (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;
-
- /* 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;
- }
- memcpy (op->body_used, op->body_info, sizeof (op->body_info));
-
- op->slaying = 0;
-
- if (!QUERY_FLAG (op, FLAG_WIZ))
- {
- CLEAR_FLAG (op, FLAG_XRAYS);
- CLEAR_FLAG (op, 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;
+ 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;
+ }
+
+ for (int i = NUM_BODY_LOCATIONS; i--; )
+ slot[i].used = slot[i].info;
+
+ slaying = 0;
+
+ if (!QUERY_FLAG (this, FLAG_WIZ))
+ {
+ CLEAR_FLAG (this, FLAG_XRAYS);
+ CLEAR_FLAG (this, FLAG_MAKE_INVIS);
+ }
+
+ CLEAR_FLAG (this, FLAG_LIFESAVE);
+ CLEAR_FLAG (this, FLAG_STEALTH);
+ CLEAR_FLAG (this, FLAG_BLIND);
+
+ if (!QUERY_FLAG (arch, FLAG_REFL_SPELL )) CLEAR_FLAG (this, FLAG_REFL_SPELL);
+ if (!QUERY_FLAG (arch, FLAG_REFL_MISSILE)) CLEAR_FLAG (this, FLAG_REFL_MISSILE);
+ if (!QUERY_FLAG (arch, FLAG_UNDEAD )) CLEAR_FLAG (this, FLAG_UNDEAD);
+ if (!QUERY_FLAG (arch, FLAG_SEE_IN_DARK )) CLEAR_FLAG (this, FLAG_SEE_IN_DARK);
+
+ path_attuned = arch->path_attuned;
+ path_repelled = arch->path_repelled;
+ path_denied = arch->path_denied;
+ glow_radius = arch->glow_radius;
+ move_type = arch->move_type;
+
+ chosen_skill = 0;
/* initializing resistances from the values in player/monster's
* archetype clone
*/
- memcpy (&op->resist, &op->arch->clone.resist, sizeof (op->resist));
+ memcpy (&resist, &arch->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->stats.wc;
+ stats.dam = arch->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. ;)
@@ -923,37 +799,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->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->stats.ac;
- op->stats.luck = op->arch->clone.stats.luck;
- op->speed = op->arch->clone.speed;
+ stats.luck = arch->stats.luck;
+ speed = arch->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;
-
/* 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;
+
+ /* 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 > glow_radius)
+ glow_radius = tmp->glow_radius;
/* For some things, we don't care what is equipped */
if (tmp->type == SKILL)
@@ -966,6 +839,7 @@
else if (tmp->level > mana_obj->level)
mana_obj = tmp;
}
+
if (IS_GRACE_SKILL (tmp->subtype))
{
if (!grace_obj)
@@ -984,56 +858,67 @@
* 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 (op->type == PLAYER)
- {
- if (tmp->type == BOW)
- op->contr->ranges[range_bow] = tmp;
-
- if (tmp->type == WAND || tmp->type == ROD || tmp->type == HORN)
- op->contr->ranges[range_misc] = tmp;
+ if ((tmp->flag [FLAG_APPLIED]
+ && tmp->type != CONTAINER
+ && tmp->type != CLOSE_CON)
+ || (tmp->type == SKILL
+ && tmp->subtype == SK_PRAYING))
+ {
+ if (type == PLAYER)
+ {
+ contr->item_power += tmp->item_power;
+
+ if (tmp == contr->combat_ob || tmp == contr->ranged_ob)
+ if (tmp != current_weapon
+ && (tmp->type != SKILL || tmp->subtype != SK_PRAYING)
+ && !tmp->flag [FLAG_CURSED]
+ && !tmp->flag [FLAG_DAMNED])
+ continue;
for (i = 0; i < NUM_STATS; i++)
- change_attr_value (&(op->stats), i, get_attr_value (&(tmp->stats), i));
+ change_attr_value (&stats, i, tmp->stats.stat (i));
- /* these are the items that currently can change digestion, regeneration,
- * spell point recovery and mana point recovery. Seems sort of an arbitary
+ /* 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;
}
} /* if this is a player */
+ else
+ {
+ if (tmp->type == WEAPON)
+ current_weapon = tmp;
+ }
/* 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++)
+ slot[i].used += tmp->slot[i].info;
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.
*/
@@ -1042,7 +927,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)
{
@@ -1052,180 +937,200 @@
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;
-
- 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);
+ if (tmp->type != SYMPTOM)
+ {
+ attacktype |= tmp->attacktype;
+ 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, 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 += tmp->stats.exp / 3.f + 1.f;
}
else
- added_speed += (float) tmp->stats.exp;
+ added_speed += tmp->stats.exp;
}
switch (tmp->type)
{
- /* skills modifying the character -b.t. */
- /* for all skills and skill granting objects */
- case SKILL:
- if (!QUERY_FLAG (tmp, FLAG_APPLIED))
- break;
+#if 0
+ case WAND:
+ case ROD:
+ case HORN:
+ if (type != PLAYER || current_weapon == tmp)
+ chosen_skill = tmp;
+ break;
+#endif
- if (IS_COMBAT_SKILL (tmp->subtype))
- wc_obj = tmp;
+ /* skills modifying the character -b.t. */
+ /* for all skills and skill granting objects */
+ case SKILL:
+ {
+ if (!QUERY_FLAG (tmp, FLAG_APPLIED) || skill_flags [tmp->subtype] & SF_APPLY)
+ break;
- if (op->chosen_skill)
+ if (chosen_skill)
{
- LOG (llevDebug, "fix_player, op %s has multiple skills applied\n", &op->name);
+ LOG (llevDebug, "fix_player, op %s has multiple skills applied (%s and %s)\n",
+ &name, &chosen_skill->name, &tmp->name);
+
+ tmp->flag [FLAG_APPLIED] = false;
+ update_stats ();
+ return;
}
- op->chosen_skill = tmp;
+ else
+ 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);
+ { /* skill is a 'weapon' */
+ 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 += 1 + chosen_skill->level * tmp->stats.dam / 9;
+
if (tmp->magic)
- op->stats.dam += tmp->magic;
+ stats.dam += tmp->magic;
}
+
if (tmp->stats.wc)
- wc -= (tmp->stats.wc + tmp->magic);
+ 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;
- break;
+ ac -= tmp->stats.ac + tmp->magic;
- 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;
- break;
-
- case SHIELD:
- if (settings.spell_encumbrance == TRUE && op->type == PLAYER)
- op->contr->encumbrance += (int) tmp->weight / 2000;
- case RING:
- case AMULET:
- case GIRDLE:
- case HELMET:
- case BOOTS:
- case GLOVES:
- case CLOAK:
- if (tmp->stats.wc)
- wc -= (tmp->stats.wc + tmp->magic);
- if (tmp->stats.dam)
- op->stats.dam += (tmp->stats.dam + tmp->magic);
- if (tmp->stats.ac)
- ac -= (tmp->stats.ac + tmp->magic);
- break;
+ if (settings.spell_encumbrance == TRUE && type == PLAYER)
+ contr->encumbrance += (int) 3 *tmp->weight / 1000;
+ }
+
+ break;
+
+ case SHIELD:
+ if (settings.spell_encumbrance == TRUE && type == PLAYER)
+ contr->encumbrance += (int) tmp->weight / 2000;
+ case RING:
+ case AMULET:
+ case GIRDLE:
+ case HELMET:
+ case BOOTS:
+ case GLOVES:
+ case CLOAK:
+ if (tmp->stats.wc)
+ wc -= tmp->stats.wc + tmp->magic;
+
+ if (tmp->stats.dam)
+ stats.dam += tmp->stats.dam + tmp->magic;
+
+ if (tmp->stats.ac)
+ ac -= tmp->stats.ac + tmp->magic;
+
+ break;
+
+ case BOW:
+ case WEAPON:
+ if (type != PLAYER || current_weapon == tmp)
+ {
+ wc -= tmp->stats.wc + tmp->magic;
+
+ if (tmp->stats.ac && tmp->stats.ac + tmp->magic > 0)
+ ac -= tmp->stats.ac + tmp->magic;
+
+ stats.dam += tmp->stats.dam + tmp->magic;
+ weapon_weight = tmp->weight;
+ weapon_speed = (WEAPON_SPEED (tmp) * 2 - tmp->magic) / 2;
+
+ if (weapon_speed < 0)
+ weapon_speed = 0;
+
+ slaying = tmp->slaying;
+
+ /* If there is desire that two handed weapons should do
+ * extra strength damage, this is where the code should
+ * go.
+ */
+
+ if (type == PLAYER)
+ if (settings.spell_encumbrance)
+ contr->encumbrance += tmp->weight * 3 / 1000;
+ }
- case WEAPON:
+ break;
+
+ case ARMOUR: /* Only the best of these three are used: */
+ if (settings.spell_encumbrance == TRUE && type == PLAYER)
+ contr->encumbrance += tmp->weight / 1000;
+
+ case BRACERS:
+ case FORCE:
+ if (tmp->stats.wc)
+ {
+ if (best_wc < tmp->stats.wc + tmp->magic)
+ {
+ wc += best_wc;
+ best_wc = tmp->stats.wc + tmp->magic;
+ }
+ else
+ wc += tmp->stats.wc + tmp->magic;
+ }
+
+ if (tmp->stats.ac)
+ {
+ if (best_ac < tmp->stats.ac + tmp->magic)
+ {
+ ac += best_ac; /* Remove last bonus */
+ best_ac = tmp->stats.ac + tmp->magic;
+ }
+ 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 && tmp->stats.ac + tmp->magic > 0)
- ac -= tmp->stats.ac + tmp->magic;
- op->stats.dam += (tmp->stats.dam + tmp->magic);
- weapon_weight = tmp->weight;
- weapon_speed = ((int) WEAPON_SPEED (tmp) * 2 - tmp->magic) / 2;
- if (weapon_speed < 0)
- weapon_speed = 0;
- op->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;
-
- 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;
- case BRACERS:
- case FORCE:
- if (tmp->stats.wc)
- {
- if (best_wc < tmp->stats.wc + tmp->magic)
- {
- wc += best_wc;
- best_wc = tmp->stats.wc + tmp->magic;
- }
- else
- wc += tmp->stats.wc + tmp->magic;
- }
- if (tmp->stats.ac)
- {
- if (best_ac < tmp->stats.ac + tmp->magic)
- {
- ac += best_ac; /* Remove last bonus */
- best_ac = tmp->stats.ac + tmp->magic;
- }
- 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;
- break;
+ if (tmp->stats.ac)
+ ac -= (tmp->stats.ac + tmp->magic);
+
+ if (ARMOUR_SPEED (tmp) && ARMOUR_SPEED (tmp) / 10.f < max)
+ max = ARMOUR_SPEED (tmp) / 10.f;
+
+ break;
} /* switch tmp->type */
} /* item is equipped */
} /* for loop of items */
@@ -1242,18 +1147,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! */
@@ -1261,78 +1167,79 @@
/* 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
@@ -1340,41 +1247,39 @@
* 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)
@@ -1387,107 +1292,99 @@
* to make up for the change. Note that I left the
* monster bonus the same as before. -b.t.
*/
+ object *wc_obj = chosen_skill;
- if (op->type == PLAYER && wc_obj && wc_obj->level > 1)
+ if (contr && 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 */
+ /* additional 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));
+
+ /* additional dam every 4 levels. */
+ 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];
- op->stats.dam += dam_bonus[op->stats.Str];
+ if (stats.dam < 1)
+ stats.dam = 1;
- if (op->stats.dam < 1)
- op->stats.dam = 1;
+ speed = 1.f + speed_bonus[stats.Dex];
- 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 (settings.search_items && contr->search_str[0])
+ speed -= 1;
+ if (attacktype == 0)
+ attacktype = arch->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 = (20 - 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.01f)
+ K = 0.01f;
+
+ contr->weapon_sp = K * s * .5f; //TODO: balance the .5
}
+
/* 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->stats.dam * 3)
+ stats.dam = arch->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,
- * so its value is the same.
- */
- if (wc > 120)
- wc = 120;
- else if (wc < -120)
- wc = -120;
- op->stats.wc = wc;
-
- if (ac > 120)
- ac = 120;
- else if (ac < -120)
- ac = -120;
- op->stats.ac = ac;
+ stats.wc = clamp (wc, MIN_WC, MAX_WC);
+ stats.ac = clamp (ac, MIN_AC, MAX_AC);
/* if for some reason the creature doesn't have any move type,
* give them walking as a default.
@@ -1495,18 +1392,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;
}
/*
@@ -1516,12 +1421,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;
}
/*
@@ -1602,16 +1511,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->archname == dragon_ability_force)
+ abil = tmp;
+ else if (tmp->arch->archname == dragon_skin_force)
+ skin = tmp;
+
/* if the force is missing -> bail out */
if (abil == NULL)
return;
@@ -1665,6 +1574,7 @@
LOG (llevError, "add_player_exp: couldn't find skill %s\n", skill_name);
return NULL;
}
+
/* clear the flag - exp goes into this bucket, but player
* still doesn't know it.
*/
@@ -1672,15 +1582,17 @@
skill_obj->stats.exp = 0;
skill_obj->level = 1;
insert_ob_in_ob (skill_obj, op);
- if (op->contr)
+
+ if (player *pl = op->contr)
{
- op->contr->last_skill_ob[skill_obj->subtype] = skill_obj;
- op->contr->last_skill_exp[skill_obj->subtype] = -1;
+ pl->last_skill_ob [skill_obj->subtype] = skill_obj;
+ if (pl->ns)
+ pl->ns->last_skill_exp[skill_obj->subtype] = -1;//TODO: should be made superfluous
}
+
return skill_obj;
}
-
/* player_lvl_adj() - for the new exp system. we are concerned with
* whether the player gets more hp, sp and new levels.
* Note this this function should only be called for players. Monstes
@@ -1700,7 +1612,7 @@
{
op->level++;
- if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl (who))
+ if (op && op == who && op->stats.exp > 1 && is_dragon_pl (who))
dragon_level_gain (who);
/* Only roll these if it is the player (who) that gained the level */
@@ -1711,30 +1623,36 @@
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)
sprintf (buf, "You are now level %d in the %s skill.", op->level, &op->name);
else
sprintf (buf, "You are now level %d.", op->level);
+
if (who)
new_draw_info (NDI_UNIQUE | NDI_RED, 0, who, buf);
}
+
player_lvl_adj (who, op); /* To increase more levels */
}
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);
new_draw_info (NDI_UNIQUE | NDI_RED, 0, who, buf);
}
+
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);
}
@@ -1748,6 +1666,7 @@
{
if (level > settings.max_level)
return (sint64) (expmul * levels[settings.max_level]);
+
return (sint64) (expmul * levels[level]);
}
@@ -1778,7 +1697,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
@@ -1786,7 +1704,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)
{
@@ -1796,11 +1713,11 @@
/* prevents some forms of abuse. */
if (op->contr->braced)
- exp = exp / 5;
+ exp /= 5;
/* Try to find the matching skill.
* We do a shortcut/time saving mechanism first - see if it matches
- * chosen_skill. This means we don't need to search through
+ * chosen_skill. This means we don't need to search through
* the players inventory.
*/
if (skill_name)
@@ -1941,6 +1858,7 @@
player_lvl_adj (op, tmp);
}
}
+
if (flag != SK_SUBTRACT_SKILL_EXP)
{
del_exp = check_exp_loss (op, exp);
@@ -1949,8 +1867,6 @@
}
}
-
-
/* change_exp() - changes experience to a player/monster. This
* does bounds checking to make sure we don't overflow the max exp.
*
@@ -1960,17 +1876,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 */
@@ -2019,8 +1929,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);
}
}
@@ -2028,7 +1937,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)
{
@@ -2060,6 +1968,7 @@
percentage_loss = op->stats.exp * settings.death_penalty_ratio / 100;
level_loss = op->stats.exp - levels[MAX (0, op->level - settings.death_penalty_level)];
+
if (level_loss < 0)
level_loss = 0;
loss = check_exp_loss (op, MIN (level_loss, percentage_loss));
@@ -2083,5 +1992,6 @@
if ((random_roll (1, 20, op, PREFER_HIGH) + bonus) < savethrow[level])
return 0;
+
return 1;
}