--- deliantra/server/common/living.C 2006/08/26 23:36:28 1.2 +++ deliantra/server/common/living.C 2006/08/29 08:01:35 1.3 @@ -1,6 +1,6 @@ /* * static char *rcsid_living_c = - * "$Id: living.C,v 1.2 2006/08/26 23:36:28 root Exp $"; + * "$Id: living.C,v 1.3 2006/08/29 08:01:35 root Exp $"; */ /* @@ -215,22 +215,22 @@ "You feel your spirits return." }; const char *const gain_msg[NUM_STATS] = { - "You feel stronger.", - "You feel more agile.", - "You feel healthy.", - "You feel wiser.", - "You seem to look better.", - "You feel smarter.", - "You feel more potent." + "You feel stronger.", + "You feel more agile.", + "You feel healthy.", + "You feel wiser.", + "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 lose some of your memory!", - "You look ugly!", - "You feel stupid!", - "You feel less potent!" + "You feel weaker!", + "You feel clumsy!", + "You feel less healthy!", + "You lose some of your memory!", + "You look ugly!", + "You feel stupid!", + "You feel less potent!" }; const char *const statname[NUM_STATS] = { @@ -304,7 +304,7 @@ stats->Int+=value; break; default: - LOG(llevError,"Invalid attribute in change_attr_value: %d\n", attr); + LOG(llevError,"Invalid attribute in change_attr_value: %d\n", attr); } } @@ -381,57 +381,57 @@ memcpy(&refop, op, sizeof(object)); if(op->type==PLAYER) { - if (tmp->type==POTION) { - potion_max=1; - for(j=0;jcontr->orig_stats),j); - i = get_attr_value(&(tmp->stats),j); - - /* nstat is what the stat will be after use of the potion */ - 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 - * that adjust that stat by more than one point, so we need - * to allow for that. - */ - 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); - } - if (nstat != ostat) { - set_attr_value(&(op->contr->orig_stats), j, nstat); - potion_max=0; - } - else if (i) { - /* potion is useless - player has already hit the natural maximum */ - 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;jstats),j,flag*get_attr_value(&(tmp->stats),j)); - check_stat_bounds(&(op->stats)); - } /* end of potion handling code */ + if (tmp->type==POTION) { + potion_max=1; + for(j=0;jcontr->orig_stats),j); + i = get_attr_value(&(tmp->stats),j); + + /* nstat is what the stat will be after use of the potion */ + 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 + * that adjust that stat by more than one point, so we need + * to allow for that. + */ + 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); + } + if (nstat != ostat) { + set_attr_value(&(op->contr->orig_stats), j, nstat); + potion_max=0; + } + else if (i) { + /* potion is useless - player has already hit the natural maximum */ + 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;jstats),j,flag*get_attr_value(&(tmp->stats),j)); + check_stat_bounds(&(op->stats)); + } /* end of potion handling code */ } /* reset attributes that fix_player 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->path_repelled&=~tmp->path_repelled; - 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->attacktype&=~tmp->attacktype; + op->path_attuned&=~tmp->path_attuned; + op->path_repelled&=~tmp->path_repelled; + 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; } /* call fix_player since op object could have whatever attribute due @@ -444,24 +444,24 @@ * print out message if this is a bow. */ if(tmp->attacktype & AT_CONFUSION && tmp->type != BOW) { - success=1; - DIFF_MSG(flag, "Your hands begin to glow red.", - "Your hands stop glowing red."); + 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."); + 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."); + 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."); + 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 @@ -470,166 +470,166 @@ * from fly high) */ if (tmp->move_type && op->move_type != refop.move_type) { - success=1; + success=1; - /* MOVE_FLY_HIGH trumps MOVE_FLY_LOW - changing your move_fly_low - * status doesn't make a difference if you are flying high - */ - 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."); - } - - if (tmp->move_type & MOVE_FLY_HIGH) { - /* 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!.", - (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"); + /* MOVE_FLY_HIGH trumps MOVE_FLY_LOW - changing your move_fly_low + * status doesn't make a difference if you are flying high + */ + 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."); + } + + if (tmp->move_type & MOVE_FLY_HIGH) { + /* 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!.", + (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"); - /* Changing move status may mean you are affected by things you weren't before */ - check_move_on(op, op); + /* Changing move status may mean you are affected by things you weren't before */ + check_move_on(op, op); } /* 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,FLAG_UNDEAD) != QUERY_FLAG(&refop,FLAG_UNDEAD)) { - success=1; - if(flag>0) { - if(op->race) free_string(op->race); - op->race=add_string("undead"); - new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce drains away!"); - } else { - if(op->race) free_string(op->race); - if(op->arch->clone.race) - op->race=add_string(op->arch->clone.race); - else - op->race = NULL; - new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce returns!"); - } - } + if ( QUERY_FLAG(op,FLAG_UNDEAD) != QUERY_FLAG(&refop,FLAG_UNDEAD)) { + success=1; + if(flag>0) { + if(op->race) free_string(op->race); + op->race=add_string("undead"); + new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce drains away!"); + } else { + if(op->race) free_string(op->race); + if(op->arch->clone.race) + op->race=add_string(op->arch->clone.race); + else + op->race = NULL; + new_draw_info(NDI_UNIQUE, 0, op,"Your lifeforce returns!"); + } + } if ( QUERY_FLAG(op,FLAG_STEALTH) != QUERY_FLAG(&refop,FLAG_STEALTH)){ - success=1; - DIFF_MSG(flag, "You walk more quietly.", "You walk more noisily."); + 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."); + 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 */ if(QUERY_FLAG(tmp,FLAG_BLIND)) { - success=1; - if(flag>0) { - if(QUERY_FLAG(op,FLAG_WIZ)) - new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self is blinded."); - else { - new_draw_info(NDI_UNIQUE, 0, op,"You are blinded."); - SET_FLAG(op,FLAG_BLIND); - if(op->type==PLAYER) - op->contr->do_los=1; - } - } else { - if(QUERY_FLAG(op,FLAG_WIZ)) - new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self can now see again."); - else { - new_draw_info(NDI_UNIQUE, 0, op,"Your vision returns."); - CLEAR_FLAG(op,FLAG_BLIND); - if(op->type==PLAYER) - op->contr->do_los=1; - } - } + success=1; + if(flag>0) { + if(QUERY_FLAG(op,FLAG_WIZ)) + new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self is blinded."); + else { + new_draw_info(NDI_UNIQUE, 0, op,"You are blinded."); + SET_FLAG(op,FLAG_BLIND); + if(op->type==PLAYER) + op->contr->do_los=1; + } + } else { + if(QUERY_FLAG(op,FLAG_WIZ)) + new_draw_info(NDI_UNIQUE, 0, op,"Your mortal self can now see again."); + else { + new_draw_info(NDI_UNIQUE, 0, op,"Your vision returns."); + CLEAR_FLAG(op,FLAG_BLIND); + if(op->type==PLAYER) + op->contr->do_los=1; + } + } } if ( QUERY_FLAG(op,FLAG_SEE_IN_DARK) != QUERY_FLAG(&refop,FLAG_SEE_IN_DARK)){ - success=1; + success=1; if(op->type==PLAYER) - op->contr->do_los=1; - DIFF_MSG(flag, "Your vision is better in the dark.", "You see less well in the dark."); + op->contr->do_los=1; + 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)){ - success=1; - if(flag>0) { - if(QUERY_FLAG(op,FLAG_WIZ)) - new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a little clearer."); - else { - new_draw_info(NDI_UNIQUE, 0, op,"Everything becomes transparent."); - if(op->type==PLAYER) - op->contr->do_los=1; - } - } else { - if(QUERY_FLAG(op,FLAG_WIZ)) - new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a bit out of focus."); - else { - new_draw_info(NDI_UNIQUE, 0, op,"Everything suddenly looks very solid."); - if(op->type==PLAYER) - op->contr->do_los=1; - } - } + success=1; + if(flag>0) { + if(QUERY_FLAG(op,FLAG_WIZ)) + new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a little clearer."); + else { + new_draw_info(NDI_UNIQUE, 0, op,"Everything becomes transparent."); + if(op->type==PLAYER) + op->contr->do_los=1; + } + } else { + if(QUERY_FLAG(op,FLAG_WIZ)) + new_draw_info(NDI_UNIQUE, 0, op,"Your vision becomes a bit out of focus."); + else { + new_draw_info(NDI_UNIQUE, 0, op,"Everything suddenly looks very solid."); + if(op->type==PLAYER) + op->contr->do_los=1; + } + } } if(tmp->stats.luck) { - success=1; - DIFF_MSG(flag*tmp->stats.luck, "You feel more lucky.", "You feel less lucky."); + success=1; + DIFF_MSG(flag*tmp->stats.luck, "You feel more lucky.", "You feel less lucky."); } if(tmp->stats.hp && op->type==PLAYER) { - success=1; - DIFF_MSG(flag*tmp->stats.hp, "You feel much more healthy!", - "You feel much less healthy!"); + success=1; + DIFF_MSG(flag*tmp->stats.hp, "You feel much more healthy!", + "You feel much less healthy!"); } if(tmp->stats.sp && op->type==PLAYER && tmp->type!=SKILL) { - success=1; - DIFF_MSG(flag*tmp->stats.sp, "You feel one with the powers of magic!", - "You suddenly feel very mundane."); + success=1; + DIFF_MSG(flag*tmp->stats.sp, "You feel one with the powers of magic!", + "You suddenly feel very mundane."); } /* for the future when artifacts set this -b.t. */ if(tmp->stats.grace && op->type==PLAYER) { - success=1; - DIFF_MSG(flag*tmp->stats.grace, "You feel closer to your god!", - "You suddenly feel less holy."); + success=1; + DIFF_MSG(flag*tmp->stats.grace, "You feel closer to your god!", + "You suddenly feel less holy."); } if(tmp->stats.food && op->type==PLAYER) { - success=1; - DIFF_MSG(flag*tmp->stats.food, "You feel your digestion slowing down.", - "You feel your digestion speeding up."); + success=1; + DIFF_MSG(flag*tmp->stats.food, "You feel your digestion slowing down.", + "You feel your digestion speeding up."); } /* Messages for changed resistance */ for (i=0; iresist[i] != refop.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]); - else - sprintf(message, "Your resistance to %s drops to %d%%.", - change_resist_msg[i], op->resist[i]); + if (op->resist[i] != refop.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]); + else + 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); - } + new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, op, message); + } } if(tmp->type!=EXPERIENCE && !potion_max) { - for (j=0; jstats),j))!=0) { - success=1; - DIFF_MSG(i * flag, gain_msg[j], lose_msg[j]); - } - } + for (j=0; jstats),j))!=0) { + success=1; + DIFF_MSG(i * flag, gain_msg[j], lose_msg[j]); + } + } } return success; } @@ -695,7 +695,7 @@ new_luck = tmp->stats.luck+value; if (new_luck >= -100 && new_luck <= 100) { op->stats.luck+=value; - tmp->stats.luck = new_luck; + tmp->stats.luck = new_luck; } } else { if (!tmp->stats.luck) { @@ -777,51 +777,51 @@ /* First task is to clear all the values back to their original values */ if(op->type==PLAYER) { - for(i=0;istats),i,get_attr_value(&(op->contr->orig_stats),i)); - } - if (settings.spell_encumbrance == TRUE) - op->contr->encumbrance=0; + for(i=0;istats),i,get_attr_value(&(op->contr->orig_stats),i)); + } + if (settings.spell_encumbrance == TRUE) + op->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; + 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)); if(op->slaying!=NULL) { - free_string(op->slaying); - op->slaying=NULL; + free_string(op->slaying); + op->slaying=NULL; } if(!QUERY_FLAG(op,FLAG_WIZ)) { - CLEAR_FLAG(op, FLAG_XRAYS); - CLEAR_FLAG(op, FLAG_MAKE_INVIS); + 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); + CLEAR_FLAG(op,FLAG_REFL_SPELL); if ( ! QUERY_FLAG (&op->arch->clone, FLAG_REFL_MISSILE)) - CLEAR_FLAG(op,FLAG_REFL_MISSILE); + CLEAR_FLAG(op,FLAG_REFL_MISSILE); if(!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD)) - CLEAR_FLAG(op,FLAG_UNDEAD); + CLEAR_FLAG(op,FLAG_UNDEAD); if ( ! QUERY_FLAG (&op->arch->clone, FLAG_SEE_IN_DARK)) - CLEAR_FLAG(op,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; @@ -836,11 +836,11 @@ memcpy(&op->resist, &op->arch->clone.resist, sizeof(op->resist)); for (i=0;iresist[i] > 0) - prot[i]= op->resist[i], vuln[i]=0; - else - vuln[i]= -(op->resist[i]), prot[i]=0; - potion_resist[i]=0; + if (op->resist[i] > 0) + prot[i]= op->resist[i], vuln[i]=0; + else + vuln[i]= -(op->resist[i]), prot[i]=0; + potion_resist[i]=0; } wc=op->arch->clone.stats.wc; @@ -854,11 +854,11 @@ * that their protection from physical goes down */ if(!QUERY_FLAG(op,FLAG_USE_ARMOUR) && op->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,op->arch->clone.stats.ac - op->level/3); + prot[ATNR_PHYSICAL] += ((100-prot[AT_PHYSICAL])*(80*op->level/settings.max_level))/100; } else - ac=op->arch->clone.stats.ac; + ac=op->arch->clone.stats.ac; op->stats.luck=op->arch->clone.stats.luck; op->speed = op->arch->clone.speed; @@ -868,256 +868,256 @@ */ for(tmp=op->inv;tmp!=NULL;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 - * then calls this function. - */ - if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == POTION) { - continue; - } - - /* For some things, we don't care what is equipped */ - if (tmp->type == SKILL) { - /* Want to take the highest skill here. */ - if (IS_MANA_SKILL(tmp->subtype)) { - if (!mana_obj) mana_obj=tmp; - else if (tmp->level > mana_obj->level) mana_obj = tmp; - } - if (IS_GRACE_SKILL(tmp->subtype)) { - if (!grace_obj) grace_obj=tmp; - else if (tmp->level > grace_obj->level) grace_obj = tmp; - } - } - - /* Container objects are not meant to adjust a 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 - * in the praying skill, and the player should always get those. - * It also means we need to put in additional checks for applied below, - * 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; - - for(i=0;istats),i,get_attr_value(&(tmp->stats),i)); - - /* these are the items that currently can change digestion, regeneration, - * spell point recovery and mana point recovery. Seems sort of an arbitary - * list, but other items store other info into stats array. - */ - if ((tmp->type == EXPERIENCE) || (tmp->type == WEAPON) || - (tmp->type == ARMOUR) || (tmp->type == HELMET) || - (tmp->type == SHIELD) || (tmp->type == RING) || - (tmp->type == BOOTS) || (tmp->type == GLOVES) || - (tmp->type == AMULET ) || (tmp->type == GIRDLE) || - (tmp->type == BRACERS ) || (tmp->type == CLOAK) || - (tmp->type == DISEASE) || (tmp->type == FORCE) || - (tmp->type == SKILL)) { - 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; - } - } /* if this is a player */ - - /* Update slots used for items */ - if (QUERY_FLAG(tmp,FLAG_APPLIED)) { - for (i=0; ibody_used[i] += tmp->body_info[i]; - } - - if(tmp->type==SYMPTOM) { - speed_reduce_from_disease = tmp->last_sp / 100.0; - 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.) - * Resistance from potions are treated special as well. If there's - * more than one potion-effect, the bigger prot.-value is taken. - */ - if (tmp->type != POTION) { - for (i=0; itype==POTION_EFFECT) { - if (potion_resist[i]) - potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]); - else - potion_resist[i] = tmp->resist[i]; - } - else if (tmp->resist[i] > 0) - prot[i] += ((100-prot[i])*tmp->resist[i])/100; - else if (tmp->resist[i] < 0) - 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(QUERY_FLAG(tmp,FLAG_UNDEAD)&&!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD)) - SET_FLAG(op,FLAG_UNDEAD); - - if(QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) { - SET_FLAG(op,FLAG_MAKE_INVIS); - op->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; - } else - added_speed+=(float)tmp->stats.exp; - } + /* 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 + * then calls this function. + */ + if (QUERY_FLAG(tmp, FLAG_APPLIED) && tmp->type == POTION) { + continue; + } + + /* For some things, we don't care what is equipped */ + if (tmp->type == SKILL) { + /* Want to take the highest skill here. */ + if (IS_MANA_SKILL(tmp->subtype)) { + if (!mana_obj) mana_obj=tmp; + else if (tmp->level > mana_obj->level) mana_obj = tmp; + } + if (IS_GRACE_SKILL(tmp->subtype)) { + if (!grace_obj) grace_obj=tmp; + else if (tmp->level > grace_obj->level) grace_obj = tmp; + } + } + + /* Container objects are not meant to adjust a 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 + * in the praying skill, and the player should always get those. + * It also means we need to put in additional checks for applied below, + * 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; + + for(i=0;istats),i,get_attr_value(&(tmp->stats),i)); + + /* these are the items that currently can change digestion, regeneration, + * spell point recovery and mana point recovery. Seems sort of an arbitary + * list, but other items store other info into stats array. + */ + if ((tmp->type == EXPERIENCE) || (tmp->type == WEAPON) || + (tmp->type == ARMOUR) || (tmp->type == HELMET) || + (tmp->type == SHIELD) || (tmp->type == RING) || + (tmp->type == BOOTS) || (tmp->type == GLOVES) || + (tmp->type == AMULET ) || (tmp->type == GIRDLE) || + (tmp->type == BRACERS ) || (tmp->type == CLOAK) || + (tmp->type == DISEASE) || (tmp->type == FORCE) || + (tmp->type == SKILL)) { + 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; + } + } /* if this is a player */ + + /* Update slots used for items */ + if (QUERY_FLAG(tmp,FLAG_APPLIED)) { + for (i=0; ibody_used[i] += tmp->body_info[i]; + } + + if(tmp->type==SYMPTOM) { + speed_reduce_from_disease = tmp->last_sp / 100.0; + 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.) + * Resistance from potions are treated special as well. If there's + * more than one potion-effect, the bigger prot.-value is taken. + */ + if (tmp->type != POTION) { + for (i=0; itype==POTION_EFFECT) { + if (potion_resist[i]) + potion_resist[i] = MAX(potion_resist[i], tmp->resist[i]); + else + potion_resist[i] = tmp->resist[i]; + } + else if (tmp->resist[i] > 0) + prot[i] += ((100-prot[i])*tmp->resist[i])/100; + else if (tmp->resist[i] < 0) + 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(QUERY_FLAG(tmp,FLAG_UNDEAD)&&!QUERY_FLAG(&op->arch->clone,FLAG_UNDEAD)) + SET_FLAG(op,FLAG_UNDEAD); + + if(QUERY_FLAG(tmp,FLAG_MAKE_INVIS)) { + SET_FLAG(op,FLAG_MAKE_INVIS); + op->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; + } else + added_speed+=(float)tmp->stats.exp; + } - switch(tmp->type) { + 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 (IS_COMBAT_SKILL(tmp->subtype)) wc_obj=tmp; - - if (op->chosen_skill) { - LOG(llevDebug, "fix_player, op %s has multiple skills applied\n", op->name); - } - op->chosen_skill = tmp; - if(tmp->stats.dam>0) { /* skill is a 'weapon' */ - if(!QUERY_FLAG(op,FLAG_READY_WEAPON)) - weapon_speed = (int) WEAPON_SPEED(tmp); - if(weapon_speed<0) weapon_speed = 0; - weapon_weight=tmp->weight; - op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9)); - if(tmp->magic) op->stats.dam += tmp->magic; - } - if(tmp->stats.wc) - wc-=(tmp->stats.wc+tmp->magic); - - if(tmp->slaying!=NULL) { - if (op->slaying != NULL) - free_string (op->slaying); - add_refcount(op->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; - - 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; - - case WEAPON: - 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; - if(tmp->slaying!=NULL) { - if (op->slaying != NULL) - free_string (op->slaying); - add_refcount(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_wcstats.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_acstats.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.0type */ - } /* item is equipped */ + /* for all skills and skill granting objects */ + case SKILL: + if (!QUERY_FLAG(tmp,FLAG_APPLIED)) break; + + if (IS_COMBAT_SKILL(tmp->subtype)) wc_obj=tmp; + + if (op->chosen_skill) { + LOG(llevDebug, "fix_player, op %s has multiple skills applied\n", op->name); + } + op->chosen_skill = tmp; + if(tmp->stats.dam>0) { /* skill is a 'weapon' */ + if(!QUERY_FLAG(op,FLAG_READY_WEAPON)) + weapon_speed = (int) WEAPON_SPEED(tmp); + if(weapon_speed<0) weapon_speed = 0; + weapon_weight=tmp->weight; + op->stats.dam+=tmp->stats.dam*(1 + (op->chosen_skill->level/9)); + if(tmp->magic) op->stats.dam += tmp->magic; + } + if(tmp->stats.wc) + wc-=(tmp->stats.wc+tmp->magic); + + if(tmp->slaying!=NULL) { + if (op->slaying != NULL) + free_string (op->slaying); + add_refcount(op->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; + + 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; + + case WEAPON: + 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; + if(tmp->slaying!=NULL) { + if (op->slaying != NULL) + free_string (op->slaying); + add_refcount(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_wcstats.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_acstats.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.0type */ + } /* item is equipped */ } /* for loop of items */ /* We've gone through all the objects the player has equipped. For many things, we @@ -1131,174 +1131,174 @@ * 'total resistance = vulnerability from cursed potion'. */ for (i=0; iresist[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]; + 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]; } /* Figure out the players sp/mana/hp totals. */ if(op->type==PLAYER) { - int pl_level; + int pl_level; - check_stat_bounds(&(op->stats)); - pl_level=op->level; + check_stat_bounds(&(op->stats)); + pl_level=op->level; - if(pl_level<1) pl_level=1; /* safety, we should always get 1 levels worth of hp! */ + if(pl_level<1) pl_level=1; /* safety, we should always get 1 levels worth of hp! */ - /* 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++) { - j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2; - if(i%2 && con_bonus[op->stats.Con]%2) { - if (con_bonus[op->stats.Con]>0) - j++; - else - j--; - } - op->stats.maxhp+=j>1?j:1; /* always get at least 1 hp/level */ - } - - for(i=11;i<=op->level;i++) - op->stats.maxhp+=2; - - if(op->stats.hp>op->stats.maxhp) - op->stats.hp=op->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; - if(!grace_obj) grace_obj = op; - /* set maxsp */ - if(!mana_obj || !mana_obj->level || op->type!=PLAYER) mana_obj = op; - - if (mana_obj == op && op->type == PLAYER) { - op->stats.maxsp = 1; - } else { - sp_tmp=0.0; - 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); - } 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; - sp_tmp+=stmp; - } - op->stats.maxsp=(int)sp_tmp; - - for(i=11;i<=mana_obj->level;i++) - op->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; - - /* 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 == op && op->type == PLAYER) { - op->stats.maxgrace = 1; - } else { - /* store grace in a float - this way, the divisions below don't create - * big jumps when you go from level to level - with int's, it then - * 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++) { - float grace_tmp=0.0; - - /* 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); - } 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; - sp_tmp+=grace_tmp; - } - op->stats.maxgrace=(int)sp_tmp; - - /* two grace points per level after 11 */ - for(i=11;i<=grace_obj->level;i++) - op->stats.maxgrace+=2; - } - /* No limit on grace vs maxgrace */ - - if(op->contr->braced) { - ac+=2; - wc+=4; - } - else - ac-=dex_bonus[op->stats.Dex]; - - /* In new exp/skills system, wc bonuses are related to - * the players level in a relevant exp object (wc_obj) - * not the general player level -b.t. - * I changed this slightly so that wc bonuses are better - * than before. This is to balance out the fact that - * the player no longer gets a personal weapon w/ 1 - * improvement every level, now its fighterlevel/5. So - * we give the player a bonus here in wc and dam - * to make up for the change. Note that I left the - * monster bonus the same as before. -b.t. - */ + /* 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++) { + j=op->contr->levhp[i]+con_bonus[op->stats.Con]/2; + if(i%2 && con_bonus[op->stats.Con]%2) { + if (con_bonus[op->stats.Con]>0) + j++; + else + j--; + } + op->stats.maxhp+=j>1?j:1; /* always get at least 1 hp/level */ + } + + for(i=11;i<=op->level;i++) + op->stats.maxhp+=2; + + if(op->stats.hp>op->stats.maxhp) + op->stats.hp=op->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; + if(!grace_obj) grace_obj = op; + /* set maxsp */ + if(!mana_obj || !mana_obj->level || op->type!=PLAYER) mana_obj = op; + + if (mana_obj == op && op->type == PLAYER) { + op->stats.maxsp = 1; + } else { + sp_tmp=0.0; + 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); + } 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; + sp_tmp+=stmp; + } + op->stats.maxsp=(int)sp_tmp; + + for(i=11;i<=mana_obj->level;i++) + op->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; + + /* 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 == op && op->type == PLAYER) { + op->stats.maxgrace = 1; + } else { + /* store grace in a float - this way, the divisions below don't create + * big jumps when you go from level to level - with int's, it then + * 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++) { + float grace_tmp=0.0; + + /* 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); + } 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; + sp_tmp+=grace_tmp; + } + op->stats.maxgrace=(int)sp_tmp; + + /* two grace points per level after 11 */ + for(i=11;i<=grace_obj->level;i++) + op->stats.maxgrace+=2; + } + /* No limit on grace vs maxgrace */ + + if(op->contr->braced) { + ac+=2; + wc+=4; + } + else + ac-=dex_bonus[op->stats.Dex]; + + /* In new exp/skills system, wc bonuses are related to + * the players level in a relevant exp object (wc_obj) + * not the general player level -b.t. + * I changed this slightly so that wc bonuses are better + * than before. This is to balance out the fact that + * the player no longer gets a personal weapon w/ 1 + * improvement every level, now its fighterlevel/5. So + * we give the player a bonus here in wc and dam + * to make up for the change. Note that I left the + * monster bonus the same as before. -b.t. + */ - if(op->type==PLAYER && wc_obj && wc_obj->level>1) { + if(op->type==PLAYER && wc_obj && wc_obj->level>1) { wc-=(wc_obj->level+thaco_bonus[op->stats.Str]); - for(i=1;ilevel;i++) { - /* addtional wc every 6 levels */ - if(!(i%6)) wc--; - /* addtional dam every 4 levels. */ - if(!(i%4) && (dam_bonus[op->stats.Str]>=0)) - op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5)); - } - } else - wc-=(op->level+thaco_bonus[op->stats.Str]); - - op->stats.dam+=dam_bonus[op->stats.Str]; - - if(op->stats.dam<1) - op->stats.dam=1; - - op->speed=1.0+speed_bonus[op->stats.Dex]; - if (settings.search_items && op->contr->search_str[0]) - op->speed -= 1; - if (op->attacktype==0) - op->attacktype=op->arch->clone.attacktype; + for(i=1;ilevel;i++) { + /* addtional wc every 6 levels */ + if(!(i%6)) wc--; + /* addtional dam every 4 levels. */ + if(!(i%4) && (dam_bonus[op->stats.Str]>=0)) + op->stats.dam+=(1+(dam_bonus[op->stats.Str]/5)); + } + } else + wc-=(op->level+thaco_bonus[op->stats.Str]); + + op->stats.dam+=dam_bonus[op->stats.Str]; + + if(op->stats.dam<1) + op->stats.dam=1; + + op->speed=1.0+speed_bonus[op->stats.Dex]; + if (settings.search_items && op->contr->search_str[0]) + op->speed -= 1; + if (op->attacktype==0) + op->attacktype=op->arch->clone.attacktype; } /* End if player */ if(added_speed>=0) - op->speed+=added_speed/10.0; + op->speed+=added_speed/10.0; else /* Something wrong here...: */ - op->speed /= (float)(1.0-added_speed); + op->speed /= (float)(1.0-added_speed); /* Max is determined by armour */ if(op->speed>max) - op->speed=max; + op->speed=max; if(op->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]; - if(f>0) op->speed=op->speed/(1.0+f/max_carry[op->stats.Str]); + /* 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]; + if(f>0) op->speed=op->speed/(1.0+f/max_carry[op->stats.Str]); } op->speed+=bonus_speed/10.0; /* Not affected by limits */ @@ -1311,28 +1311,28 @@ if (op->speed<0.01 && op->type==PLAYER) op->speed=0.01; if(op->type == PLAYER) { - float M,W,s,D,K,S,M2; + 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; + /* (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; } /* 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; + op->stats.dam=op->arch->clone.stats.dam*3; /* Prevent overflows of wc - best you can get is ABS(120) - this * should be more than enough - remember, AC is also in 8 bits, @@ -1374,7 +1374,7 @@ 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; + op->stats.Cha>0; } /* @@ -1398,7 +1398,7 @@ /* first, look for the highest level */ for(i=0; iresist[i] > abil->resist[atnr])) { + (atnr==-1 || abil->resist[i] > abil->resist[atnr])) { level = abil->resist[i]; atnr = i; } @@ -1425,11 +1425,11 @@ else { /* special titles for extra high resistance! */ if (skin->resist[atnr] > 80) - sprintf(pl->contr->title, "legendary %s dragon", attacks[atnr]); + sprintf(pl->contr->title, "legendary %s dragon", attacks[atnr]); else if (skin->resist[atnr] > 50) - sprintf(pl->contr->title, "ancient %s dragon", attacks[atnr]); + sprintf(pl->contr->title, "ancient %s dragon", attacks[atnr]); else - sprintf(pl->contr->title, "big %s dragon", attacks[atnr]); + sprintf(pl->contr->title, "big %s dragon", attacks[atnr]); } } @@ -1449,12 +1449,12 @@ /* 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; - } + 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; + } } /* if the force is missing -> bail out */ if (abil == NULL) return; @@ -1463,27 +1463,27 @@ * New abilties can only be gained by surpassing this max level */ if (who->level > abil->level) { - /* increase our focused ability */ - abil->resist[abil->stats.exp]++; + /* increase our focused ability */ + abil->resist[abil->stats.exp]++; - if (abil->resist[abil->stats.exp]>0 && abil->resist[abil->stats.exp]%5 == 0) { - /* time to hand out a new ability-gift */ - dragon_ability_gain(who, (int)abil->stats.exp, - (int)((1+abil->resist[abil->stats.exp])/5.)); - } + if (abil->resist[abil->stats.exp]>0 && abil->resist[abil->stats.exp]%5 == 0) { + /* time to hand out a new ability-gift */ + dragon_ability_gain(who, (int)abil->stats.exp, + (int)((1+abil->resist[abil->stats.exp])/5.)); + } - if (abil->last_eat > 0 && atnr_is_dragon_enabled(abil->last_eat)) { - /* apply new ability focus */ - sprintf(buf, "Your metabolism now focuses on %s!", - change_resist_msg[abil->last_eat]); - new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, who, buf); + if (abil->last_eat > 0 && atnr_is_dragon_enabled(abil->last_eat)) { + /* apply new ability focus */ + sprintf(buf, "Your metabolism now focuses on %s!", + change_resist_msg[abil->last_eat]); + new_draw_info(NDI_UNIQUE|NDI_BLUE, 0, who, buf); - abil->stats.exp = abil->last_eat; - abil->last_eat = 0; - } + abil->stats.exp = abil->last_eat; + abil->last_eat = 0; + } - abil->level = who->level; + abil->level = who->level; } /* last but not least, set the new title for the dragon */ @@ -1502,8 +1502,8 @@ 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); - return NULL; + 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. @@ -1513,8 +1513,8 @@ skill_obj->level = 1; insert_ob_in_ob(skill_obj, op); if (op->contr) { - op->contr->last_skill_ob[skill_obj->subtype] = skill_obj; - op->contr->last_skill_exp[skill_obj->subtype] = -1; + op->contr->last_skill_ob[skill_obj->subtype] = skill_obj; + op->contr->last_skill_exp[skill_obj->subtype] = -1; } return skill_obj; } @@ -1531,38 +1531,38 @@ char buf[MAX_BUF]; if(!op) /* when rolling stats */ - op = who; + op = who; if(op->level < settings.max_level && op->stats.exp >= level_exp(op->level+1,who->expmul)) { - op->level++; - - if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl(who)) - dragon_level_gain(who); + op->level++; + + if (op != NULL && 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 */ - if(op==who && (who->level < 11) && who->type==PLAYER) { - who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1; - who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH); - who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1; - } - - fix_player(who); - 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 */ + if(op==who && (who->level < 11) && who->type==PLAYER) { + who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1; + who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH); + who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1; + } + + fix_player(who); + 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.explevel,who->expmul)) { - op->level--; - fix_player(who); - 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 */ + op->level--; + fix_player(who); + 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_spells(who->contr); @@ -1575,7 +1575,7 @@ sint64 level_exp(int level,double expmul) { if (level > settings.max_level) - return (sint64) (expmul * levels[settings.max_level]); + return (sint64) (expmul * levels[settings.max_level]); return (sint64) (expmul * levels[level]); } @@ -1629,26 +1629,26 @@ * the players inventory. */ 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 { - for (i=0; icontr->last_skill_ob[i] && - !strcmp(op->contr->last_skill_ob[i]->skill, skill_name)) { - skill_obj = op->contr->last_skill_ob[i]; - break; - } - - /* 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 (op->chosen_skill && op->chosen_skill->type == SKILL && + !strcmp(skill_name, op->chosen_skill->skill)) + skill_obj = op->chosen_skill; + else { + for (i=0; icontr->last_skill_ob[i] && + !strcmp(op->contr->last_skill_ob[i]->skill, skill_name)) { + skill_obj = op->contr->last_skill_ob[i]; + break; + } + + /* 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); + } + } } /* Basically, you can never gain more experience in one shot @@ -1660,21 +1660,21 @@ ADD_EXP(op->stats.exp, (sint64) ((float) exp_to_add * (skill_obj? skill_obj->expmul:1))); if (settings.permanent_exp_ratio) { - ADD_EXP(op->perm_exp, (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1))); - calc_perm_exp(op); + ADD_EXP(op->perm_exp, (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1))); + calc_perm_exp(op); } player_lvl_adj(op,NULL); if (skill_obj) { - exp_to_add = exp; - limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2; - if (exp_to_add > limit) exp_to_add=limit; - ADD_EXP(skill_obj->stats.exp, exp_to_add); - if (settings.permanent_exp_ratio) { - skill_obj->perm_exp += (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO); - calc_perm_exp(skill_obj); - } - player_lvl_adj(op,skill_obj); + exp_to_add = exp; + limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2; + if (exp_to_add > limit) exp_to_add=limit; + ADD_EXP(skill_obj->stats.exp, exp_to_add); + if (settings.permanent_exp_ratio) { + skill_obj->perm_exp += (sint64) ((float) exp_to_add * PERM_EXP_GAIN_RATIO); + calc_perm_exp(skill_obj); + } + player_lvl_adj(op,skill_obj); } } @@ -1692,9 +1692,9 @@ if (exp > op->stats.exp) exp = op->stats.exp; if (settings.permanent_exp_ratio) { - del_exp = (sint64) ((op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO); - if (del_exp < 0) del_exp = 0; - if (exp > del_exp) exp=del_exp; + del_exp = (sint64) ((op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO); + if (del_exp < 0) del_exp = 0; + if (exp > del_exp) exp=del_exp; } return exp; } @@ -1725,24 +1725,24 @@ sint64 del_exp; 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)) { - del_exp = check_exp_loss(tmp, exp); - tmp->stats.exp -= del_exp; - player_lvl_adj(op, tmp); - } else if (flag != SK_SUBTRACT_SKILL_EXP) { - /* only want to process other skills if we are not trying - * to match a specific skill. - */ - del_exp = check_exp_loss(tmp, (sint64) (tmp->stats.exp * fraction)); - tmp->stats.exp -= del_exp; - player_lvl_adj(op, tmp); - } - } + if(tmp->type==SKILL && tmp->stats.exp) { + if (flag == SK_SUBTRACT_SKILL_EXP && skill && !strcmp(tmp->skill, skill)) { + del_exp = check_exp_loss(tmp, exp); + tmp->stats.exp -= del_exp; + player_lvl_adj(op, tmp); + } else if (flag != SK_SUBTRACT_SKILL_EXP) { + /* only want to process other skills if we are not trying + * to match a specific skill. + */ + del_exp = check_exp_loss(tmp, (sint64) (tmp->stats.exp * fraction)); + tmp->stats.exp -= del_exp; + player_lvl_adj(op, tmp); + } + } if (flag != SK_SUBTRACT_SKILL_EXP) { - del_exp = check_exp_loss(op, exp); - op->stats.exp -= del_exp; - player_lvl_adj(op,NULL); + del_exp = check_exp_loss(op, exp); + op->stats.exp -= del_exp; + player_lvl_adj(op,NULL); } } @@ -1770,8 +1770,8 @@ /* safety */ if(!op) { - LOG(llevError,"change_exp() called for null object!\n"); - return; + LOG(llevError,"change_exp() called for null object!\n"); + return; } /* if no change in exp, just return - most of the below code @@ -1785,29 +1785,29 @@ * worth. */ if(op->type != PLAYER) { - /* Sanity check */ - if (!QUERY_FLAG(op, FLAG_ALIVE)) return; + /* Sanity check */ + if (!QUERY_FLAG(op, FLAG_ALIVE)) return; - /* reset exp to max allowed value. We subtract from - * MAX_EXPERIENCE to prevent overflows. If the player somehow has - * more than max exp, just return. - */ - if (exp > 0 && ( op->stats.exp > (MAX_EXPERIENCE - exp))) { - exp = MAX_EXPERIENCE - op->stats.exp; - if (exp < 0) return; - } + /* reset exp to max allowed value. We subtract from + * MAX_EXPERIENCE to prevent overflows. If the player somehow has + * more than max exp, just return. + */ + if (exp > 0 && ( op->stats.exp > (MAX_EXPERIENCE - exp))) { + exp = MAX_EXPERIENCE - op->stats.exp; + if (exp < 0) return; + } - op->stats.exp += exp; + op->stats.exp += exp; } else { /* Players only */ - if(exp>0) - add_player_exp(op, exp, skill_name, flag); - else - /* note that when you lose exp, it doesn't go against - * a particular skill, so we don't need to pass that - * along. - */ - subtract_player_exp(op, FABS(exp), skill_name, flag); + if(exp>0) + add_player_exp(op, exp, skill_name, flag); + else + /* note that when you lose exp, it doesn't go against + * a particular skill, so we don't need to pass that + * along. + */ + subtract_player_exp(op, FABS(exp), skill_name, flag); } } @@ -1824,23 +1824,23 @@ sint64 level_loss; /* defined by the setting 'death_penalty_levels */ for(tmp=op->inv;tmp;tmp=tmp->below) - if(tmp->type==SKILL && tmp->stats.exp) { + if(tmp->type==SKILL && tmp->stats.exp) { - percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100; - level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)]; + percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100; + level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)]; - /* With the revised exp system, you can get cases where - * losing several levels would still require that you have more - * exp than you currently have - this is true if the levels - * tables is a lot harder. - */ - if (level_loss < 0) level_loss = 0; - - loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss)); - - tmp->stats.exp -= loss; - player_lvl_adj(op,tmp); - } + /* With the revised exp system, you can get cases where + * losing several levels would still require that you have more + * exp than you currently have - this is true if the levels + * tables is a lot harder. + */ + if (level_loss < 0) level_loss = 0; + + loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss)); + + tmp->stats.exp -= loss; + player_lvl_adj(op,tmp); + } percentage_loss = op->stats.exp * settings.death_penalty_ratio/100; level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)]; @@ -1863,7 +1863,7 @@ if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL; if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) - return 0; + return 0; return 1; }