Index: common/init.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/common/init.c,v retrieving revision 1.47 diff -C5 -r1.47 init.c *** common/init.c 11 Feb 2006 14:05:32 -0000 1.47 --- common/init.c 6 Mar 2006 18:48:17 -0000 *************** *** 54,64 **** PLAYERDIR, MAPDIR, ARCHETYPES,REGIONS,TREASURES, UNIQUE_DIR, TEMPLATE_DIR, TMPDIR, STAT_LOSS_ON_DEATH, PK_LUCK_PENALTY, ! USE_PERMANENT_EXPERIENCE, BALANCED_STAT_LOSS, NOT_PERMADETH, SIMPLE_EXP, RESET_LOCATION_TIME, SET_TITLE, --- 54,66 ---- PLAYERDIR, MAPDIR, ARCHETYPES,REGIONS,TREASURES, UNIQUE_DIR, TEMPLATE_DIR, TMPDIR, STAT_LOSS_ON_DEATH, PK_LUCK_PENALTY, ! PERMANENT_EXPERIENCE_RATIO, ! DEATH_PENALTY_RATIO, ! DEATH_PENALTY_LEVEL, BALANCED_STAT_LOSS, NOT_PERMADETH, SIMPLE_EXP, RESET_LOCATION_TIME, SET_TITLE, Index: common/living.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/common/living.c,v retrieving revision 1.76 diff -C5 -r1.76 living.c *** common/living.c 9 Feb 2006 00:48:36 -0000 1.76 --- common/living.c 6 Mar 2006 18:48:24 -0000 *************** *** 1591,1602 **** */ void calc_perm_exp(object *op) { int p_exp_min; ! /* Ensure that our permanent experience minimum is met. */ ! p_exp_min = (int)(PERM_EXP_MINIMUM_RATIO * (float)(op->stats.exp)); if (op->perm_exp < p_exp_min) op->perm_exp = p_exp_min; /* Cap permanent experience. */ --- 1591,1604 ---- */ void calc_perm_exp(object *op) { int p_exp_min; ! /* Ensure that our permanent experience minimum is met. ! * permenent_exp_ratio is an integer percentage, we divide by 100 ! * to get the fraction */ ! p_exp_min = (int)(settings.permanent_exp_ratio * (float)(op->stats.exp)/100); if (op->perm_exp < p_exp_min) op->perm_exp = p_exp_min; /* Cap permanent experience. */ *************** *** 1658,1679 **** exp_to_add = exp; limit=(levels[op->level+1]-levels[op->level])/2; if (exp_to_add > limit) exp_to_add=limit; ADD_EXP(op->stats.exp, (float) exp_to_add * (skill_obj? skill_obj->expmul:1)); ! if (settings.use_permanent_experience) { ADD_EXP(op->perm_exp, (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.use_permanent_experience) { skill_obj->perm_exp += exp_to_add * PERM_EXP_GAIN_RATIO; calc_perm_exp(skill_obj); } player_lvl_adj(op,skill_obj); } --- 1660,1681 ---- exp_to_add = exp; limit=(levels[op->level+1]-levels[op->level])/2; if (exp_to_add > limit) exp_to_add=limit; ADD_EXP(op->stats.exp, (float) exp_to_add * (skill_obj? skill_obj->expmul:1)); ! if (settings.permanent_exp_ratio) { ADD_EXP(op->perm_exp, (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 += exp_to_add * PERM_EXP_GAIN_RATIO; calc_perm_exp(skill_obj); } player_lvl_adj(op,skill_obj); } *************** *** 1690,1700 **** sint64 check_exp_loss(const object *op, sint64 exp) { sint64 del_exp; if (exp > op->stats.exp) exp = op->stats.exp; ! if (settings.use_permanent_experience) { del_exp = (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; --- 1692,1702 ---- sint64 check_exp_loss(const object *op, sint64 exp) { sint64 del_exp; if (exp > op->stats.exp) exp = op->stats.exp; ! if (settings.permanent_exp_ratio) { del_exp = (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; *************** *** 1811,1853 **** subtract_player_exp(op, FABS(exp), skill_name, flag); } } ! /* Applies a death penalty experience. 20% or 3 levels, whichever is ! * less experience lost. */ void apply_death_exp_penalty(object *op) { object *tmp; sint64 loss; ! sint64 loss_20p; /* 20 percent experience loss */ ! sint64 loss_3l; /* 3 level experience loss */ for(tmp=op->inv;tmp;tmp=tmp->below) if(tmp->type==SKILL && tmp->stats.exp) { ! loss_20p = tmp->stats.exp * 0.20; ! loss_3l = tmp->stats.exp - levels[MAX(0,tmp->level -3)]; /* With the revised exp system, you can get cases where ! * losing 3 levels would still require that you have more ! * exp than you current have - this is true if the levels * tables is a lot harder. */ ! if (loss_3l < 0) loss_3l = 0; ! loss = check_exp_loss(tmp, MIN(loss_3l, loss_20p)); tmp->stats.exp -= loss; player_lvl_adj(op,tmp); } ! loss_20p = op->stats.exp * 0.20; ! loss_3l = op->stats.exp - levels[MAX(0,op->level -3)]; ! if (loss_3l < 0) loss_3l = 0; ! loss = check_exp_loss(op, MIN(loss_3l, loss_20p)); op->stats.exp -= loss; player_lvl_adj(op,NULL); } --- 1813,1856 ---- subtract_player_exp(op, FABS(exp), skill_name, flag); } } ! /* Applies a death penalty experience, the size of this is defined by the ! * 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) { object *tmp; sint64 loss; ! sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */ ! 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) { ! 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); } ! 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)); op->stats.exp -= loss; player_lvl_adj(op,NULL); } Index: include/config.h =================================================================== RCS file: /cvsroot/crossfire/crossfire/include/config.h,v retrieving revision 1.69 diff -C5 -r1.69 config.h *** include/config.h 29 Oct 2005 09:34:02 -0000 1.69 --- include/config.h 6 Mar 2006 18:48:27 -0000 *************** *** 116,126 **** /* Don't edit these values. They are configured in lib/settings. These are Simply the defaults. */ #define BALANCED_STAT_LOSS FALSE ! #define USE_PERMANENT_EXPERIENCE FALSE #define SET_TITLE TRUE #define SIMPLE_EXP TRUE #define SPELLPOINT_LEVEL_DEPEND TRUE #define SPELL_ENCUMBRANCE TRUE #define SPELL_FAILURE_EFFECTS FALSE --- 116,128 ---- /* Don't edit these values. They are configured in lib/settings. These are Simply the defaults. */ #define BALANCED_STAT_LOSS FALSE ! #define PERMANENT_EXPERIENCE_RATIO 25 ! #define DEATH_PENALTY_RATIO 20 ! #define DEATH_PENALTY_LEVEL 3 #define SET_TITLE TRUE #define SIMPLE_EXP TRUE #define SPELLPOINT_LEVEL_DEPEND TRUE #define SPELL_ENCUMBRANCE TRUE #define SPELL_FAILURE_EFFECTS FALSE *************** *** 225,266 **** */ /* #define PARTY_KILL_LOG 20 */ ! /* Use permanent experience code? ! * This code allows players to build up a small amount of 'permanent ! * experience' which reduces the effect of large experience drains, such as ! * death. This makes multiple frequent deaths less devastating, and also ! * ensures that any character will make some gradual progress even if they ! * die all of the time. ! * A nice option if your keep dying due to massive client/server lags despite ! * playing well... or you like to swim well outside of your depth. :) ! * ! * The PERM_EXP values adjust the behaviour of this option - if ! * USE_PERMAMENT_EXPERIENCE if off, these values have no meaning. If it ! * is on, the minimum ratio is the minimum amount of permanent exp relative ! * to the total exp in the skill (ie, at a default of .25, if you had 100 ! * experience, at least 25 of it would be permanent). The gain ratio ! * is how much of experienced experience goes to the permanent value. ! * This does not detract from total exp gain (ie, if you gained 100 exp, ! * 100 would go to the skill total and 10 to the permanent value). ! * the loss ratio is the maximum amount of experience that can be lost ! * in any one hit - this is calculated as total exp - perm exp * loss ratio. * * A few thoughts on these default value (by MSW) * gain ratio is pretty much meaningless until exp has been lost, as until ! * that poin, the minimum ratio will be used. * It is also impossible for the exp to actually be reduced to the permanent * exp ratio - since the loss ratio is .5, it will just get closer and * closer. However, after about half a dozen hits, pretty much all the * exp that can be lost has been lost, and after that, only minor loss * will occur. */ /* GD */ - #define PERM_EXP_MINIMUM_RATIO 0.25f #define PERM_EXP_GAIN_RATIO 0.10f #define PERM_EXP_MAX_LOSS_RATIO 0.50f /* * WATCHDOG lets sends datagrams to port 13325 on localhost --- 227,259 ---- */ /* #define PARTY_KILL_LOG 20 */ ! /* ! * The PERM_EXP values adjust the behaviour of permenent experience. - if ! * the setting permanent_experience_percentage is zero, these values have ! * no meaning. The value in the settings file is the percentage of the ! * experience that is permenent, the rest could be lost on death. When dying, ! * the greatest amount of non-permenent exp it is possible to lose at one time ! * is PERM_EXP_MAX_LOSS_RATIO - this is calculated as ! * total exp - perm exp * loss ratio. The gain ratio is how much of experienced ! * experience goes to the permanent value. This does not detract from total ! * exp gain (ie, if you gained 100 exp, 100 would go to the skill total and ! * 10 to the permanent value). * * A few thoughts on these default value (by MSW) * gain ratio is pretty much meaningless until exp has been lost, as until ! * that poin, the value in the settings file will be used. * It is also impossible for the exp to actually be reduced to the permanent * exp ratio - since the loss ratio is .5, it will just get closer and * closer. However, after about half a dozen hits, pretty much all the * exp that can be lost has been lost, and after that, only minor loss * will occur. */ /* GD */ #define PERM_EXP_GAIN_RATIO 0.10f #define PERM_EXP_MAX_LOSS_RATIO 0.50f /* * WATCHDOG lets sends datagrams to port 13325 on localhost Index: include/global.h =================================================================== RCS file: /cvsroot/crossfire/crossfire/include/global.h,v retrieving revision 1.62 diff -C5 -r1.62 global.h *** include/global.h 8 Jan 2006 16:31:17 -0000 1.62 --- include/global.h 6 Mar 2006 18:48:29 -0000 *************** *** 326,346 **** char *uniquedir; /* directory for the unique items */ char *templatedir; /* directory for the template map */ char *tmpdir; /* Directory to use for temporary files */ uint8 stat_loss_on_death; /* If true, chars lose a random stat when they die */ sint16 pk_luck_penalty; /* Amount by which player luck is reduced if they PK */ ! uint8 use_permanent_experience; /* If true, players can gain perm exp */ uint8 balanced_stat_loss; /* If true, Death stat depletion based on level etc */ uint8 not_permadeth; /* if true, death is non-permament */ uint8 simple_exp; /* If true, use the simple experience system */ int reset_loc_time; /* Number of seconds to put player back at home */ uint8 set_title; /* players can set thier title */ uint8 resurrection; /* ressurection possible w/ permadeth on */ uint8 search_items; /* search_items command */ uint8 spell_encumbrance; /* encumbrance effects spells */ uint8 spell_failure_effects; /* nasty backlash to spell failures */ ! uint16 set_friendly_fire; /* Percent of damage done by peaceful player vs player damage */ uint8 casting_time; /* it takes awhile to cast a spell */ uint8 real_wiz; /* use mud-like wizards */ uint8 recycle_tmp_maps; /* re-use tmp maps. */ uint8 explore_mode; /* explore mode allowed? */ uint8 spellpoint_level_depend; /* spell costs go up with level */ --- 326,348 ---- char *uniquedir; /* directory for the unique items */ char *templatedir; /* directory for the template map */ char *tmpdir; /* Directory to use for temporary files */ uint8 stat_loss_on_death; /* If true, chars lose a random stat when they die */ sint16 pk_luck_penalty; /* Amount by which player luck is reduced if they PK */ ! uint8 permanent_exp_ratio; /* how much exp should be 'permenant' and unable to be lost*/ ! uint8 death_penalty_ratio; /* how much exp should be lost at death */ ! uint8 death_penalty_level; /* how many levels worth of exp may be lost on one death */ uint8 balanced_stat_loss; /* If true, Death stat depletion based on level etc */ uint8 not_permadeth; /* if true, death is non-permament */ uint8 simple_exp; /* If true, use the simple experience system */ int reset_loc_time; /* Number of seconds to put player back at home */ uint8 set_title; /* players can set thier title */ uint8 resurrection; /* ressurection possible w/ permadeth on */ uint8 search_items; /* search_items command */ uint8 spell_encumbrance; /* encumbrance effects spells */ uint8 spell_failure_effects; /* nasty backlash to spell failures */ ! uint16 set_friendly_fire; /* Percent of damage done by peaceful player vs player damage */ uint8 casting_time; /* it takes awhile to cast a spell */ uint8 real_wiz; /* use mud-like wizards */ uint8 recycle_tmp_maps; /* re-use tmp maps. */ uint8 explore_mode; /* explore mode allowed? */ uint8 spellpoint_level_depend; /* spell costs go up with level */ Index: lib/settings =================================================================== RCS file: /cvsroot/crossfire/crossfire/lib/settings,v retrieving revision 1.22 diff -C5 -r1.22 settings *** lib/settings 22 Jan 2006 02:32:46 -0000 1.22 --- lib/settings 6 Mar 2006 18:48:31 -0000 *************** *** 198,230 **** # Setting it to true keeps the old behaviour. This can be # changed at run time via -stat_loss_on_death or +stat_loss_on_death. stat_loss_on_death false ! # This makes repeated stat loss at lower levels more mercifull. Basically, # the more stats you have lost, the less likely that # you will lose more. Additionally, lower level characters are shown # a lot more mercy (there are caps on how much of a stat you can lose too). ! # On the nasty side, if you are higher level, you can lose mutiple stats # _at_once_ and are shown less mercy when you die. But when you're higher # level, it is much easier to buy back your stats with potions. # Turn this on if you want death-based stat loss to be more merciful # at low levels and more cruel at high levels. # Only works when stats are depleted rather than lost. This option has # no effect if you are using genuine stat loss. balanced_stat_loss false ! # This allows players to build up a small amount of 'permanent ! # experience' which reduces the effect of large experience drains, such as ! # death. This makes multiple frequent deaths less devastating, and also ! # ensures that any character will make some gradual progress even if they ! # die all of the time. ! # A nice option if your keep dying due to massive client/server lags despite ! # playing well... or you like to swim well outside of your depth. :) ! use_permanent_experience false # This is the penalty to luck that is given to a player who kills another # player (PK's). The value here is deducted from their luck value, so set this # high to discourage PK-ing and zero (or negative) to encourage it. # Range is limited to -100 to 100, since this is the value range that the luck --- 198,241 ---- # Setting it to true keeps the old behaviour. This can be # changed at run time via -stat_loss_on_death or +stat_loss_on_death. stat_loss_on_death false ! # This makes repeated stat loss at lower levels more merciful. Basically, # the more stats you have lost, the less likely that # you will lose more. Additionally, lower level characters are shown # a lot more mercy (there are caps on how much of a stat you can lose too). ! # On the nasty side, if you are higher level, you can lose multiple stats # _at_once_ and are shown less mercy when you die. But when you're higher # level, it is much easier to buy back your stats with potions. # Turn this on if you want death-based stat loss to be more merciful # at low levels and more cruel at high levels. # Only works when stats are depleted rather than lost. This option has # no effect if you are using genuine stat loss. balanced_stat_loss false ! # This defines how much of a player's experience should be 'permanent' and ! # not able to be lost on death. A high value makes multiple frequent deaths ! # less devastating, and also ensures that any character will make some ! # gradual progress even if they die all of the time. This value is the minimum ! # amount of a player's exp that can ever be 'permanent' so setting this to 0 ! # would allow all exp to be lost, and setting it to 100 would stop exp loss ! # entirely (the same effect would be achieved by setting the two ! # death_penalty settings below to 0). ! ! permanent_experience_percentage 25 ! ! # When a player dies, they lose a proportion of their experience, which is ! # defined by the following two values. They will lose either ! # death_penalty_percentage% of their experience, or no more than ! # death_penalty_levels levels, or half of their non-permenent experience, ! # whichever is the least of these. Note that this is calculated per-skill, ! # so which method is used could vary for different skills. ! death_penalty_percentage 20 ! death_penalty_levels 3 # This is the penalty to luck that is given to a player who kills another # player (PK's). The value here is deducted from their luck value, so set this # high to discourage PK-ing and zero (or negative) to encourage it. # Range is limited to -100 to 100, since this is the value range that the luck Index: server/init.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/server/init.c,v retrieving revision 1.73 diff -C5 -r1.73 init.c *** server/init.c 10 Feb 2006 23:59:27 -0000 1.73 --- server/init.c 6 Mar 2006 18:48:36 -0000 *************** *** 574,592 **** } else { LOG(llevError, "load_settings: Unknown value for " "stat_loss_on_death: %s\n", cp); } } else if (!strcasecmp(buf, "use_permanent_experience")) { ! if (!strcasecmp(cp, "on") || !strcasecmp(cp, "true")) { ! settings.use_permanent_experience=TRUE; ! } else if (!strcasecmp(cp, "off") || !strcasecmp(cp, "false")) { ! settings.use_permanent_experience=FALSE; ! } else { ! LOG(llevError, "load_settings: Unknown value for " ! "use_permanent_experience: %s\n", cp); ! } ! } else if (!strcasecmp(buf, "balanced_stat_loss")) { if (!strcasecmp(cp, "on") || !strcasecmp(cp, "true")) { settings.balanced_stat_loss=TRUE; } else if (!strcasecmp(cp, "off") || !strcasecmp(cp, "false")) { settings.balanced_stat_loss=FALSE; } else { --- 574,607 ---- } else { LOG(llevError, "load_settings: Unknown value for " "stat_loss_on_death: %s\n", cp); } } else if (!strcasecmp(buf, "use_permanent_experience")) { ! LOG(llevError, "use_permanent_experience is deprecated, use" ! "permenent_experience_percentage instead\n"); ! } else if (!strcasecmp(buf, "permanent_experience_percentage")) { ! int val = atoi(cp); ! if (val < 0 || val >100) ! LOG(llevError, "load_settings: permenent_experience_percentage" ! "must be between 0 and 100, %d is invalid\n", val); ! else ! settings.permanent_exp_ratio = val; ! } else if (!strcasecmp(buf, "death_penalty_percentage")) { ! int val = atoi(cp); ! if (val < 0 || val >100) ! LOG(llevError, "load_settings: death_penalty_percentage" ! "must be between 0 and 100, %d is invalid\n", val); ! else ! settings.death_penalty_ratio = val; ! } else if (!strcasecmp(buf, "death_penalty_levels")) { ! int val = atoi(cp); ! if (val < 0 || val > 255) ! LOG(llevError, "load_settings: death_penalty_levels" ! "can not be negative, %d is invalid\n", val); ! else ! settings.death_penalty_level = val; ! }else if (!strcasecmp(buf, "balanced_stat_loss")) { if (!strcasecmp(cp, "on") || !strcasecmp(cp, "true")) { settings.balanced_stat_loss=TRUE; } else if (!strcasecmp(cp, "off") || !strcasecmp(cp, "false")) { settings.balanced_stat_loss=FALSE; } else { Index: server/skill_util.c =================================================================== RCS file: /cvsroot/crossfire/crossfire/server/skill_util.c,v retrieving revision 1.63 diff -C5 -r1.63 skill_util.c *** server/skill_util.c 17 Feb 2006 21:29:48 -0000 1.63 --- server/skill_util.c 6 Mar 2006 18:48:37 -0000 *************** *** 655,671 **** /* Need to have a pointer and use strdup for qsort to work properly */ char skills[NUM_SKILLS][MAX_BUF]; for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { ! if (tmp->type == SKILL) { if ( search && strstr(tmp->name,search)==NULL ) continue; /* Basically want to fill this out to 40 spaces with periods */ sprintf(buf,"%s%s", tmp->name, periods); buf[40] = 0; ! if (settings.use_permanent_experience) { #ifdef WIN32 sprintf(skills[num_skills_found++],"%slvl:%3d (xp:%I64d/%I64d/%d%%)", buf,tmp->level, tmp->stats.exp, level_exp(tmp->level+1, op->expmul), --- 655,671 ---- /* Need to have a pointer and use strdup for qsort to work properly */ char skills[NUM_SKILLS][MAX_BUF]; for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { ! if (tmp->type == SKILL) { if ( search && strstr(tmp->name,search)==NULL ) continue; /* Basically want to fill this out to 40 spaces with periods */ sprintf(buf,"%s%s", tmp->name, periods); buf[40] = 0; ! if (settings.permanent_exp_ratio) { #ifdef WIN32 sprintf(skills[num_skills_found++],"%slvl:%3d (xp:%I64d/%I64d/%d%%)", buf,tmp->level, tmp->stats.exp, level_exp(tmp->level+1, op->expmul),