My skills are assigned at level with a base percentage of 60% and can be increased via usage. Skills/spells/songs used more often increase at a slower rate than those used less frequently.
Code:
void check_improve(struct char_data *ch, int sn, bool success)
{
int need, gain, roll_s, roll_f, base;
/* NPC doesn't have skills */
if (IS_NPC(ch))
return;
/* PC doesn't have level required for the skill */
if (GET_LEVEL(ch) < spell_info[sn].min_level[GET_CLASS(ch)])
return;
/* Skill is not practiced or skill is maxed */
if (GET_SKILL(ch, sn) == 0 || GET_SKILL(ch, sn) == MAX_SKILL(ch))
return;
/* Base rate of increase for spells */
if (sn > 0 && sn <= NUM_SPELLS)
{
if (spell_info[sn].violent)
base = 5 * MAX_SKILL(ch);
else
base = 3 * MAX_SKILL(ch);
}
/* Base rate of increase for songs */
if (sn > ZERO_SONGS && sn <= ZERO_SONGS + NUM_SONGS)
{
if (spell_info[sn].routines == MAG_AFFECTS)
base = 3 * MAX_SKILL(ch);
else if (spell_info[sn].routines == MAG_POINTS)
base = 5 * MAX_SKILL(ch);
else
base = 5 * MAX_SKILL(ch);
}
/* Base rate of increase for skills */
if (sn > ZERO_SKILLS && sn <= ZERO_SKILLS + NUM_SKILLS)
base = 5 * MAX_SKILL(ch);
else
base = 5 * MAX_SKILL(ch);
if (GET_CLASS(ch) == CLASS_ROGUE)
need = MAX_SKILL(ch) - GET_SKILL(ch, sn) + GET_LUCK(ch) * 2;
else
need = MAX_SKILL(ch) - GET_SKILL(ch, sn);
/*
Size for successful roll
GET_TOTAL(ch) is GET_LEVEL(ch) + an endgame rank
*/
roll_s = MAX(0, base - (2 * GET_TOTAL(ch)));
/*
Size for failure roll
GET_TOTAL(ch) is GET_LEVEL(ch) + an endgame rank
*/
roll_f = MAX(0, base - (3 * GET_TOTAL(ch)));
/* Was the skill check a success? */
if (success)
{
if (need > rand_number(0, roll_s))
{
gain = GET_SKILL(ch, sn);
gain++;
SET_SKILL(ch, sn, MIN(MAX_SKILL(ch), gain));
send_to_char(ch, "You have become better at %s! (%d%%)\n\r", spell_info[sn].name, GET_SKILL(ch, sn));
if (GET_SKILL(ch, sn) >= MAX_SKILL(ch))
send_to_char(ch, "You are now learned in at %s.\r\n", spell_info[sn].name);
}
}
else /* Whatever skill, we failed it. Lets try to learn from our mistakes. */
{
if (need > rand_number(0, roll_f))
{
gain = GET_SKILL(ch, sn);
gain += dice(1, 4) + 1;
SET_SKILL(ch, sn, MIN(MAX_SKILL(ch), gain));
send_to_char(ch, "You learn from your mistakes, and your %s skill improves. (%d%%)\n\r", spell_info[sn].name, GET_SKILL(ch, sn));
if (GET_SKILL(ch, sn) >= MAX_SKILL(ch))
send_to_char(ch, "You are now learned in at %s.\r\n", spell_info[sn].name);
}
}
}