/* Code specifically for the new skill system */
#if defined(WIN32)
#include <time.h>
#else
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "magic.h"
#include <math.h>
/* command procedures needed */
DECLARE_DO_FUN(do_groups );
DECLARE_DO_FUN(do_help );
DECLARE_DO_FUN(do_say );
/* used to get new skills */
void do_gain(CHAR_DATA *ch, char *argument)
{
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
CHAR_DATA *trainer;
int gn = 0, sn = 0;
if (IS_NPC(ch))
return;
/* find a trainer */
for ( trainer = ch->in_room->people;
trainer != NULL;
trainer = trainer->next_in_room)
if (IS_NPC(trainer) && IS_SET(trainer->act,ACT_GAIN))
break;
if (trainer == NULL || !can_see(ch,trainer))
{
send_to_char("You can't do that here.\n\r",ch);
return;
}
one_argument(argument,arg);
if (arg[0] == '\0')
{
do_say(trainer,"Pardon me?");
return;
}
if (!str_prefix(arg,"list"))
{
int col;
col = 0;
sprintf(buf, "%-18s %-5s %-18s %-5s %-18s %-5s\n\r",
"group","cost","group","cost","group","cost");
send_to_char(buf,ch);
for (gn = 0; gn < MAX_GROUP; gn++)
{
if (group_table[gn].name == NULL)
break;
if (!ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->Class] > 0)
{
sprintf(buf,"%-18s %-5d ",
group_table[gn].name,group_table[gn].rating[ch->Class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if (col % 3 != 0)
send_to_char("\n\r",ch);
send_to_char("\n\r",ch);
col = 0;
sprintf(buf, "%-18s %-5s %-18s %-5s %-18s %-5s\n\r",
"skill","cost","skill","cost","skill","cost");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (!ch->pcdata->learned[sn]
&& skill_table[sn].rating[ch->Class] > 0
&& skill_table[sn].spell_fun == spell_null)
{
sprintf(buf,"%-18s %-5d ",
skill_table[sn].name,skill_table[sn].rating[ch->Class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if (col % 3 != 0)
send_to_char("\n\r",ch);
return;
}
if (!str_prefix(arg,"convert"))
{
if (ch->practice < 10)
{
act("$N tells you 'You are not yet ready.'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your practice to training",
ch,NULL,trainer,TO_CHAR);
ch->practice -= 10;
ch->train +=1 ;
return;
}
if (!str_prefix(arg,"points"))
{
if (ch->train < 2)
{
act("$N tells you 'You are not yet ready.'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->points <= 40)
{
act("$N tells you 'There would be no point in that.'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N trains you, and you feel more at ease with your skills.",
ch,NULL,trainer,TO_CHAR);
ch->train -= 2;
ch->pcdata->points -= 1;
ch->exp = 0;
return;
}
/* else add a group/skill */
gn = group_lookup(argument);
if (gn > 0)
{
if (ch->pcdata->group_known[gn])
{
act("$N tells you 'You already know that group!'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (group_table[gn].rating[ch->Class] <= 0)
{
act("$N tells you 'That group is beyond your powers.'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->train < group_table[gn].rating[ch->Class])
{
act("$N tells you 'You are not yet ready for that group.'",
ch,NULL,trainer,TO_CHAR);
return;
}
/* add the group */
gn_add(ch,gn);
act("$N trains you in the art of $t",
ch,group_table[gn].name,trainer,TO_CHAR);
ch->train -= group_table[gn].rating[ch->Class];
return;
}
sn = skill_lookup(argument);
if (sn > -1)
{
if (skill_table[sn].spell_fun != spell_null)
{
act("$N tells you 'You must learn the full group.'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->learned[sn])
{
act("$N tells you 'You already know that skill!'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (skill_table[sn].rating[ch->Class] <= 0)
{
act("$N tells you 'That skill is beyond your powers.'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->train < skill_table[sn].rating[ch->Class])
{
act("$N tells you 'You are not yet ready for that skill.'",
ch,NULL,trainer,TO_CHAR);
return;
}
/* add the skill */
ch->pcdata->learned[sn] = 1;
act("$N trains you in the art of $t",
ch,skill_table[sn].name,trainer,TO_CHAR);
ch->train -= skill_table[sn].rating[ch->Class];
return;
}
act("$N tells you 'I do not understand...'",ch,NULL,trainer,TO_CHAR);
}
/* RT spells and skills show the players spells (or skills) */
void do_spells(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char spell_list[LEVEL_HERO][MAX_STRING_LENGTH];
char spell_columns[LEVEL_HERO];
int sn,lev,mana;
bool found = FALSE;
if (IS_NPC(ch))
return;
/* initilize data */
for (lev = 0; lev < LEVEL_HERO; lev++)
{
spell_columns[lev] = 0;
spell_list[lev][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (skill_table[sn].skill_level[ch->Class] < LEVEL_HERO &&
skill_table[sn].spell_fun != spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
lev = skill_table[sn].skill_level[ch->Class];
if (ch->level < lev)
sprintf(buf,"%-18s n/a ", skill_table[sn].name);
else
{
mana = UMAX(skill_table[sn].min_mana,
100/(2 + ch->level - lev));
sprintf(buf,"%-18s %3d mana ",skill_table[sn].name,mana);
}
if (spell_list[lev][0] == '\0')
sprintf(spell_list[lev],"\n\rLevel %2d: %s",lev,buf);
else /* append */
{
if ( ++spell_columns[lev] % 2 == 0)
strcat(spell_list[lev],"\n\r ");
strcat(spell_list[lev],buf);
}
}
}
/* return results */
if (!found)
{
send_to_char("You know no spells.\n\r",ch);
return;
}
for (lev = 0; lev < LEVEL_HERO; lev++)
if (spell_list[lev][0] != '\0')
send_to_char(spell_list[lev],ch);
send_to_char("\n\r",ch);
}
void do_skills(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
char skill_list[LEVEL_HERO][MAX_STRING_LENGTH];
char skill_columns[LEVEL_HERO];
int sn,lev;
bool found = FALSE;
if (IS_NPC(ch))
return;
/* initilize data */
for (lev = 0; lev < LEVEL_HERO; lev++)
{
skill_columns[lev] = 0;
skill_list[lev][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL )
break;
if (skill_table[sn].skill_level[ch->Class] < LEVEL_HERO &&
skill_table[sn].spell_fun == spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
lev = skill_table[sn].skill_level[ch->Class];
if (ch->level < lev)
sprintf(buf,"%-18s n/a ", skill_table[sn].name);
else
sprintf(buf,"%-18s %3d%% ",skill_table[sn].name,
ch->pcdata->learned[sn]);
if (skill_list[lev][0] == '\0')
sprintf(skill_list[lev],"\n\rLevel %2d: %s",lev,buf);
else /* append */
{
if ( ++skill_columns[lev] % 2 == 0)
strcat(skill_list[lev],"\n\r ");
strcat(skill_list[lev],buf);
}
}
}
/* return results */
if (!found)
{
send_to_char("You know no skills.\n\r",ch);
return;
}
for (lev = 0; lev < LEVEL_HERO; lev++)
if (skill_list[lev][0] != '\0')
send_to_char(skill_list[lev],ch);
send_to_char("\n\r",ch);
}
/* shows skills, groups and costs (only if not bought) */
void list_group_costs(CHAR_DATA *ch)
{
char buf[MAX_STRING_LENGTH];
int gn,sn,col;
if (IS_NPC(ch))
return;
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s\n\r","group","cp","group","cp","group","cp");
send_to_char(buf,ch);
for (gn = 0; gn < MAX_GROUP; gn++)
{
if (group_table[gn].name == NULL)
break;
if (!ch->gen_data->group_chosen[gn]
&& !ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->Class] > 0)
{
sprintf(buf,"%-18s %-5d ",group_table[gn].name,
group_table[gn].rating[ch->Class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r",ch);
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s\n\r","skill","cp","skill","cp","skill","cp");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (!ch->gen_data->skill_chosen[sn]
&& ch->pcdata->learned[sn] == 0
&& skill_table[sn].spell_fun == spell_null
&& skill_table[sn].rating[ch->Class] > 0)
{
sprintf(buf,"%-18s %-5d ",skill_table[sn].name,
skill_table[sn].rating[ch->Class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r",ch);
sprintf(buf,"Creation points: %d\n\r",ch->pcdata->points);
send_to_char(buf,ch);
sprintf(buf,"Experience modifier: %d%% (Percent of difference from the norm)\n\r",
figure_difference(ch->gen_data->points_chosen));
send_to_char(buf,ch);
return;
}
void list_group_chosen(CHAR_DATA *ch)
{
char buf[MAX_STRING_LENGTH];
int gn,sn,col;
if (IS_NPC(ch))
return;
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s","group","cp","group","cp","group","cp\n\r");
send_to_char(buf,ch);
for (gn = 0; gn < MAX_GROUP; gn++)
{
if (group_table[gn].name == NULL)
break;
if (ch->gen_data->group_chosen[gn]
&& group_table[gn].rating[ch->Class] > 0)
{
sprintf(buf,"%-18s %-5d ",group_table[gn].name,
group_table[gn].rating[ch->Class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r",ch);
col = 0;
sprintf(buf,"%-18s %-5s %-18s %-5s %-18s %-5s","skill","cp","skill","cp","skill","cp\n\r");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (ch->gen_data->skill_chosen[sn]
&& skill_table[sn].rating[ch->Class] > 0)
{
sprintf(buf,"%-18s %-5d ",skill_table[sn].name,
skill_table[sn].rating[ch->Class]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
send_to_char("\n\r",ch);
sprintf(buf,"Creation points: %d\n\r",ch->gen_data->points_chosen);
send_to_char(buf,ch);
sprintf(buf,"Experience modifier: %d%% (Percent of difference from the norm)\n\r",
figure_difference(ch->gen_data->points_chosen));
send_to_char(buf,ch);
return;
}
long exp_per_level(CHAR_DATA *ch, int points)
{
long expl=0;
if (IS_NPC(ch))
return 1000;
switch(ch->level) {
case 1: expl=750;
break;
case 2: expl=1500;
break;
case 3: expl=3000;
break;
case 4: expl=6000;
break;
case 5: expl=12000;
break;
case 6: expl=24000;
break;
case 7: expl=48000;
break;
case 8: expl=96000;
break;
case 9: expl=192000;
break;
case 10: expl=384000;
break;
case 11: expl=768000;
break;
case 12: expl=1536000;
break;
case 13: expl=1996800;
break;
case 14: expl=2595840;
break;
case 15: expl=3374590;
break;
case 16: expl=4386970;
break;
case 17: expl=5703060;
break;
case 18: expl=7413970;
break;
case 19: expl=9638170;
break;
case 20: expl=12529620;
break;
case 21: expl=16288510;
break;
case 22: expl=19546214;
break;
case 23: expl=23455450;
break;
case 24: expl=28146540;
break;
case 25: expl=33775850;
break;
case 26: expl=37153440;
break;
case 27: expl=40868780;
break;
case 28: expl=44955660;
break;
case 29: expl=49451230;
break;
case 30: expl=53523100;
break;
case 31: expl=57500000;
break;
case 32: expl=61506090;
break;
case 33: expl=65571300;
break;
case 34: expl=69696969;
break;
case 35: expl=74530130;
break;
case 36: expl=79590170;
break;
case 37: expl=84567800;
break;
case 38: expl=89012000;
break;
case 39: expl=94500600;
break;
case 40: expl=99503030;
break;
case 41: expl=104000000;
break;
case 42: expl=108000000;
break;
case 43: expl=112000000;
break;
case 44: expl=116000000;
break;
case 45: expl=120000000;
break;
case 46: expl=124000000;
break;
case 47: expl=128000000;
break;
case 48: expl=132000000;
break;
case 49: expl=136000000;
break;
case 50: expl=140000000;
break;
case 51: expl=150000000;
break;
case 52: expl=160000000;
break;
case 53: expl=170000000;
break;
case 54: expl=180000000;
break;
case 55: expl=190000000;
break;
case 56: expl=200000000;
break;
case 57: expl=210000000;
break;
case 58: expl=220000000;
break;
case 59: expl=230000000;
break;
case 60: expl=240000000;
break;
case 61: expl=250000000;
break;
case 62: expl=260000000;
break;
case 63: expl=270000000;
break;
case 64: expl=280000000;
break;
case 65: expl=290000000;
break;
case 66: expl=300000000;
break;
case 67: expl=310000000;
break;
case 68: expl=320000000;
break;
case 69: expl=330000000;
break;
case 70: expl=340000000;
break;
case 71: expl=350000000;
break;
case 72: expl=360000000;
break;
case 73: expl=370000000;
break;
case 74: expl=380000000;
break;
case 75: expl=390000000;
break;
case 76: expl=400000000;
break;
case 77: expl=410000000;
break;
case 78: expl=420000000;
break;
case 79: expl=430000000;
break;
case 80: expl=460000000;
break;
case 81: expl=480000000;
break;
case 82: expl=500000000;
break;
case 83: expl=520000000;
break;
case 84: expl=540000000;
break;
case 85: expl=560000000;
break;
case 86: expl=580000000;
break;
case 87: expl=600000000;
break;
case 88: expl=620000000;
break;
case 89: expl=640000000;
break;
case 90: expl=660000000;
break;
case 91: expl=700000000;
break;
case 92: expl=999999999;
break;
case 93: expl=999999999;
break;
case 94: expl=999999999;
break;
case 95: expl=999999999;
break;
case 96: expl=999999999;
break;
case 97: expl=999999999;
break;
case 98: expl=999999999;
break;
case 99: expl=999999999;
break;
case 100: expl=999999999;
break;
}
/* if (points > 110) expl=(long)pow((double)110,(double)1.2)*(expl/100); */
if (points >= 28) expl=(long)pow((double)points,(double)1.2)*(expl/100);
/* && (points <= 110)) */
if (points < 28) expl=(long) (expl*((26.0+points)/100.0));
/* if (points < 40)
return 1000 * pc_race_table[ch->race].class_mult[ch->Class]/100;
/ processing /
points -= 40;
while (points > 9)
{
expl += inc;
points -= 10;
if (points > 9)
{
expl += inc;
inc *= 2;
points -= 10;
}
}
expl += points * inc / 10;*/
return expl * (pc_race_table[ch->race].class_mult[ch->Class]/100);
}
/* this procedure handles the input parsing for the skill generator */
bool parse_gen_groups(CHAR_DATA *ch,char *argument)
{
char arg[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
int gn,sn,i;
if (argument[0] == '\0')
return FALSE;
argument = one_argument(argument,arg);
if (!str_prefix(arg,"help"))
{
if (argument[0] == '\0')
{
do_help(ch,"group help");
return TRUE;
}
do_help(ch,argument);
return TRUE;
}
if (!str_prefix(arg,"add"))
{
if (argument[0] == '\0')
{
send_to_char("You must provide a skill name.\n\r",ch);
return TRUE;
}
/* Fix this to look for groups that person already has and only charge for the ones they don't. -Zane */
gn = group_lookup(argument);
if (gn != -1)
{
if (ch->gen_data->group_chosen[gn]
|| ch->pcdata->group_known[gn])
{
send_to_char("You already know that group!\n\r",ch);
return TRUE;
}
if (group_table[gn].rating[ch->Class] < 1)
{
send_to_char("That group is not available.\n\r",ch);
return TRUE;
}
/* If this is broken, please mail dennis@realms.reichel.net :-) */
for ( i=0; group_table[gn].spells[i] != NULL ; i++)
{
if ( group_lookup( group_table[gn].spells[i] ) == -1 )
continue;
if ( ch->pcdata->group_known[group_lookup( group_table[gn].spells[i])] )
{
send_to_char("That group contains groups you already know.\n\r",ch);
send_to_char("Please \"drop\" them if you wish to gain this one.\n\r",ch);
return TRUE;
}
}
for ( i=0; group_table[gn].spells[i] != NULL ; i++)
{
if ( skill_lookup( group_table[gn].spells[i] ) == -1 )
continue;
if ( ch->gen_data->skill_chosen[skill_lookup( group_table[gn].spells[i])] )
{
send_to_char("That group contains skills/spells you already know.\n\r",ch);
send_to_char("Please \"drop\" them if you wish to gain this one.\n\r",ch);
return TRUE;
}
}
sprintf(buf,"%s group added\n\r",group_table[gn].name);
send_to_char(buf,ch);
ch->gen_data->group_chosen[gn] = TRUE;
ch->gen_data->points_chosen += group_table[gn].rating[ch->Class];
gn_add(ch,gn);
ch->pcdata->points += group_table[gn].rating[ch->Class];
return TRUE;
}
sn = skill_lookup(argument);
if (sn != -1)
{
if (ch->gen_data->skill_chosen[sn]
|| ch->pcdata->learned[sn] > 0)
{
send_to_char("You already know that skill!\n\r",ch);
return TRUE;
}
if (skill_table[sn].rating[ch->Class] < 1
|| skill_table[sn].spell_fun != spell_null)
{
send_to_char("That skill is not available.\n\r",ch);
return TRUE;
}
sprintf(buf, "%s skill added\n\r",skill_table[sn].name);
send_to_char(buf,ch);
ch->gen_data->skill_chosen[sn] = TRUE;
ch->gen_data->points_chosen += skill_table[sn].rating[ch->Class];
ch->pcdata->learned[sn] = 1;
ch->pcdata->points += skill_table[sn].rating[ch->Class];
return TRUE;
}
send_to_char("No skills or groups by that name...\n\r",ch);
return TRUE;
}
if (!strcmp(arg,"drop"))
{
if (argument[0] == '\0')
{
send_to_char("You must provide a skill to drop.\n\r",ch);
return TRUE;
}
gn = group_lookup(argument);
if (gn != -1 && ch->gen_data->group_chosen[gn])
{
send_to_char("Group dropped.\n\r",ch);
ch->gen_data->group_chosen[gn] = FALSE;
ch->gen_data->points_chosen -= group_table[gn].rating[ch->Class];
gn_remove(ch,gn);
for (i = 0; i < MAX_GROUP; i++)
{
if (ch->gen_data->group_chosen[gn])
gn_add(ch,gn);
}
ch->pcdata->points -= group_table[gn].rating[ch->Class];
return TRUE;
}
sn = skill_lookup(argument);
if (sn != -1 && ch->gen_data->skill_chosen[sn])
{
send_to_char("Skill dropped.\n\r",ch);
ch->gen_data->skill_chosen[sn] = FALSE;
ch->gen_data->points_chosen -= skill_table[sn].rating[ch->Class];
ch->pcdata->learned[sn] = 0;
ch->pcdata->points -= skill_table[sn].rating[ch->Class];
return TRUE;
}
send_to_char("You haven't bought any such skill or group.\n\r",ch);
return TRUE;
}
if (!str_prefix(arg,"premise"))
{
do_help(ch,"premise");
return TRUE;
}
if (!str_prefix(arg,"list"))
{
list_group_costs(ch);
return TRUE;
}
if (!str_prefix(arg,"learned"))
{
list_group_chosen(ch);
return TRUE;
}
if (!str_prefix(arg,"info"))
{
do_groups(ch,argument);
return TRUE;
}
return FALSE;
}
/* shows all groups, or the sub-members of a group */
void do_groups(CHAR_DATA *ch, char *argument)
{
char buf[MAX_STRING_LENGTH];
int gn,sn,col;
if (IS_NPC(ch))
return;
col = 0;
if (argument[0] == '\0')
{ /* show all groups */
for (gn = 0; gn < MAX_GROUP; gn++)
{
if (group_table[gn].name == NULL)
break;
if (ch->pcdata->group_known[gn])
{
sprintf(buf,"%-20s ",group_table[gn].name);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
sprintf(buf,"Creation points: %d\n\r",ch->pcdata->points);
send_to_char(buf,ch);
return;
}
if (!str_cmp(argument,"all")) /* show all groups */
{
for (gn = 0; gn < MAX_GROUP; gn++)
{
if (group_table[gn].name == NULL)
break;
sprintf(buf,"%-20s ",group_table[gn].name);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
return;
}
/* show the sub-members of a group */
gn = group_lookup(argument);
if (gn == -1)
{
send_to_char("No group of that name exist.\n\r",ch);
send_to_char(
"Type 'groups all' or 'info all' for a full listing.\n\r",ch);
return;
}
for (sn = 0; sn < MAX_IN_GROUP; sn++)
{
if (group_table[gn].spells[sn] == NULL)
break;
sprintf(buf,"%-20s ",group_table[gn].spells[sn]);
send_to_char(buf,ch);
if (++col % 3 == 0)
send_to_char("\n\r",ch);
}
if ( col % 3 != 0 )
send_to_char( "\n\r", ch );
}
/* checks for skill improvement */
void check_improve( CHAR_DATA *ch, int sn, bool success, int multiplier )
{
char buf[MAX_STRING_LENGTH];
int chance;
if (IS_NPC(ch))
return;
if (ch->level < skill_table[sn].skill_level[ch->Class]
|| skill_table[sn].rating[ch->Class] == 0
|| ch->pcdata->learned[sn] == 0
|| ch->pcdata->learned[sn] == 100)
return; /* skill is not known */
/* check to see if the character has a chance to learn */
chance = 10 * int_app[get_curr_stat(ch,STAT_INT)].learn;
chance /= ( multiplier
* skill_table[sn].rating[ch->Class]
* 4);
chance += ch->level;
if (number_range(1,1000) > chance)
return;
/* now that the character has a CHANCE to learn, see if they really have */
if (success)
{
chance = URANGE(5,100 - ch->pcdata->learned[sn], 95);
if (number_percent() < chance)
{
sprintf(buf,"You have become better at %s!\n\r",
skill_table[sn].name);
send_to_char(buf,ch);
ch->pcdata->learned[sn]++;
gain_exp(ch,2 * skill_table[sn].rating[ch->Class]);
}
}
else
{
chance = URANGE(5,ch->pcdata->learned[sn]/2,30);
if (number_percent() < chance)
{
sprintf(buf,
"You learn from your mistakes, and your %s skill improves.\n\r",
skill_table[sn].name);
send_to_char(buf,ch);
ch->pcdata->learned[sn] += number_range(1,3);
ch->pcdata->learned[sn] = UMIN(ch->pcdata->learned[sn],100);
gain_exp(ch,2 * skill_table[sn].rating[ch->Class]);
}
}
}
/* returns a group index number given the name */
int group_lookup( const char *name )
{
int gn;
for ( gn = 0; gn < MAX_GROUP; gn++ )
{
if ( group_table[gn].name == NULL )
break;
if ( LOWER(name[0]) == LOWER(group_table[gn].name[0])
&& !str_prefix( name, group_table[gn].name ) )
return gn;
}
return -1;
}
/* recursively adds a group given its number -- uses group_add */
void gn_add( CHAR_DATA *ch, int gn)
{
int i;
ch->pcdata->group_known[gn] = TRUE;
for ( i = 0; i < MAX_IN_GROUP; i++)
{
if (group_table[gn].spells[i] == NULL)
break;
group_add(ch,group_table[gn].spells[i],FALSE);
}
}
/* recusively removes a group given its number -- uses group_remove */
void gn_remove( CHAR_DATA *ch, int gn)
{
int i;
ch->pcdata->group_known[gn] = FALSE;
for ( i = 0; i < MAX_IN_GROUP; i ++)
{
if (group_table[gn].spells[i] == NULL)
break;
group_remove(ch,group_table[gn].spells[i]);
}
}
/* use for processing a skill or group for addition */
void group_add( CHAR_DATA *ch, const char *name, bool deduct)
{
int sn,gn;
if (IS_NPC(ch)) /* NPCs do not have skills */
return;
sn = skill_lookup(name);
if (sn != -1)
{
if (ch->pcdata->learned[sn] == 0) /* i.e. not known */
{
ch->pcdata->learned[sn] = 1;
if (deduct)
ch->pcdata->points += skill_table[sn].rating[ch->Class];
}
return;
}
/* now check groups */
gn = group_lookup(name);
if (gn != -1)
{
if (ch->pcdata->group_known[gn] == FALSE)
{
ch->pcdata->group_known[gn] = TRUE;
if (deduct)
ch->pcdata->points += group_table[gn].rating[ch->Class];
}
gn_add(ch,gn); /* make sure all skills in the group are known */
}
}
/* used for processing a skill or group for deletion -- no points back! */
void group_remove(CHAR_DATA *ch, const char *name)
{
int sn, gn;
sn = skill_lookup(name);
if (sn != -1)
{
ch->pcdata->learned[sn] = 0;
return;
}
/* now check groups */
gn = group_lookup(name);
if (gn != -1 && ch->pcdata->group_known[gn] == TRUE)
{
ch->pcdata->group_known[gn] = FALSE;
gn_remove(ch,gn); /* be sure to call gn_add on all remaining groups */
}
}