--- deliantra/server/common/living.C 2007/01/08 20:39:48 1.27 +++ deliantra/server/common/living.C 2007/04/29 18:11:39 1.41 @@ -1,26 +1,26 @@ /* - CrossFire, A Multiplayer game for X-windows - - 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 -*/ + * 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 @@ -195,7 +195,7 @@ "You feel less healthy", "You suddenly begin to lose your memory!", "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] = { @@ -204,7 +204,7 @@ "You feel your health return.", "You feel your memory return.", "You feel your wisdom return.", - "You feel your spirits return." + "You feel your spirits return.", "You feel your charisma return.", }; const char *const gain_msg[NUM_STATS] = { @@ -213,7 +213,7 @@ "You feel healthy.", "You feel smarter.", "You feel wiser.", - "You feel more potent." + "You feel more potent.", "You seem to look better.", }; const char *const lose_msg[NUM_STATS] = { @@ -222,7 +222,7 @@ "You feel less healthy!", "You feel stupid!", "You lose some of your memory!", - "You feel less potent!" + "You feel less potent!", "You look ugly!", }; @@ -679,7 +679,7 @@ void object::drain_stat () { - drain_specific_stat (RANDOM () % NUM_STATS); + drain_specific_stat (rndm (NUM_STATS)); } void @@ -757,7 +757,7 @@ /* 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; @@ -820,12 +820,10 @@ * 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 object::update_stats () { @@ -847,21 +845,22 @@ contr->encumbrance = 0; attacktype = 0; - contr->digestion = 0; - contr->gen_hp = 0; - contr->gen_sp = 0; - contr->gen_grace = 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; + 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. */ - contr->ranges[range_bow] = NULL; - contr->ranges[range_misc] = NULL; - contr->ranges[range_skill] = NULL; + contr->ranges[range_bow] = 0; + contr->ranges[range_misc] = 0; + contr->ranges[range_skill] = 0; } memcpy (body_used, body_info, sizeof (body_info)); @@ -883,11 +882,12 @@ 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_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; + 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 @@ -928,7 +928,6 @@ /* 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 = inv; tmp; tmp = tmp->below) { /* See note in map.c:update_position about making this additive @@ -938,7 +937,7 @@ 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) @@ -974,8 +973,11 @@ * 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 (type == PLAYER) { @@ -986,13 +988,13 @@ contr->ranges[range_misc] = tmp; for (i = 0; i < NUM_STATS; i++) - change_attr_value (&(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 == WEAPON) || + 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) || @@ -1017,13 +1019,14 @@ 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,21 +1045,21 @@ 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) + if (tmp->type != SYMPTOM) attacktype |= tmp->attacktype; - path_attuned |= tmp->path_attuned; + path_attuned |= tmp->path_attuned; path_repelled |= tmp->path_repelled; - path_denied |= tmp->path_denied; - stats.luck += tmp->stats.luck; - move_type |= tmp->move_type; + 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); @@ -1079,11 +1082,11 @@ { 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) @@ -1105,7 +1108,7 @@ if (tmp->stats.dam > 0) { /* skill is a 'weapon' */ if (!QUERY_FLAG (this, FLAG_READY_WEAPON)) - weapon_speed = (int) WEAPON_SPEED (tmp); + weapon_speed = WEAPON_SPEED (tmp); if (weapon_speed < 0) weapon_speed = 0; @@ -1155,23 +1158,24 @@ case GLOVES: case CLOAK: if (tmp->stats.wc) - wc -= (tmp->stats.wc + tmp->magic); + wc -= tmp->stats.wc + tmp->magic; if (tmp->stats.dam) - 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 BOW: 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; - 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; @@ -1179,19 +1183,21 @@ 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. */ + current_weapon = tmp; - if (settings.spell_encumbrance == TRUE && type == PLAYER) - contr->encumbrance += (int) 3 *tmp->weight / 1000; + 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 && type == PLAYER) - contr->encumbrance += (int) tmp->weight / 1000; + contr->encumbrance += tmp->weight / 1000; case BRACERS: case FORCE: @@ -1223,8 +1229,8 @@ 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 */ @@ -1302,7 +1308,7 @@ stats.maxsp = 1; else { - sp_tmp = 0.0; + sp_tmp = 0.f; for (i = 1; i <= mana_obj->level && i <= 10; i++) { @@ -1310,17 +1316,17 @@ /* Got some extra bonus at first level */ if (i < 2) - stmp = contr->levsp[i] + ((2.0 * (float) sp_bonus[stats.Pow] + (float) sp_bonus[stats.Int]) / 6.0); + stmp = contr->levsp[i] + (2.f * sp_bonus[stats.Pow] + sp_bonus[stats.Int]) / 6.f; else - stmp = (float) contr->levsp[i] + (2.0 * (float) sp_bonus[stats.Pow] + (float) sp_bonus[stats.Int]) / 12.0; + stmp = contr->levsp[i] + (2.f * sp_bonus[stats.Pow] + sp_bonus[stats.Int]) / 12.f; - if (stmp < 1.0) - stmp = 1.0; + if (stmp < 1.f) + stmp = 1.f; sp_tmp += stmp; } - stats.maxsp = (int) sp_tmp; + stats.maxsp = (sint16)sp_tmp; for (i = 11; i <= mana_obj->level; i++) stats.maxsp += 2; @@ -1342,26 +1348,24 @@ * 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; + 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 = contr->levgrace[i] + (((float) grace_bonus[stats.Pow] + - 2.0 * (float) grace_bonus[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) contr->levgrace[i] - + ((float) grace_bonus[stats.Pow] + 2.0 * (float) grace_bonus[stats.Wis]) / 12.0; + grace_tmp = contr->levgrace[i] + (grace_bonus[stats.Pow] + 2.f * grace_bonus[stats.Wis]) / 12.f; - if (grace_tmp < 1.0) - grace_tmp = 1.0; + if (grace_tmp < 1.f) + grace_tmp = 1.f; sp_tmp += grace_tmp; } - 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++) @@ -1391,26 +1395,28 @@ if (type == PLAYER && wc_obj && wc_obj->level > 1) { - wc -= (wc_obj->level + thaco_bonus[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[stats.Str] >= 0)) - stats.dam += (1 + (dam_bonus[stats.Str] / 5)); + if (!(i % 4) && dam_bonus[stats.Str] >= 0) + stats.dam += 1 + dam_bonus[stats.Str] / 5; } } else - wc -= (level + thaco_bonus[stats.Str]); + wc -= level + thaco_bonus[stats.Str]; stats.dam += dam_bonus[stats.Str]; if (stats.dam < 1) stats.dam = 1; - speed = 1.0 + speed_bonus[stats.Dex]; + speed = 1.f + speed_bonus[stats.Dex]; if (settings.search_items && contr->search_str[0]) speed -= 1; @@ -1421,9 +1427,9 @@ } /* End if player */ if (added_speed >= 0) - speed += added_speed / 10.0; + speed += added_speed / 10.f; else /* Something wrong here...: */ - speed /= (float) (1.0 - added_speed); + speed /= 1.f - added_speed; /* Max is determined by armour */ if (speed > max) @@ -1438,43 +1444,45 @@ */ f = (carrying / 1000) - max_carry[stats.Str]; if (f > 0) - speed = speed / (1.0 + f / max_carry[stats.Str]); + speed = speed / (1.f + f / max_carry[stats.Str]); } - 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. */ speed = speed * speed_reduce_from_disease; - if (speed < 0.01 && type == PLAYER) - speed = 0.01; + if (speed < 0.01f && type == PLAYER) + speed = 0.01f; 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[stats.Str] - 121) / 121.0; - M2 = max_carry[stats.Str] / 100.0; - W = weapon_weight / 20000.0; - s = 2 - weapon_speed / 10.0; - D = (stats.Dex - 14) / 14.0; - K = 1 + M / 3.0 - W / (3 * M2) + speed / 5.0 + D / 2.0; - K *= (4 + level) / (float) (6 + level) * 1.2; - if (K <= 0) - K = 0.01; - S = speed / (K * 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 (type != PLAYER && arch != NULL && stats.dam > 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 @@ -1517,6 +1525,10 @@ 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; } /* @@ -1529,8 +1541,13 @@ 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; } /* @@ -1611,16 +1628,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; @@ -1762,6 +1779,7 @@ { if (level > settings.max_level) return (sint64) (expmul * levels[settings.max_level]); + return (sint64) (expmul * levels[level]); } @@ -1953,6 +1971,7 @@ player_lvl_adj (op, tmp); } } + if (flag != SK_SUBTRACT_SKILL_EXP) { del_exp = check_exp_loss (op, exp); @@ -1961,8 +1980,6 @@ } } - - /* change_exp() - changes experience to a player/monster. This * does bounds checking to make sure we don't overflow the max exp. * @@ -1972,11 +1989,9 @@ * 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 LOG (llevDebug, "change_exp() called for %s, exp = %" PRId64 "\n", query_name (op), exp); #endif @@ -2027,8 +2042,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); } } @@ -2036,7 +2050,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) {