/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Much time and thought has gone into this software and you are *
* benefitting. We hope that you share your changes too. What goes *
* around, comes around. *
***************************************************************************/
/***************************************************************************
* ROM 2.4 is copyright 1993-1995 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file 'rom.license' *
***************************************************************************/
/***************************************************************************
* ROT 2.0 is copyright 1996-1999 by Russ Walsh *
* By using this code, you have agreed to follow the terms of the *
* ROT license, in the file 'rot.license' *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#if defined(WIN32)
#include <time.h>
#else
#include <sys/time.h>
#endif
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "magic.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 buf[MSL];
char arg[MIL];
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;
}
if (ch->spirit)
{
send_to_char( "Spirits cannot gain.\n\r", ch);
return;
}
one_argument(argument,arg);
if (arg[0] == '\0')
{
do_say(trainer,"{aPardon me?{x");
send_to_char("{aI offer the following gain options:{x\n\r",ch);
send_to_char("{R list {aList the groups and skills you can gain.{x\n\r", ch);
send_to_char("{R convert {aConverts 5 practices to 1 train.{x\n\r", ch);
send_to_char("{R study {aConverts 1 train to 6 practices.{x\n\r", ch);
send_to_char("{R quest {aConverts 3 quest points to 1 train.{x\n\r", ch);
send_to_char("{R points {aGain creation points.{x\n\r", ch);
send_to_char("{R <{rname{R> {aGain skill or group <name>{x\n\r\n\r", ch);
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++)
{
bool nfound = FALSE;
int tmpskill = 999;
if (group_table[gn].name == NULL)
break;
if (!ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->class] > 0)
{
nfound = TRUE;
sprintf(buf,"{R%-18s %-5d {x",
group_table[gn].name,group_table[gn].rating[ch->class]);
tmpskill = group_table[gn].rating[ch->class];
}
if ( (ch->pcdata->tier == 2)
&& !ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->clasb] > 0)
{
sprintf(buf,"{B%-18s %-5d {x",
group_table[gn].name,group_table[gn].rating[ch->clasb]);
if (nfound)
{
sprintf(buf,"{G%-18s %-5d {x",
group_table[gn].name,
UMIN(tmpskill, group_table[gn].rating[ch->clasb]) );
}
nfound = TRUE;
}
if (nfound)
{
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, "{M%-18s {Y%-5s {M%-18s {Y%-5s {M%-18s {Y%-5s{x\n\r",
"skill","cost","skill","cost","skill","cost");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
bool nfound = FALSE;
int tmpskill = 999;
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)
{
nfound = TRUE;
sprintf(buf,"{R%-18s %-5d {x",
skill_table[sn].name,skill_table[sn].rating[ch->class]);
tmpskill = skill_table[sn].rating[ch->class];
}
if ( (ch->pcdata->tier == 2)
&& !ch->pcdata->learned[sn]
&& skill_table[sn].rating[ch->clasb] > 0
&& skill_table[sn].spell_fun == spell_null)
{
sprintf(buf,"{B%-18s %-5d {x",
skill_table[sn].name,skill_table[sn].rating[ch->clasb]);
if (nfound)
{
sprintf(buf,"{G%-18s %-5d {x",
skill_table[sn].name,
UMIN(tmpskill, skill_table[sn].rating[ch->clasb]) );
}
nfound = TRUE;
}
if (nfound)
{
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 < 6)
{
act("$N tells you '{aYou are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your practice to training",
ch,NULL,trainer,TO_CHAR);
ch->practice -= 5;
ch->train +=1 ;
return;
}
if (!str_prefix(arg,"study"))
{
if (ch->train < 1)
{
act("$N tells you '{aYou are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your training to practice",
ch,NULL,trainer,TO_CHAR);
ch->train -= 1;
ch->practice += 5;
return;
}
if (!str_prefix(arg,"quest"))
{
if (ch->aqps < 3)
{
act("$N tells you '{aYou are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
act("$N helps you apply your quest points to training",
ch,NULL,trainer,TO_CHAR);
ch->aqps -= 3;
ch->train += 1;
return;
}
if (!str_prefix(arg,"points"))
{
if (!IS_NPC(ch) && IS_SET(ch->act, PLR_LQUEST))
{
act("$N tells you '{aYou may not gain points while on a level quest.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->train < 1)
{
act("$N tells you '{aYou are not yet ready.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->points <= 40)
{
act("$N tells you '{aThere would be no point in that.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (((ch->level + 1) * exp_per_level(ch,ch->pcdata->points) - ch->exp) >= 5000)
{
sprintf(buf, "Go work off some of that exp first %s.",ch->name);
do_say(trainer,buf);
return;
}
act("$N trains you, and you feel more at ease with your skills.",
ch,NULL,trainer,TO_CHAR);
ch->train -= 1;
ch->pcdata->points -= 1;
ch->exp = (long)exp_per_level(ch,ch->pcdata->points) * ch->level;
return;
}
/* else add a group/skill */
gn = group_lookup(argument);
if (gn > 0)
{
if (ch->pcdata->group_known[gn])
{
act("$N tells you '{aYou already know that group!{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->tier >= 2)
{
if ( ( group_table[gn].rating[ch->class] <= 0 ) && ( group_table[gn].rating[ch->clasb] <= 0 ) ) {
act("$N tells you '{MThat group is beyond your powers.{x'", ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->train < group_table[gn].rating[ch->class]) {
act("$N tells you '{WYou are not yet ready for that group.{x'", ch,NULL,trainer,TO_CHAR);
return;
}
}
else {
if ( ( group_table[gn].rating[ch->class] <= 0 ) && ( group_table[gn].rating[ch->clasb] <= 0 ) ) {
act("$N tells you '{mThat group is beyond your powers.{x'", ch,NULL,trainer,TO_CHAR);
return;
}
if ( ( ch->train < group_table[gn].rating[ch->class] ) && ( ch->train < group_table[gn].rating[ch->clasb] ) ) {
act("$N tells you '{wYou are not yet ready for that group.{x'", 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);
if (ch->pcdata->tier >= 2)
{
ch->train -= group_table[gn].rating[ch->class];
} else {
int tmptrain = 999;
if (group_table[gn].rating[ch->class] > 0)
tmptrain = group_table[gn].rating[ch->class];
if (group_table[gn].rating[ch->clasb] > 0)
tmptrain = UMIN(tmptrain, group_table[gn].rating[ch->clasb]);
ch->train -= tmptrain;
}
return;
}
sn = skill_lookup(argument);
if (sn > -1)
{
if (skill_table[sn].spell_fun != spell_null)
{
act("$N tells you '{aYou must learn the full group.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->learned[sn])
{
act("$N tells you '{aYou already know that skill!{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->pcdata->tier != 2)
{
if (skill_table[sn].rating[ch->class] <= 0)
{
act("$N tells you '{aThat skill is beyond your powers.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if (ch->train < skill_table[sn].rating[ch->class])
{
act("$N tells you '{aYou are not yet ready for that skill.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
} else {
if ( ( skill_table[sn].rating[ch->class] <= 0 )
&& ( skill_table[sn].rating[ch->clasb] <= 0 ) )
{
act("$N tells you '{aThat skill is beyond your powers.{x'",
ch,NULL,trainer,TO_CHAR);
return;
}
if ( ( ch->train < skill_table[sn].rating[ch->class] )
&& ( ch->train < skill_table[sn].rating[ch->clasb] ) )
{
act("$N tells you '{aYou are not yet ready for that skill.{x'",
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);
if (ch->pcdata->tier >= 2)
{
ch->train -= skill_table[sn].rating[ch->class];
} else {
int tmptrain = 999;;
if (skill_table[sn].rating[ch->class] > 0)
tmptrain = skill_table[sn].rating[ch->class];
if (skill_table[sn].rating[ch->clasb] > 0)
tmptrain = UMIN(tmptrain, skill_table[sn].rating[ch->clasb]);
ch->train -= tmptrain;
}
return;
}
act("$N tells you '{aI do not understand...{x'",ch,NULL,trainer,TO_CHAR);
}
/* RT spells and skills show the players spells (or skills) */
void do_spells(CHAR_DATA *ch, char *argument)
{
char spell_list[LEVEL_HERO][MSL];
char spell_columns[LEVEL_HERO];
int sn,lev,mana;
bool found = FALSE;
bool nfound = FALSE;
char buf[MSL];
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;
nfound = FALSE;
if (skill_table[sn].skill_level[ch->class] < LEVEL_HERO &&
skill_table[sn].spell_fun != spell_null &&
ch->pcdata->learned[sn] > 0)
{
nfound = TRUE;
found = TRUE;
lev = skill_table[sn].skill_level[ch->class];
if (ch->level < lev)
sprintf(buf,"{R%-18s n/a {x", skill_table[sn].name);
else
{
mana = UMAX(skill_table[sn].min_mana, 100/(2 + ch->level - lev));
sprintf(buf,"{R%-18s %3d mana {x",skill_table[sn].name,mana);
}
}
if (ch->pcdata->tier == 2)
{
if (skill_table[sn].skill_level[ch->clasb] < LEVEL_HERO
&& skill_table[sn].spell_fun != spell_null
&& ch->pcdata->learned[sn] > 0)
{
int nlev;
if (!nfound)
lev = 999;
found = TRUE;
nlev = skill_table[sn].skill_level[ch->clasb];
if (ch->level < nlev && nlev < lev)
{
sprintf(buf,"{B%-18s n/a {x", skill_table[sn].name);
}
else if (nlev < lev)
{
mana = UMAX(skill_table[sn].min_mana,100/(2+ch->level-nlev));
sprintf(buf,"{B%-18s %3d mana {x",skill_table[sn].name,mana);
}
if (nfound)
{
if (ch->level < nlev)
{
if (nlev < lev)
{
sprintf(buf,"{G%-18s n/a {x", skill_table[sn].name);
}
} else {
if (nlev < lev)
{
mana = UMAX(skill_table[sn].min_mana, 100/(2 + ch->level - nlev));
sprintf(buf,"{G%-18s %3d mana {x",skill_table[sn].name,mana);
}
}
}
if (nlev < lev)
lev = nlev;
nfound = TRUE;
}
}
if (nfound)
{
if (spell_list[lev][0] == '\0')
sprintf(spell_list[lev],"\n\r{MLevel %2d: {x%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_bskills(CHAR_DATA *ch, char *argument)
{
char skill_list[LEVEL_HERO][MSL];
char skill_columns[LEVEL_HERO];
int sn,lev;
bool found = FALSE;
bool nfound = FALSE;
char buf[MSL];
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;
nfound = FALSE;
if (skill_table[sn].skill_level[ch->clasb] < LEVEL_HERO &&
skill_table[sn].spell_fun == spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
nfound = TRUE;
lev = skill_table[sn].skill_level[ch->clasb];
if (ch->level < lev)
sprintf(buf,"{R%-18s n/a {x", skill_table[sn].name);
else
sprintf(buf,"{R%-18s %3d%% {x",skill_table[sn].name,
ch->pcdata->learned[sn]);
}
if (ch->pcdata->tier == 2)
{
if (skill_table[sn].skill_level[ch->clasb] < LEVEL_HERO &&
skill_table[sn].spell_fun == spell_null &&
ch->pcdata->learned[sn] > 0)
{
int nlev;
if (!nfound)
lev = 999;
found = TRUE;
nlev = skill_table[sn].skill_level[ch->clasb];
if (ch->level < nlev)
{
sprintf(buf,"{B%-18s n/a {x", skill_table[sn].name);
} else {
sprintf(buf,"{B%-18s %3d%% {x",skill_table[sn].name,
ch->pcdata->learned[sn]);
}
if (nlev < lev)
lev = nlev;
if (nfound)
{
if (ch->level < lev)
{
sprintf(buf,"{G%-18s n/a {x", skill_table[sn].name);
} else {
sprintf(buf,"{G%-18s %3d%% {x",skill_table[sn].name,
ch->pcdata->learned[sn]);
}
}
nfound = TRUE;
}
}
if (nfound)
{
if (skill_list[lev][0] == '\0')
sprintf(skill_list[lev],"\n\r{MLevel %2d: {x%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);
}
void do_skills(CHAR_DATA *ch, char *argument)
{
char skill_list[LEVEL_HERO][MSL];
char skill_columns[LEVEL_HERO];
int sn,lev;
bool found = FALSE;
bool nfound = FALSE;
char buf[MSL];
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;
nfound = FALSE;
if (skill_table[sn].skill_level[ch->clasb] < LEVEL_HERO &&
skill_table[sn].spell_fun == spell_null &&
ch->pcdata->learned[sn] > 0)
{
found = TRUE;
nfound = TRUE;
lev = skill_table[sn].skill_level[ch->clasb];
if (ch->level < lev)
sprintf(buf,"{R%-18s n/a {x", skill_table[sn].name);
else
sprintf(buf,"{R%-18s %3d%% {x",skill_table[sn].name,
ch->pcdata->learned[sn]);
}
if (ch->pcdata->tier == 2)
{
if (skill_table[sn].skill_level[ch->clasb] < LEVEL_HERO &&
skill_table[sn].spell_fun == spell_null &&
ch->pcdata->learned[sn] > 0)
{
int nlev;
if (!nfound)
lev = 999;
found = TRUE;
nlev = skill_table[sn].skill_level[ch->clasb];
if (ch->level < nlev)
{
sprintf(buf,"{B%-18s n/a {x", skill_table[sn].name);
} else {
sprintf(buf,"{B%-18s %3d%% {x",skill_table[sn].name,
ch->pcdata->learned[sn]);
}
if (nlev < lev)
lev = nlev;
if (nfound)
{
if (ch->level < lev)
{
sprintf(buf,"{G%-18s n/a {x", skill_table[sn].name);
} else {
sprintf(buf,"{G%-18s %3d%% {x",skill_table[sn].name,
ch->pcdata->learned[sn]);
}
}
nfound = TRUE;
}
}
if (nfound)
{
if (skill_list[lev][0] == '\0')
sprintf(skill_list[lev],"\n\r{MLevel %2d: {x%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[100];
int gn,sn,col;
if (IS_NPC(ch))
return;
col = 0;
sprintf(buf,"{M%-18s {Y%-5s {M%-18s {Y%-5s {M%-18s {Y%-5s{x\n\r",
"group","cp","group","cp","group","cp");
send_to_char(buf,ch);
for (gn = 0; gn < MAX_GROUP; gn++)
{
bool found = FALSE;
int tmpcost = 999;
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)
{
found = TRUE;
sprintf(buf,"{R%-18s %-5d {x",group_table[gn].name,
group_table[gn].rating[ch->class]);
tmpcost = group_table[gn].rating[ch->class];
}
if (ch->pcdata->tier == 2)
{
if (!ch->gen_data->group_chosen[gn]
&& !ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->clasb] > 0)
{
sprintf(buf,"{B%-18s %-5d {x",group_table[gn].name,
group_table[gn].rating[ch->clasb]);
if (group_table[gn].rating[ch->clasb] < tmpcost)
{
tmpcost = group_table[gn].rating[ch->clasb];
}
if (found)
{
sprintf(buf,"{G%-18s %-5d {x",group_table[gn].name,
tmpcost);
}
found = TRUE;
}
}
if (found)
{
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,"{M%-18s {Y%-5s {M%-18s {Y%-5s {M%-18s {Y%-5s{x\n\r",
"skill","cp","skill","cp","skill","cp");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
bool found = FALSE;
int tmpcost = 999;
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)
{
found = TRUE;
sprintf(buf,"{R%-18s %-5d {x",skill_table[sn].name,
skill_table[sn].rating[ch->class]);
tmpcost = skill_table[sn].rating[ch->class];
}
if (ch->pcdata->tier == 2)
{
if (!ch->gen_data->skill_chosen[sn]
&& ch->pcdata->learned[sn] == 0
&& skill_table[sn].spell_fun == spell_null
&& skill_table[sn].rating[ch->clasb] > 0)
{
sprintf(buf,"{B%-18s %-5d {x",skill_table[sn].name,
skill_table[sn].rating[ch->clasb]);
if (skill_table[sn].rating[ch->clasb] < tmpcost)
{
tmpcost = skill_table[sn].rating[ch->clasb];
}
if (found)
{
sprintf(buf,"{G%-18s %-5d {x",skill_table[sn].name,
tmpcost);
}
found = TRUE;
}
}
if (found)
{
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 per level: %ld\n\r",
exp_per_level(ch,ch->gen_data->points_chosen));
send_to_char(buf,ch);
return;
}
void list_group_chosen(CHAR_DATA *ch)
{
char buf[100];
int gn,sn,col;
if (IS_NPC(ch))
return;
col = 0;
sprintf(buf,"{M%-18s {Y%-5s {M%-18s {Y%-5s {M%-18s {Y%-5s{x\n\r",
"group","cp","group","cp","group","cp");
send_to_char(buf,ch);
for (gn = 0; gn < MAX_GROUP; gn++)
{
bool found = FALSE;
if (group_table[gn].name == NULL)
break;
if (ch->gen_data->group_chosen[gn]
&& group_table[gn].rating[ch->class] > 0)
{
found = TRUE;
sprintf(buf,"{R%-18s %-5d {x",group_table[gn].name,
group_table[gn].rating[ch->class]);
}
if (ch->pcdata->tier == 2)
{
if (ch->gen_data->group_chosen[gn]
&& group_table[gn].rating[ch->clasb] > 0)
{
sprintf(buf,"{B%-18s %-5d {x",group_table[gn].name,
group_table[gn].rating[ch->clasb]);
if (found)
{
sprintf(buf,"{G%-18s %-5d {x",group_table[gn].name,
UMIN(group_table[gn].rating[ch->class], group_table[gn].rating[ch->clasb]));
}
found = TRUE;
}
}
if (found)
{
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,"{M%-18s {Y%-5s {M%-18s {Y%-5s {M%-18s {Y%-5s{x\n\r",
"skill","cp","skill","cp","skill","cp");
send_to_char(buf,ch);
for (sn = 0; sn < MAX_SKILL; sn++)
{
bool found = FALSE;
if (skill_table[sn].name == NULL)
break;
if (ch->gen_data->skill_chosen[sn]
&& skill_table[sn].rating[ch->class] > 0)
{
found = TRUE;
sprintf(buf,"{R%-18s %-5d {x",skill_table[sn].name,
skill_table[sn].rating[ch->class]);
}
if (ch->pcdata->tier == 2)
{
if (ch->gen_data->skill_chosen[sn]
&& skill_table[sn].rating[ch->clasb] > 0)
{
sprintf(buf,"{B%-18s %-5d {x",skill_table[sn].name,
skill_table[sn].rating[ch->clasb]);
}
if (found)
{
sprintf(buf,"{G%-18s %-5d {x",skill_table[sn].name,
skill_table[sn].rating[ch->clasb]);
}
found = TRUE;
}
if (found)
{
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,"{MCreation points: {C%d{x\n\r",ch->gen_data->points_chosen);
send_to_char(buf,ch);
sprintf(buf,"{MExperience per level: {C%ld{x\n\r",
exp_per_level(ch,ch->gen_data->points_chosen));
send_to_char(buf,ch);
return;
}
long exp_per_level(CHAR_DATA *ch, int points)
{
long expl,inc;
if (IS_NPC(ch))
return 1000;
expl = 1000;
inc = 500;
if (points < 40)
{
if (ch->pcdata->tier != 2)
{
return 1000 * pc_race_table[ch->race].class_mult[ch->class]/100;
} else {
long rpoint;
rpoint = ( ( ( 1000 * pc_race_table[ch->race].class_mult[ch->class]/100 )
+ ( 1000 * pc_race_table[ch->race].class_mult[ch->class]/100 )
+ ( 1000 * pc_race_table[ch->race].class_mult[ch->clasb]/100 ) )
/ 3 );
return (long)rpoint;
}
}
/* processing */
points -= 40;
while (points > 9)
{
expl += (long)inc;
points -= 10;
if (points > 9)
{
expl += (long)inc;
inc *= 2;
points -= 10;
}
}
expl += (long)points * (long)inc / 10;
if (ch->pcdata->tier != 2)
{
return (long)expl * (long)pc_race_table[ch->race].class_mult[ch->class]/100;
} else {
long rpoint;
rpoint = ( ( ( (long)expl * (long)pc_race_table[ch->race].class_mult[ch->class]/100 )
+ ( (long)expl * (long)pc_race_table[ch->race].class_mult[ch->class]/100 )
+ ( (long)expl * (long)pc_race_table[ch->race].class_mult[ch->clasb]/100 ) )
/ 3 );
return (long)rpoint;
}
}
/* this procedure handles the input parsing for the skill generator */
bool parse_gen_groups(CHAR_DATA *ch,char *argument)
{
char arg[MIL];
char buf[100];
int gn,sn,i;
if (argument[0] == '\0')
return FALSE;
if (IS_NPC(ch))
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;
}
gn = group_lookup(argument);
if (gn != -1)
{
bool found = FALSE;
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)
{
found = TRUE;
}
if (ch->pcdata->tier == 2)
if (group_table[gn].rating[ch->clasb] > 0)
found = FALSE;
if (found)
{
send_to_char("That group is not available.\n\r",ch);
return TRUE;
}
found = FALSE;
if (exp_per_level(ch,ch->gen_data->points_chosen+group_table[gn].rating[ch->class]) > 500000)
{
found = TRUE;
send_to_char("That will take you over the Exp/Level limit.\n\r",ch);
return TRUE;
}
if (ch->pcdata->tier == 2)
if (exp_per_level(ch,ch->gen_data->points_chosen+group_table[gn].rating[ch->clasb]) <= 500000)
found = FALSE;
if (found)
{
send_to_char("That will take you over the Exp/Level limit.\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;
if (ch->pcdata->tier != 2)
{
ch->gen_data->points_chosen += group_table[gn].rating[ch->class];
} else {
if (group_table[gn].rating[ch->class] < 1)
{
ch->gen_data->points_chosen += group_table[gn].rating[ch->clasb];
} else if (group_table[gn].rating[ch->clasb] < 1)
{
ch->gen_data->points_chosen += group_table[gn].rating[ch->class];
} else {
ch->gen_data->points_chosen += UMIN(
group_table[gn].rating[ch->class],
group_table[gn].rating[ch->clasb]);
}
}
gn_add(ch,gn);
if (ch->pcdata->tier != 2)
{
ch->pcdata->points += group_table[gn].rating[ch->class];
} else {
if (group_table[gn].rating[ch->class] < 1)
{
ch->pcdata->points += group_table[gn].rating[ch->clasb];
} else if (group_table[gn].rating[ch->clasb] < 1)
{
ch->pcdata->points += group_table[gn].rating[ch->class];
} else {
ch->pcdata->points += UMIN(
group_table[gn].rating[ch->class],
group_table[gn].rating[ch->clasb]);
}
}
return TRUE;
}
sn = skill_lookup(argument);
if (sn != -1)
{
bool found = FALSE;
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)
found = TRUE;
if (ch->pcdata->tier == 2)
if (skill_table[sn].rating[ch->class] > 0)
found = FALSE;
if (skill_table[sn].spell_fun != spell_null)
found = TRUE;
if (found)
{
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;
if (ch->pcdata->tier != 2)
{
ch->gen_data->points_chosen += skill_table[sn].rating[ch->class];
} else {
if (skill_table[sn].rating[ch->class] < 1)
{
ch->gen_data->points_chosen += skill_table[sn].rating[ch->clasb];
} else if (skill_table[sn].rating[ch->clasb] < 1)
{
ch->gen_data->points_chosen += skill_table[sn].rating[ch->class];
} else {
ch->gen_data->points_chosen += UMIN(
skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]);
}
}
ch->pcdata->learned[sn] = 1;
if (ch->pcdata->tier != 2)
{
ch->pcdata->points += skill_table[sn].rating[ch->class];
} else {
if (skill_table[sn].rating[ch->class] < 1)
{
ch->pcdata->points += skill_table[sn].rating[ch->clasb];
} else if (skill_table[sn].rating[ch->clasb] < 1)
{
ch->pcdata->points += skill_table[sn].rating[ch->class];
} else {
ch->pcdata->points += UMIN(
skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]);
}
}
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;
if (ch->pcdata->tier != 2)
{
ch->gen_data->points_chosen -= group_table[gn].rating[ch->class];
} else {
if (group_table[gn].rating[ch->class] < 1)
{
ch->gen_data->points_chosen -= group_table[gn].rating[ch->clasb];
} else if (group_table[gn].rating[ch->clasb] < 1)
{
ch->gen_data->points_chosen -= group_table[gn].rating[ch->class];
} else {
ch->gen_data->points_chosen -= UMIN(
group_table[gn].rating[ch->class],
group_table[gn].rating[ch->clasb]);
}
}
gn_remove(ch,gn);
for (i = 0; i < MAX_GROUP; i++)
{
if (ch->gen_data->group_chosen[gn])
gn_add(ch,gn);
}
if (ch->pcdata->tier != 2)
{
ch->pcdata->points -= group_table[gn].rating[ch->class];
} else {
if (group_table[gn].rating[ch->class] < 1)
{
ch->pcdata->points -= group_table[gn].rating[ch->clasb];
} else if (group_table[gn].rating[ch->clasb] < 1)
{
ch->pcdata->points -= group_table[gn].rating[ch->class];
} else {
ch->pcdata->points -= UMIN(
group_table[gn].rating[ch->class],
group_table[gn].rating[ch->clasb]);
}
}
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;
if (ch->pcdata->tier != 2)
{
ch->gen_data->points_chosen -= skill_table[sn].rating[ch->class];
} else {
if (skill_table[sn].rating[ch->class] < 1)
{
ch->gen_data->points_chosen -= skill_table[sn].rating[ch->clasb];
} else if (skill_table[sn].rating[ch->clasb] < 1)
{
ch->gen_data->points_chosen -= skill_table[sn].rating[ch->class];
} else {
ch->gen_data->points_chosen -= UMIN(
skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]);
}
}
ch->pcdata->learned[sn] = 0;
if (ch->pcdata->tier != 2)
{
ch->pcdata->points -= skill_table[sn].rating[ch->class];
} else {
if (skill_table[sn].rating[ch->class] < 1)
{
ch->pcdata->points -= skill_table[sn].rating[ch->clasb];
} else if (skill_table[sn].rating[ch->clasb] < 1)
{
ch->pcdata->points -= skill_table[sn].rating[ch->class];
} else {
ch->pcdata->points -= UMIN(
skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]);
}
}
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[100];
int gn,sn,col;
if (IS_NPC(ch))
return;
col = 0;
send_to_char("Use the class command (help class) for a listing\n\r",ch);
send_to_char("more in tune with your current character.\n\r\n\r",ch);
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 );
}
/* shows all groups, or the sub-members of a group available to your class*/
void do_class(CHAR_DATA *ch, char *argument)
{
char arg[MIL];
char buf[MSL];
int gn,sn,tn,col,class,clasb;
bool found = FALSE;
if (IS_NPC(ch))
return;
col = 0;
argument = one_argument(argument,arg);
class = class_lookup(arg);
if (class != -1)
argument = one_argument(argument,arg);
clasb = -1;
if (arg[0] == '\0')
{ /* show all groups */
send_to_char( "Groups you currently have:\n\r", ch );
send_to_char( "--------------------------\n\r", ch );
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);
buf[0] = '\0';
return;
}
if (!str_cmp(arg,"all")) /* show all groups */
{
if (class == -1)
{
send_to_char( "{MGroups available to your character:{x\n\r", ch );
class = ch->class;
if (ch->pcdata->tier == 2)
clasb = ch->clasb;
}
else
send_to_char( "{M Groups available to this class:{x\n\r", ch );
send_to_char( "-----------------------------------\n\r", ch );
for (gn = 0; gn < MAX_GROUP; gn++)
{
found = FALSE;
if (group_table[gn].name == NULL)
break;
if (group_table[gn].rating[class] > 0)
{
found = TRUE;
sprintf(buf,"{R%-20s {x",group_table[gn].name);
}
if ( ( ch->pcdata->tier == 2 ) && ( clasb != -1 ) )
{
if (group_table[gn].rating[clasb] > 0)
{
sprintf(buf,"{B%-20s {x",group_table[gn].name);
if (found)
{
sprintf(buf,"{G%-20s {x",group_table[gn].name);
}
found = TRUE;
}
}
if (found)
{
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 );
buf[0] = '\0';
return;
}
if (!str_cmp(arg,"skill")) /* show all skills */
{
if (class == -1)
{
send_to_char( "{MSkills available to your character:{x\n\r", ch );
class = ch->class;
if (ch->pcdata->tier == 2)
clasb = ch->clasb;
}
else
send_to_char( "{M Skills available to this class:{x\n\r", ch );
send_to_char( "-----------------------------------\n\r", ch );
send_to_char( "{MLevel{x-{YSkill{x--------------- {YLevel{x-{YSkill{x---------------\n\r", ch );
for (sn = 0; sn < MAX_SKILL; sn++)
{
found = FALSE;
if (skill_table[sn].name == NULL)
break;
if (skill_table[sn].rating[class] > 0)
{
found = TRUE;
sprintf(buf,"{R%-5d %-20s {x",
skill_table[sn].skill_level[class],skill_table[sn].name);
}
if ( ( ch->pcdata->tier == 2 ) && ( clasb != -1 ) )
{
if (skill_table[sn].rating[clasb] > 0 )
{
sprintf(buf,"{B%-5d %-20s {x",
skill_table[sn].skill_level[clasb],skill_table[sn].name);
if (found)
{
sprintf(buf,"{G%-5d %-20s {x",
UMIN(skill_table[sn].skill_level[class],
skill_table[sn].skill_level[clasb]),
skill_table[sn].name);
}
found = TRUE;
}
}
if (skill_table[sn].spell_fun != spell_null)
found = FALSE;
if (found)
{
send_to_char(buf,ch);
if (++col % 2 == 0)
send_to_char("\n\r",ch);
}
}
if (col % 2 != 0)
send_to_char("\n\r",ch);
buf[0] = '\0';
return;
}
/* show the sub-members of a group */
gn = group_lookup(arg);
if (gn == -1)
{
send_to_char("No group of that name exists.\n\r",ch);
send_to_char("Type 'class all' for a full listing.\n\r",ch);
return;
}
if ( (ch->pcdata->tier != 2) || (class != -1) )
{
if (class == -1)
class = ch->class;
if (group_table[gn].rating[class] < 1)
{
send_to_char("This class does not get that group.\n\r",ch);
send_to_char("Type 'class all' for a full listing.\n\r",ch);
return;
}
} else if (class != -1)
{
if (group_table[gn].rating[class] < 1)
{
send_to_char("This class does not get that group.\n\r",ch);
send_to_char("Type 'class all' for a full listing.\n\r",ch);
return;
}
} else {
class = ch->class;
clasb = ch->clasb;
if ( ( group_table[gn].rating[class] < 1 )
&& ( group_table[gn].rating[clasb] < 1 ) )
{
send_to_char("This character does not get that group.\n\r",ch);
send_to_char("Type 'class all' for a full listing.\n\r",ch);
return;
}
}
send_to_char( "{MSpells available in this group:{x\n\r", ch );
send_to_char( "-------------------------------\n\r", ch );
send_to_char( "{MLevel{x-{YSpell{x--------------- {MLevel{x-{YSpell{x---------------\n\r", ch );
if (class == -1)
{
class = ch->class;
if (ch->pcdata->tier == 2)
clasb = ch->clasb;
}
for (sn = 0; sn < MAX_IN_GROUP; sn++)
{
found = FALSE;
if (group_table[gn].spells[sn] == NULL)
break;
if ( ( tn = spell_avail_class( ch, group_table[gn].spells[sn] ) ) >= 0)
{
found = TRUE;
sprintf(buf,"{R%-5d %-20s {x",
skill_table[tn].skill_level[class], group_table[gn].spells[sn]);
}
if (ch->pcdata->tier == 2)
{
if ( ( tn = spell_avail_clasb( ch, group_table[gn].spells[sn] ) ) >= 0)
{
sprintf(buf,"{B%-5d %-20s {x",
skill_table[tn].skill_level[clasb], group_table[gn].spells[sn]);
}
if (found)
{
sprintf(buf,"{G%-5d %-20s {x",
UMIN(skill_table[tn].skill_level[class],
skill_table[tn].skill_level[clasb]),
group_table[gn].spells[sn]);
}
found = TRUE;
}
if (found)
{
send_to_char(buf,ch);
if (++col % 2 == 0)
send_to_char("\n\r",ch);
}
}
buf[0] = '\0';
if ( col % 2 != 0 )
send_to_char( "\n\r", ch );
}
int spell_avail( CHAR_DATA *ch, const char *name )
{
/* checks to see if a spell is available to either class */
int sn, found = -1;
if (IS_NPC(ch))
return skill_lookup(name);
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if (skill_table[sn].name == NULL)
break;
if (LOWER(name[0]) == LOWER(skill_table[sn].name[0])
&& !str_prefix(name,skill_table[sn].name))
{
if (skill_table[sn].skill_level[ch->class] <= LEVEL_HERO)
return sn;
if (ch->pcdata->tier == 2)
{
if (skill_table[sn].skill_level[ch->clasb] <= LEVEL_HERO)
return sn;
}
}
}
return found;
}
int spell_avail_class( CHAR_DATA *ch, const char *name )
{
/* checks to see if a spell is available to a primary class */
int sn, found = -1;
if (IS_NPC(ch))
return skill_lookup(name);
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if (skill_table[sn].name == NULL)
break;
if (LOWER(name[0]) == LOWER(skill_table[sn].name[0])
&& !str_prefix(name,skill_table[sn].name))
{
if (skill_table[sn].skill_level[ch->class] <= LEVEL_HERO)
return sn;
}
}
return found;
}
int spell_avail_clasb( CHAR_DATA *ch, const char *name )
{
/* checks to see if a spell is available to a secondary class */
int sn, found = -1;
if (IS_NPC(ch))
return skill_lookup(name);
if (ch->pcdata->tier != 2)
return found;
for ( sn = 0; sn < MAX_SKILL; sn++ )
{
if (skill_table[sn].name == NULL)
break;
if (LOWER(name[0]) == LOWER(skill_table[sn].name[0])
&& !str_prefix(name,skill_table[sn].name))
{
if (skill_table[sn].skill_level[ch->clasb] <= LEVEL_HERO)
return sn;
}
}
return found;
}
/* checks for skill improvement */
void check_improve( CHAR_DATA *ch, int sn, bool success, int multiplier )
{
int chance;
char buf[100];
bool found = FALSE;
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)
{
found = TRUE;
}
if (ch->pcdata->tier != 2)
{
if (found)
return; /* skill is not known */
} else if (found) {
if (ch->level < skill_table[sn].skill_level[ch->clasb]
|| skill_table[sn].rating[ch->clasb] == 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;
if (ch->pcdata->tier != 2)
{
chance /= ( multiplier
* skill_table[sn].rating[ch->class]
* 4);
} else {
if (skill_table[sn].rating[ch->clasb] < 1)
{
chance /= ( multiplier
* skill_table[sn].rating[ch->class]
* 4);
} else if (skill_table[sn].rating[ch->class] < 1)
{
chance /= ( multiplier
* skill_table[sn].rating[ch->clasb]
* 4);
} else
{
chance /= ( multiplier
* UMIN(skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb])
* 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);
if ( global_prq ){
ch->pcdata->learned[sn]++;
ch->pcdata->learned[sn]++;
ch->pcdata->learned[sn]++;
ch->pcdata->learned[sn]++;
} else {
ch->pcdata->learned[sn]++;
}
if (!IS_SET(ch->act, PLR_LQUEST))
{
if (ch->pcdata->tier != 2)
{
gain_exp(ch,2 * skill_table[sn].rating[ch->class]);
} else
{
if (skill_table[sn].rating[ch->clasb] < 1)
{
gain_exp(ch,2 * skill_table[sn].rating[ch->class]);
} else if (skill_table[sn].rating[ch->class] < 1)
{
gain_exp(ch,2 * skill_table[sn].rating[ch->clasb]);
} else
{
gain_exp(ch,2 * UMIN(skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]));
}
}
}
}
}
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);
if ( global_prq ){
ch->pcdata->learned[sn] += number_range(8,16);
ch->pcdata->learned[sn] = UMIN(ch->pcdata->learned[sn],100);
} else {
ch->pcdata->learned[sn] += number_range(1,3);
ch->pcdata->learned[sn] = UMIN(ch->pcdata->learned[sn],100);
}
if (!IS_SET(ch->act, PLR_LQUEST))
{
if (ch->pcdata->tier != 2)
{
gain_exp(ch,2 * skill_table[sn].rating[ch->class]);
} else
{
if (skill_table[sn].rating[ch->clasb] < 1)
{
gain_exp(ch,2 * skill_table[sn].rating[ch->class]);
} else if (skill_table[sn].rating[ch->class] < 1)
{
gain_exp(ch,2 * skill_table[sn].rating[ch->clasb]);
} else
{
gain_exp(ch,2 * UMIN(skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]));
}
}
}
}
}
}
/* 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)
{
if (ch->pcdata->tier != 2)
{
ch->pcdata->points += skill_table[sn].rating[ch->class];
} else
{
if (skill_table[sn].rating[ch->clasb] < 1)
{
ch->pcdata->points += skill_table[sn].rating[ch->class];
} else if (skill_table[sn].rating[ch->class] < 1)
{
ch->pcdata->points += skill_table[sn].rating[ch->clasb];
} else
{
ch->pcdata->points += UMIN(skill_table[sn].rating[ch->class],
skill_table[sn].rating[ch->clasb]);
}
}
}
}
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)
{
if (ch->pcdata->tier != 2)
{
ch->pcdata->points += group_table[gn].rating[ch->class];
} else
{
if (group_table[gn].rating[ch->clasb] < 1)
{
ch->pcdata->points += group_table[gn].rating[ch->class];
} else if (group_table[gn].rating[ch->class] < 1)
{
ch->pcdata->points += group_table[gn].rating[ch->clasb];
} else
{
ch->pcdata->points += UMIN(group_table[gn].rating[ch->class],
group_table[gn].rating[ch->clasb]);
}
}
}
}
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 */
}
}