/***************************************************************************
* 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 Rom24/doc/rom.license *
***************************************************************************/
/***************************************************************************
* ROT 1.4 is copyright 1996-1997 by Russ Walsh *
* By using this code, you have agreed to follow the terms of the *
* ROT license, in the file doc/rot.license *
***************************************************************************/
#if defined(macintosh)
#include <types.h>
#include <time.h>
#else
#include <sys/types.h>
#include <sys/time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "magic.h"
/* used to get new skills */
CH_CMD ( do_gain )
{
char buf[MAX_STRING_LENGTH];
char arg[MAX_INPUT_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, "{aPardon me?{x" );
return;
}
if ( !str_prefix ( arg, "list" ) )
{
int col;
col = 0;
sprintf ( buf, "{c%-18s {W%-5s {c%-18s {W%-5s {c%-18s {W%-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, "{c%-18s {W%-5d ", group_table[gn].name,
group_table[gn].rating[ch->class] );
send_to_char ( buf, ch );
if ( ++col % 3 == 0 )
send_to_char ( "{x\n\r", ch );
}
}
if ( col % 3 != 0 )
send_to_char ( "\n\r", ch );
send_to_char ( "\n\r", ch );
col = 0;
sprintf ( buf,
"{D%-5s {c%-16s {W%-5s {D%-5s {c%-16s {W%-5s {D%-5s {c%-16s {W%-5s{x\n\r",
"level", "skill", "cost", "level", "skill", "cost", "level",
"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, "{w[{D%3d{w] {c%-18s {W%-3d{x ",
skill_table[sn].skill_level[ch->class],
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 < 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 -= 6;
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 += 6;
return;
}
if ( !str_prefix ( arg, "points" ) )
{
if ( ch->train < 2 )
{
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;
}
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 =
( 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 ( group_table[gn].rating[ch->class] <= 0 )
{
act ( "$N tells you '{aThat 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 '{aYou 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 );
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 '{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 ( 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;
}
/* 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 '{aI do not understand...{x'", ch, NULL, trainer,
TO_CHAR );
}
/* RT spells and skills show the players spells (or skills) */
CH_CMD ( do_spells )
{
char spell_list[LEVEL_ANCIENT][MAX_STRING_LENGTH];
char spell_columns[LEVEL_ANCIENT];
int sn, lev, mana;
bool found = FALSE;
char buf[MAX_STRING_LENGTH];
if ( IS_NPC ( ch ) )
return;
/* initilize data */
for ( lev = 0; lev < LEVEL_ANCIENT; 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_ANCIENT &&
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, "{W%-19s{g n/a ", skill_table[sn].name );
else
{
mana =
UMAX ( skill_table[sn].min_mana,
100 / ( 2 + ch->level - lev ) );
sprintf ( buf, "{W%-18s {g %3d {xmana ",
skill_table[sn].name, mana );
}
if ( spell_list[lev][0] == '\0' )
sprintf ( spell_list[lev], "\n\r{WLevel %4d: {g%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_ANCIENT; lev++ )
if ( spell_list[lev][0] != '\0' )
send_to_char ( spell_list[lev], ch );
send_to_char ( "\n\r", ch );
}
CH_CMD ( do_skills )
{
char skill_list[LEVEL_ANCIENT][MAX_STRING_LENGTH];
char skill_columns[LEVEL_ANCIENT];
int sn, lev;
bool found = FALSE;
char buf[MAX_STRING_LENGTH];
if ( IS_NPC ( ch ) )
return;
/* initilize data */
for ( lev = 0; lev < LEVEL_ANCIENT; 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_ANCIENT &&
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, "{W%-16s {gn/a{x ",
skill_table[sn].name );
else
sprintf ( buf, "{W%-16s {g%3d%%{x ",
skill_table[sn].name, ch->pcdata->learned[sn] );
if ( skill_list[lev][0] == '\0' )
sprintf ( skill_list[lev], "\n\r{WLevel %3d: {g%s{x", 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_ANCIENT; 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, "{c%-18s {W%-5s {c%-18s {W%-5s {c%-18s {W%-5s{x\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, "{c%-18s {W%-5d{x ", 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, "{c%-18s {W%-2s {c%-18s {W%-2s {c%-18s {W%-2s{x\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, "{c%-18s {W%-2d{x ", 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, "{WCreation points: {R%d{x\n\r", ch->pcdata->points );
send_to_char ( buf, ch );
sprintf ( buf, "{WExperience per level: {B%ld{x\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, "%-18s %-5s %-18s %-5s %-18s %-5s{x", "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{x ", 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, "{c%-18s {W%-2s {c%-18s {W%-2s {c%-18s {W%-2s", "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, "{c%-18s {W%-2d ", 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, "{WCreation points: {R%d{x\n\r",
ch->gen_data->points_chosen );
send_to_char ( buf, ch );
sprintf ( buf, "{WExperience per level: {B%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 )
return 1000 * pc_race_table[ch->race].class_mult[ch->class] / 100;
/* 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;
return ( long ) expl *( long ) 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[100];
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;
}
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 ( exp_per_level
( ch,
ch->gen_data->points_chosen +
group_table[gn].rating[ch->class] ) > 500000 )
{
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;
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 ( !str_cmp ( 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 );
// send_to_char("Sorry that is currently a buggy choice, but will be fixed soon.\n\r",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 */
CH_CMD ( do_groups )
{
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*/
CH_CMD ( do_class )
{
char buf[100];
int gn, sn, tn, col;
if ( IS_NPC ( ch ) )
return;
col = 0;
if ( argument[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 );
return;
}
if ( !str_cmp ( argument, "all" ) ) /* show all groups */
{
send_to_char ( "Groups available to your class:\n\r", ch );
send_to_char ( "-------------------------------\n\r", ch );
for ( gn = 0; gn < MAX_GROUP; gn++ )
{
if ( group_table[gn].name == NULL )
break;
if ( group_table[gn].rating[ch->class] > 0 )
{
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 'class all' for a full listing.\n\r", ch );
return;
}
send_to_char ( "Spells available in this group:\n\r", ch );
send_to_char ( "-------------------------------\n\r", ch );
send_to_char
( "{BLevel{x-{GSpell{x--------------- {BLevel{x-{GSpell{x---------------\n\r",
ch );
for ( sn = 0; sn < MAX_IN_GROUP; sn++ )
{
if ( group_table[gn].spells[sn] == NULL )
break;
if ( ( tn = spell_avail ( ch, group_table[gn].spells[sn] ) ) >= 0 )
{
sprintf ( buf, "{B%-5d {G%-20s ",
skill_table[tn].skill_level[ch->class],
group_table[gn].spells[sn] );
send_to_char ( buf, ch );
if ( ++col % 2 == 0 )
send_to_char ( "{x\n\r", ch );
}
}
if ( col % 2 != 0 )
send_to_char ( "{x\n\r", ch );
}
int spell_avail ( CHAR_DATA * ch, const char *name )
{
/* checks to see if a spell is available to a 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_ANCIENT )
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];
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 */
}
}
CH_CMD ( do_showskill )
{
char buf[MAX_STRING_LENGTH];
int skill, class = 0;
int i;
strcpy ( buf, "" );
/*argument = one_argument(argument,arg1); */
if ( argument[0] == '\0' )
{
send_to_char ( "Syntax: showskill [skill/spell]\n\r", ch );
return;
}
if ( ( skill = skill_lookup ( argument ) ) == -1 )
{
send_to_char ( "Skill not found.\n\r", ch );
return;
}
sprintf ( buf, "{xClasses and levels for %s{x:\n\r",
skill_table[skill].name );
send_to_char ( buf, ch );
/* send_to_char("{CClass Level Gain{x\n\r",ch); */
/* send_to_char("{C----------- ----- ----{x\n\r",ch); */
i = 0;
for ( class = 0; class < MAX_CLASS; class++ )
{
if ( skill_table[skill].skill_level[class] > LEVEL_ANCIENT )
continue;
i++;
/*sprintf(buf,"{m%-11s {c%5d {m%4d{x\n\r",class_table[class].name,
skill_table[skill].skill_level[class],
skill_table[skill].rating[class]); */
sprintf ( buf, "{C%-13s{x: {c%3d {x", class_table[class].name,
skill_table[skill].skill_level[class] );
buf[2] = UPPER ( buf[2] );
send_to_char ( buf, ch );
if ( i == 3 )
{
send_to_char ( "\n\r", ch );
i = 0;
}
}
return;
}
CH_CMD ( do_showclass )
{
char arg1[MAX_INPUT_LENGTH];
char buf[MAX_STRING_LENGTH];
int class, level, skill;
int i;
strcpy ( buf, "" );
argument = one_argument ( argument, arg1 );
if ( arg1[0] == '\0' )
{
send_to_char ( "Syntax: showclass [class]\n\r", ch );
return;
}
if ( ( class = class_lookup ( arg1 ) ) == -1 )
{
send_to_char ( "Class not found.\n\r", ch );
return;
}
sprintf ( buf, "{xSpells/skills for %s:{x\n\r", class_table[class].name );
send_to_char ( buf, ch );
i = 0;
for ( level = 1; level <= LEVEL_ANCIENT; level++ )
{
for ( skill = 0; skill < MAX_SKILL; skill++ )
{
if ( skill_table[skill].skill_level[class] != level )
continue;
i++;
sprintf ( buf, "{CLevel %3d: {x: {c%-20s{x ", level,
skill_table[skill].name );
send_to_char ( buf, ch );
if ( i == 2 )
{
send_to_char ( "\n\r", ch );
i = 0;
}
}
}
}