--- deliantra/server/common/living.C 2007/08/07 22:57:57 1.76 +++ deliantra/server/common/living.C 2008/12/04 03:48:19 1.92 @@ -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 @@ -282,21 +281,24 @@ int change_abil (object *op, object *tmp) { - int flag = QUERY_FLAG (tmp, FLAG_APPLIED) ? 1 : -1, success = 0; + int flag = tmp->flag [FLAG_APPLIED] ? 1 : -1; + int 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 update_stats. refop is not a real object - */ - object_copy refop = *op; + // keep some stats for comparison purposes + 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) { if (tmp->type == POTION) { potion_max = 1; + for (int j = 0; j < NUM_STATS; j++) { int ostat = op->contr->orig_stats.stat (j); @@ -305,8 +307,7 @@ /* nstat is what the stat will be after use of the potion */ 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 + /* Do some bounds checking. There is the potential for potions * that adjust that stat by more than one point, so we need * to allow for that. */ @@ -368,19 +369,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 +393,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; @@ -401,7 +402,7 @@ */ if (tmp->move_type & MOVE_FLY_LOW && !(op->move_type & MOVE_FLY_HIGH)) { - DIFF_MSG (flag, "You start to float in the air!.", "You float down to the ground."); + DIFF_MSG (flag, "You start to float in the air!", "You float down to the ground."); } if (tmp->move_type & MOVE_FLY_HIGH) @@ -423,8 +424,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 +440,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 +455,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 +472,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 +484,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 +492,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 +508,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,29 +556,26 @@ 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); } } if (!potion_max) - { - for (int j = 0; j < NUM_STATS; j++) + for (int j = 0; j < NUM_STATS; j++) + if (int i = tmp->stats.stat (j)) { - if (int i = tmp->stats.stat (j)) - { - success = 1; - DIFF_MSG (i * flag, gain_msg[j], lose_msg[j]); - } + success = 1; + DIFF_MSG (i * flag, gain_msg[j], lose_msg[j]); } - } return success; } @@ -865,8 +863,7 @@ /* 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; + glow_radius = max (glow_radius, tmp->glow_radius); /* For some things, we don't care what is equipped */ if (tmp->type == SKILL) @@ -889,7 +886,7 @@ } } - /* Container objects are not meant to adjust a players, but other applied + /* Container objects are not meant to adjust players, but other applied * objects need to make adjustments. * This block should handle all player specific changes * The check for Praying is a bit of a hack - god given bonuses are put @@ -922,7 +919,8 @@ { contr->digestion += tmp->stats.food; contr->gen_hp += tmp->stats.hp; - contr->gen_sp += tmp->stats.sp; + if (tmp->type != BOW) // ugly exception for bows + contr->gen_sp += tmp->stats.sp; contr->gen_grace += tmp->stats.grace; contr->gen_sp_armour += tmp->gen_sp_armour; } @@ -939,14 +937,10 @@ slot[i].used += tmp->slot[i].info; if (tmp->type == SYMPTOM) - { - speed_reduce_from_disease = tmp->last_sp / 100.f; + speed_reduce_from_disease = + min (speed_reduce_from_disease, tmp->last_sp ? tmp->last_sp / 100.f : 1.f); - if (speed_reduce_from_disease == 0) - speed_reduce_from_disease = 1; - } - - /* Pos. and neg. protections are counted seperate (-> pro/vuln). + /* Pos. and neg. protections are counted separate (-> pro/vuln). * (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. @@ -1356,20 +1350,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) { @@ -1411,9 +1407,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. */ @@ -1451,11 +1444,6 @@ * set the new dragon name after gaining levels or * changing ability focus (later this can be extended to * eventually change the player's face and animation) - * - * Note that the title is written to 'own_title' in the - * player struct. This should be changed to 'ext_title' - * as soon as clients support this! - * Please, anyone, write support for 'ext_title'. */ void set_dragon_name (object *pl, const object *abil, const object *skin) @@ -1483,29 +1471,17 @@ if (atnr_is_dragon_enabled (abil->stats.exp) && abil->resist[abil->stats.exp] >= level) atnr = abil->stats.exp; - level = (int) (level / 5.); - /* now set the new title */ - if (pl->contr != NULL) + if (level < 25) sprintf (pl->contr->title, "%s hatchling", attacks[atnr]); + else if (level < 50) sprintf (pl->contr->title, "%s wyrm" , attacks[atnr]); + else if (level < 75) sprintf (pl->contr->title, "%s wyvern" , attacks[atnr]); + else if (level < 100) sprintf (pl->contr->title, "%s dragon" , attacks[atnr]); + else { - if (level == 0) - sprintf (pl->contr->title, "%s hatchling", attacks[atnr]); - else if (level == 1) - sprintf (pl->contr->title, "%s wyrm", attacks[atnr]); - else if (level == 2) - sprintf (pl->contr->title, "%s wyvern", attacks[atnr]); - else if (level == 3) - sprintf (pl->contr->title, "%s dragon", attacks[atnr]); - else - { - /* special titles for extra high resistance! */ - if (skin->resist[atnr] > 80) - sprintf (pl->contr->title, "legendary %s dragon", attacks[atnr]); - else if (skin->resist[atnr] > 50) - sprintf (pl->contr->title, "ancient %s dragon", attacks[atnr]); - else - sprintf (pl->contr->title, "big %s dragon", attacks[atnr]); - } + /* special titles for extra high resistance! */ + if (skin->resist[atnr] > 80) sprintf (pl->contr->title, "legendary %s dragon", attacks[atnr]); + else if (skin->resist[atnr] > 50) sprintf (pl->contr->title, "ancient %s dragon" , attacks[atnr]); + else sprintf (pl->contr->title, "big %s dragon" , attacks[atnr]); } strcpy (pl->contr->own_title, ""); @@ -1582,7 +1558,7 @@ skill_obj = get_archetype_by_skill_name (skill_name, SKILL); if (!skill_obj) { - LOG (llevError, "add_player_exp: couldn't find skill %s\n", skill_name); + LOG (llevError, "give_skill_by_name: couldn't find skill %s\n", skill_name); return NULL; } @@ -1592,14 +1568,10 @@ CLEAR_FLAG (skill_obj, FLAG_CAN_USE_SKILL); skill_obj->stats.exp = 0; skill_obj->level = 1; - insert_ob_in_ob (skill_obj, op); + op->insert (skill_obj); if (player *pl = op->contr) - { - 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 - } + pl->link_skills (); return skill_obj; } @@ -1728,7 +1700,7 @@ static void add_player_exp (object *op, sint64 exp, const char *skill_name, int flag) { - object *skill_obj = NULL; + object *skill_obj; sint64 limit, exp_to_add; int i; @@ -1741,29 +1713,22 @@ * chosen_skill. This means we don't need to search through * the players inventory. */ + skill_obj = 0; + if (skill_name) { - if (op->chosen_skill && op->chosen_skill->type == SKILL && !strcmp (skill_name, op->chosen_skill->skill)) - skill_obj = op->chosen_skill; - else + skill_obj = op->contr->find_skill (skill_name); + + /* Player doesn't have the skill. Check to see what to do, and give + * it to the player if necessary + */ + if (!skill_obj) { - for (i = 0; i < NUM_SKILLS; i++) - if (op->contr->last_skill_ob[i] && !strcmp (op->contr->last_skill_ob[i]->skill, skill_name)) - { - skill_obj = op->contr->last_skill_ob[i]; - break; - } + if (flag == SK_EXP_NONE) + return; - /* Player doesn't have the skill. Check to see what to do, and give - * it to the player if necessary - */ - if (!skill_obj) - { - if (flag == SK_EXP_NONE) - return; - else if (flag == SK_EXP_ADD_SKILL) - give_skill_by_name (op, skill_name); - } + if (flag == SK_EXP_ADD_SKILL) + skill_obj = give_skill_by_name (op, skill_name); } } @@ -1840,7 +1805,6 @@ return MIN (exp, (sint64) MAX_EXPERIENCE - op->stats.exp); } - /* Subtracts experience from player. * if skill is set and flag == SK_SUBTRACT_SKILL_EXP, then we * only subtract from the matching skill. Otherwise, @@ -1863,7 +1827,7 @@ for (tmp = op->inv; tmp; tmp = tmp->below) if (tmp->type == SKILL && tmp->stats.exp) { - if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp (tmp->skill, skill)) + if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp (&tmp->skill, skill)) { del_exp = check_exp_loss (tmp, exp); tmp->stats.exp -= del_exp;