1 | /* |
1 | /* |
2 | * static char *rcsid_living_c = |
2 | * static char *rcsid_living_c = |
3 | * "$Id: living.c,v 1.3 2006/02/09 02:11:26 root Exp $"; |
3 | * "$Id: living.c,v 1.8 2006/06/25 22:19:41 root Exp $"; |
4 | */ |
4 | */ |
5 | |
5 | |
6 | /* |
6 | /* |
7 | CrossFire, A Multiplayer game for X-windows |
7 | CrossFire, A Multiplayer game for X-windows |
8 | |
8 | |
… | |
… | |
68 | * at .667 |
68 | * at .667 |
69 | * This is figured by diff=(y-1)/(1+y), and for buy, it is 1+diff, for sell |
69 | * This is figured by diff=(y-1)/(1+y), and for buy, it is 1+diff, for sell |
70 | * it is 1-diff |
70 | * it is 1-diff |
71 | */ |
71 | */ |
72 | |
72 | |
73 | const float cha_bonus[MAX_STAT + 1]={10.0, 10.0, 9.0, 8.0, 7.0, 6.0, /*<-5*/ |
73 | const float cha_bonus[MAX_STAT + 1] = { 10.0, |
74 | 5.0, 4.5, 4.0, 3.5, 3.0, /*<-10*/ 2.9, 2.8, 2.7, 2.6, 2.5, /*<-15*/ |
74 | 10.0, 9.0, 8.0, 7.0, 6.0, /* 5 */ |
75 | 2.4, 2.3, 2.2, 2.1, 2.0, /*<-20*/ 1.95, 1.90, 1.85, 1.80, 1.75, /*25 */ |
75 | 5.0, 4.5, 4.0, 3.5, 3.0, /* 10 */ |
|
|
76 | 2.9, 2.8, 2.7, 2.6, 2.5, /* 15 */ |
|
|
77 | 2.4, 2.3, 2.2, 2.1, 2.0, /* 20 */ |
|
|
78 | 1.9, 1.8, 1.7, 1.6, 1.5, /* 25 */ |
76 | 1.70, 1.65, 1.60, 1.55, 1.50 /*30 */ |
79 | 1.4, 1.3, 1.2, 1.1, 1.0 /* 30 */ |
77 | }; |
80 | }; |
78 | |
81 | |
79 | const int dex_bonus[MAX_STAT + 1]={ |
82 | const int dex_bonus[MAX_STAT + 1]={ |
80 | -4,-3,-2,-2,-1,-1,-1,0,0,0,0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,7 |
83 | -4,-3,-2,-2,-1,-1,-1,0,0,0,0,0,0,0,1,1,1,2,2,2,3,3,3,4,4,4,5,5,6,6,7 |
81 | }; |
84 | }; |
82 | |
85 | |
83 | /* speed_bonus uses dex as its stat */ |
86 | /* speed_bonus uses dex as its stat */ |
84 | const float speed_bonus[MAX_STAT + 1]={ |
87 | const float speed_bonus[MAX_STAT + 1]={ |
85 | -0.4, -0.4, -0.3, -0.3, -0.2, -0.2, -0.2, -0.1, -0.1, -0.1, -0.05, 0, 0, 0, |
88 | -0.4, -0.35, -0.3, -0.25, -0.2, -0.16, -0.12, -0.09, -0.06, -0.03, -0.01, 0, 0.01, 0.03, |
86 | 0.05, 0.1, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.4, |
89 | 0.05, 0.1, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.4, |
87 | 1.6, 1.8, 2.0, 2.5, 3.0 |
90 | 1.6, 1.8, 2.0, 2.5, 3.0 |
88 | }; |
91 | }; |
89 | |
92 | |
90 | /* dam_bonus, thaco_bonus, max_carry, weight limit all are based on |
93 | /* dam_bonus, thaco_bonus, max_carry, weight limit all are based on |
… | |
… | |
308 | /* |
311 | /* |
309 | * returns the specified stat. See also set_attr_value(). |
312 | * returns the specified stat. See also set_attr_value(). |
310 | */ |
313 | */ |
311 | |
314 | |
312 | sint8 |
315 | sint8 |
313 | get_attr_value(living *stats,int attr) { |
316 | get_attr_value(const living *stats,int attr) { |
314 | switch(attr) { |
317 | switch(attr) { |
315 | case STR: |
318 | case STR: |
316 | return(stats->Str); |
319 | return(stats->Str); |
317 | case DEX: |
320 | case DEX: |
318 | return(stats->Dex); |
321 | return(stats->Dex); |
… | |
… | |
1372 | * check if the stat becomes negative, thus this function |
1375 | * check if the stat becomes negative, thus this function |
1373 | * merely checks that all stats are 1 or more, and returns |
1376 | * merely checks that all stats are 1 or more, and returns |
1374 | * false otherwise. |
1377 | * false otherwise. |
1375 | */ |
1378 | */ |
1376 | |
1379 | |
1377 | int allowed_class(object *op) { |
1380 | int allowed_class(const object *op) { |
1378 | return op->stats.Dex>0&&op->stats.Str>0&&op->stats.Con>0&& |
1381 | return op->stats.Dex>0&&op->stats.Str>0&&op->stats.Con>0&& |
1379 | op->stats.Int>0&&op->stats.Wis>0&&op->stats.Pow>0&& |
1382 | op->stats.Int>0&&op->stats.Wis>0&&op->stats.Pow>0&& |
1380 | op->stats.Cha>0; |
1383 | op->stats.Cha>0; |
1381 | } |
1384 | } |
1382 | |
1385 | |
… | |
… | |
1388 | * Note that the title is written to 'own_title' in the |
1391 | * Note that the title is written to 'own_title' in the |
1389 | * player struct. This should be changed to 'ext_title' |
1392 | * player struct. This should be changed to 'ext_title' |
1390 | * as soon as clients support this! |
1393 | * as soon as clients support this! |
1391 | * Please, anyone, write support for 'ext_title'. |
1394 | * Please, anyone, write support for 'ext_title'. |
1392 | */ |
1395 | */ |
1393 | void set_dragon_name(object *pl, object *abil, object *skin) { |
1396 | void set_dragon_name(object *pl, const object *abil, const object *skin) { |
1394 | int atnr=-1; /* attacknumber of highest level */ |
1397 | int atnr=-1; /* attacknumber of highest level */ |
1395 | int level=0; /* highest level */ |
1398 | int level=0; /* highest level */ |
1396 | int i; |
1399 | int i; |
1397 | |
1400 | |
1398 | /* Perhaps do something more clever? */ |
1401 | /* Perhaps do something more clever? */ |
… | |
… | |
1541 | |
1544 | |
1542 | if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl(who)) |
1545 | if (op != NULL && op == who && op->stats.exp > 1 && is_dragon_pl(who)) |
1543 | dragon_level_gain(who); |
1546 | dragon_level_gain(who); |
1544 | |
1547 | |
1545 | /* Only roll these if it is the player (who) that gained the level */ |
1548 | /* Only roll these if it is the player (who) that gained the level */ |
1546 | if(who && op==who && (who->level < 11) && who->type==PLAYER) { |
1549 | if(op==who && (who->level < 11) && who->type==PLAYER) { |
1547 | who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1; |
1550 | who->contr->levhp[who->level] = die_roll(2, 4, who, PREFER_HIGH)+1; |
1548 | who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH); |
1551 | who->contr->levsp[who->level] = die_roll(2, 3, who, PREFER_HIGH); |
1549 | who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1; |
1552 | who->contr->levgrace[who->level]=die_roll(2, 2, who, PREFER_HIGH)-1; |
1550 | } |
1553 | } |
1551 | |
1554 | |
1552 | if(who) fix_player(who); |
1555 | fix_player(who); |
1553 | if(op->level>1) { |
1556 | if(op->level>1) { |
1554 | if (op->type!=PLAYER) |
1557 | if (op->type!=PLAYER) |
1555 | sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name); |
1558 | sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name); |
1556 | else |
1559 | else |
1557 | sprintf(buf,"You are now level %d.",op->level); |
1560 | sprintf(buf,"You are now level %d.",op->level); |
1558 | if(who) new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); |
1561 | if(who) new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); |
1559 | } |
1562 | } |
1560 | player_lvl_adj(who,op); /* To increase more levels */ |
1563 | player_lvl_adj(who,op); /* To increase more levels */ |
1561 | } else if (op->level>1 && op->stats.exp<level_exp(op->level,who->expmul)) { |
1564 | } else if (op->level>1 && op->stats.exp<level_exp(op->level,who->expmul)) { |
1562 | op->level--; |
1565 | op->level--; |
1563 | if(who) fix_player(who); |
1566 | fix_player(who); |
1564 | if(op->type!=PLAYER) { |
1567 | if(op->type!=PLAYER) { |
1565 | sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name); |
1568 | sprintf(buf,"You are now level %d in the %s skill.",op->level,op->name); |
1566 | if(who) new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); |
1569 | new_draw_info(NDI_UNIQUE|NDI_RED, 0, who,buf); |
1567 | } |
1570 | } |
1568 | player_lvl_adj(who,op); /* To decrease more levels */ |
1571 | player_lvl_adj(who,op); /* To decrease more levels */ |
1569 | } |
1572 | } |
1570 | /* check if the spell data has changed */ |
1573 | /* check if the spell data has changed */ |
1571 | esrv_update_spells(who->contr); |
1574 | esrv_update_spells(who->contr); |
… | |
… | |
1591 | */ |
1594 | */ |
1592 | void calc_perm_exp(object *op) |
1595 | void calc_perm_exp(object *op) |
1593 | { |
1596 | { |
1594 | int p_exp_min; |
1597 | int p_exp_min; |
1595 | |
1598 | |
1596 | /* Ensure that our permanent experience minimum is met. */ |
1599 | /* Ensure that our permanent experience minimum is met. |
1597 | p_exp_min = (int)(PERM_EXP_MINIMUM_RATIO * (float)(op->stats.exp)); |
1600 | * permenent_exp_ratio is an integer percentage, we divide by 100 |
|
|
1601 | * to get the fraction */ |
|
|
1602 | p_exp_min = (int)(settings.permanent_exp_ratio * (float)(op->stats.exp)/100); |
1598 | |
1603 | |
1599 | if (op->perm_exp < p_exp_min) |
1604 | if (op->perm_exp < p_exp_min) |
1600 | op->perm_exp = p_exp_min; |
1605 | op->perm_exp = p_exp_min; |
1601 | |
1606 | |
1602 | /* Cap permanent experience. */ |
1607 | /* Cap permanent experience. */ |
… | |
… | |
1658 | exp_to_add = exp; |
1663 | exp_to_add = exp; |
1659 | limit=(levels[op->level+1]-levels[op->level])/2; |
1664 | limit=(levels[op->level+1]-levels[op->level])/2; |
1660 | if (exp_to_add > limit) exp_to_add=limit; |
1665 | if (exp_to_add > limit) exp_to_add=limit; |
1661 | |
1666 | |
1662 | ADD_EXP(op->stats.exp, (float) exp_to_add * (skill_obj? skill_obj->expmul:1)); |
1667 | ADD_EXP(op->stats.exp, (float) exp_to_add * (skill_obj? skill_obj->expmul:1)); |
1663 | if (settings.use_permanent_experience) { |
1668 | if (settings.permanent_exp_ratio) { |
1664 | ADD_EXP(op->perm_exp, (float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1)); |
1669 | ADD_EXP(op->perm_exp, (float) exp_to_add * PERM_EXP_GAIN_RATIO * (skill_obj? skill_obj->expmul:1)); |
1665 | calc_perm_exp(op); |
1670 | calc_perm_exp(op); |
1666 | } |
1671 | } |
1667 | |
1672 | |
1668 | player_lvl_adj(op,NULL); |
1673 | player_lvl_adj(op,NULL); |
1669 | if (skill_obj) { |
1674 | if (skill_obj) { |
1670 | exp_to_add = exp; |
1675 | exp_to_add = exp; |
1671 | limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2; |
1676 | limit=(levels[skill_obj->level+1]-levels[skill_obj->level])/2; |
1672 | if (exp_to_add > limit) exp_to_add=limit; |
1677 | if (exp_to_add > limit) exp_to_add=limit; |
1673 | ADD_EXP(skill_obj->stats.exp, exp_to_add); |
1678 | ADD_EXP(skill_obj->stats.exp, exp_to_add); |
1674 | if (settings.use_permanent_experience) { |
1679 | if (settings.permanent_exp_ratio) { |
1675 | skill_obj->perm_exp += exp_to_add * PERM_EXP_GAIN_RATIO; |
1680 | skill_obj->perm_exp += exp_to_add * PERM_EXP_GAIN_RATIO; |
1676 | calc_perm_exp(skill_obj); |
1681 | calc_perm_exp(skill_obj); |
1677 | } |
1682 | } |
1678 | player_lvl_adj(op,skill_obj); |
1683 | player_lvl_adj(op,skill_obj); |
1679 | } |
1684 | } |
… | |
… | |
1685 | * adjustments based on permanent exp and the like. |
1690 | * adjustments based on permanent exp and the like. |
1686 | * This function should always be used for losing experience - |
1691 | * This function should always be used for losing experience - |
1687 | * the 'exp' value passed should be positive - this is the |
1692 | * the 'exp' value passed should be positive - this is the |
1688 | * amount that should get subtract from the player. |
1693 | * amount that should get subtract from the player. |
1689 | */ |
1694 | */ |
1690 | sint64 check_exp_loss(object *op, sint64 exp) |
1695 | sint64 check_exp_loss(const object *op, sint64 exp) |
1691 | { |
1696 | { |
1692 | sint64 del_exp; |
1697 | sint64 del_exp; |
1693 | |
1698 | |
1694 | if (exp > op->stats.exp) exp = op->stats.exp; |
1699 | if (exp > op->stats.exp) exp = op->stats.exp; |
1695 | if (settings.use_permanent_experience) { |
1700 | if (settings.permanent_exp_ratio) { |
1696 | del_exp = (op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO; |
1701 | del_exp = (op->stats.exp - op->perm_exp) * PERM_EXP_MAX_LOSS_RATIO; |
1697 | if (del_exp < 0) del_exp = 0; |
1702 | if (del_exp < 0) del_exp = 0; |
1698 | if (exp > del_exp) exp=del_exp; |
1703 | if (exp > del_exp) exp=del_exp; |
1699 | } |
1704 | } |
1700 | return exp; |
1705 | return exp; |
1701 | } |
1706 | } |
1702 | |
1707 | |
1703 | sint64 check_exp_adjust(object *op, sint64 exp) |
1708 | sint64 check_exp_adjust(const object *op, sint64 exp) |
1704 | { |
1709 | { |
1705 | if (exp<0) return check_exp_loss(op, exp); |
1710 | if (exp<0) return check_exp_loss(op, exp); |
1706 | else return MIN(exp, MAX_EXPERIENCE - op->stats.exp); |
1711 | else return MIN(exp, MAX_EXPERIENCE - op->stats.exp); |
1707 | } |
1712 | } |
1708 | |
1713 | |
… | |
… | |
1811 | subtract_player_exp(op, FABS(exp), skill_name, flag); |
1816 | subtract_player_exp(op, FABS(exp), skill_name, flag); |
1812 | |
1817 | |
1813 | } |
1818 | } |
1814 | } |
1819 | } |
1815 | |
1820 | |
1816 | /* Applies a death penalty experience. 20% or 3 levels, whichever is |
1821 | /* Applies a death penalty experience, the size of this is defined by the |
1817 | * less experience lost. |
1822 | * settings death_penalty_percentage and death_penalty_levels, and by the |
|
|
1823 | * amount of permenent experience, whichever gives the lowest loss. |
1818 | */ |
1824 | */ |
1819 | |
1825 | |
1820 | void apply_death_exp_penalty(object *op) { |
1826 | void apply_death_exp_penalty(object *op) { |
1821 | object *tmp; |
1827 | object *tmp; |
1822 | sint64 loss; |
1828 | sint64 loss; |
1823 | sint64 loss_20p; /* 20 percent experience loss */ |
1829 | sint64 percentage_loss; /* defined by the setting 'death_penalty_percent' */ |
1824 | sint64 loss_3l; /* 3 level experience loss */ |
1830 | sint64 level_loss; /* defined by the setting 'death_penalty_levels */ |
1825 | |
1831 | |
1826 | for(tmp=op->inv;tmp;tmp=tmp->below) |
1832 | for(tmp=op->inv;tmp;tmp=tmp->below) |
1827 | if(tmp->type==SKILL && tmp->stats.exp) { |
1833 | if(tmp->type==SKILL && tmp->stats.exp) { |
1828 | |
1834 | |
1829 | #ifdef COZY_SERVER |
1835 | percentage_loss = tmp->stats.exp * settings.death_penalty_ratio/100; |
1830 | loss_20p = tmp->stats.exp * 0.05; |
1836 | level_loss = tmp->stats.exp - levels[MAX(0,tmp->level - settings.death_penalty_level)]; |
1831 | #else |
|
|
1832 | loss_20p = tmp->stats.exp * 0.20; |
|
|
1833 | #endif |
|
|
1834 | loss_3l = tmp->stats.exp - levels[MAX(0,tmp->level -3)]; |
|
|
1835 | |
1837 | |
1836 | /* With the revised exp system, you can get cases where |
1838 | /* With the revised exp system, you can get cases where |
1837 | * losing 3 levels would still require that you have more |
1839 | * losing several levels would still require that you have more |
1838 | * exp than you current have - this is true if the levels |
1840 | * exp than you currently have - this is true if the levels |
1839 | * tables is a lot harder. |
1841 | * tables is a lot harder. |
1840 | */ |
1842 | */ |
1841 | if (loss_3l < 0) loss_3l = 0; |
1843 | if (level_loss < 0) level_loss = 0; |
1842 | |
1844 | |
1843 | loss = check_exp_loss(tmp, MIN(loss_3l, loss_20p)); |
1845 | loss = check_exp_loss(tmp, MIN(level_loss, percentage_loss)); |
1844 | |
1846 | |
1845 | tmp->stats.exp -= loss; |
1847 | tmp->stats.exp -= loss; |
1846 | player_lvl_adj(op,tmp); |
1848 | player_lvl_adj(op,tmp); |
1847 | } |
1849 | } |
1848 | |
1850 | |
1849 | #ifdef COZY_SERVER |
1851 | percentage_loss = op->stats.exp * settings.death_penalty_ratio/100; |
1850 | loss_20p = op->stats.exp * 0.20; |
1852 | level_loss = op->stats.exp - levels[MAX(0,op->level - settings.death_penalty_level)]; |
1851 | #else |
|
|
1852 | loss_20p = op->stats.exp * 0.05; |
|
|
1853 | #endif |
|
|
1854 | loss_3l = op->stats.exp - levels[MAX(0,op->level -3)]; |
|
|
1855 | if (loss_3l < 0) loss_3l = 0; |
1853 | if (level_loss < 0) level_loss = 0; |
1856 | loss = check_exp_loss(op, MIN(loss_3l, loss_20p)); |
1854 | loss = check_exp_loss(op, MIN(level_loss, percentage_loss)); |
1857 | |
1855 | |
1858 | op->stats.exp -= loss; |
1856 | op->stats.exp -= loss; |
1859 | player_lvl_adj(op,NULL); |
1857 | player_lvl_adj(op,NULL); |
1860 | } |
1858 | } |
1861 | |
1859 | |
… | |
… | |
1864 | * save_throw table. level is the effective level to make |
1862 | * save_throw table. level is the effective level to make |
1865 | * the save at, and bonus is any plus/bonus (typically based on |
1863 | * the save at, and bonus is any plus/bonus (typically based on |
1866 | * resistance to particular attacktype. |
1864 | * resistance to particular attacktype. |
1867 | * Returns 1 if op makes his save, 0 if he failed |
1865 | * Returns 1 if op makes his save, 0 if he failed |
1868 | */ |
1866 | */ |
1869 | int did_make_save(object *op, int level, int bonus) |
1867 | int did_make_save(const object *op, int level, int bonus) |
1870 | { |
1868 | { |
1871 | if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL; |
1869 | if (level > MAX_SAVE_LEVEL) level = MAX_SAVE_LEVEL; |
1872 | |
1870 | |
1873 | if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) |
1871 | if ((random_roll(1, 20, op, PREFER_HIGH) + bonus) < savethrow[level]) |
1874 | return 0; |
1872 | return 0; |