/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik Strfeldt, 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-1998 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@hypercube.org) *
* Gabrielle Taylor (gtaylor@hypercube.org) *
* Brian Moore (zump@rom.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Rom24/doc/rom.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 "interp.h"
#include "magic.h"
#include "recycle.h"
/* used to get new skills */
void do_gain (CHAR_DATA * ch, char *argument)
{
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_function (trainer, &do_say, "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 (!ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->class2] > 0
&& group_table[gn].rating[ch->class] < 0
&& ch->class2 != -1)
{
sprintf (buf, "%-18s %-5d ",
group_table[gn].name,
group_table[gn].rating[ch->class2]);
send_to_char (buf, ch);
if (++col % 3 == 0)
send_to_char ("\n\r", ch);
}
if (!ch->pcdata->group_known[gn]
&& group_table[gn].rating[ch->class3] > 0
&& group_table[gn].rating[ch->class] < 0
&& group_table[gn].rating[ch->class2] < 0
&& ch->class3 != -1)
{
sprintf (buf, "%-18s %-5d ",
group_table[gn].name,
group_table[gn].rating[ch->class3]);
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 (!ch->pcdata->learned[sn]
&& skill_table[sn].rating[ch->class2] > 0
&& skill_table[sn].rating[ch->class] < 0
&& ch->class2 != -1
&& skill_table[sn].spell_fun == spell_null)
{
sprintf (buf, "%-18s %-5d ",
skill_table[sn].name,
skill_table[sn].rating[ch->class2]);
send_to_char (buf, ch);
if (++col % 3 == 0)
send_to_char ("\n\r", ch);
}
if (!ch->pcdata->learned[sn]
&& skill_table[sn].rating[ch->class3] > 0
&& ch->class3 != -1
&& skill_table[sn].rating[ch->class] < 0
&& skill_table[sn].rating[ch->class2] < 0
&& skill_table[sn].spell_fun == spell_null)
{
sprintf (buf, "%-18s %-5d ",
skill_table[sn].name,
skill_table[sn].rating[ch->class3]);
send_to_char (buf, ch);
if (++col % 3 == 0)
send_to_char ("\n\r", ch);
}
if (!ch->pcdata->learned[sn]
&& skill_table[sn].rating[ch->class4] > 0
&& ch->class4 != -1
&& skill_table[sn].rating[ch->class] < 0
&& skill_table[sn].rating[ch->class2] < 0
&& skill_table[sn].rating[ch->class3] < 0
&& skill_table[sn].spell_fun == spell_null)
{
sprintf (buf, "%-18s %-5d ",
skill_table[sn].name,
skill_table[sn].rating[ch->class4]);
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 = 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 'You already know that group!'",
ch, NULL, trainer, TO_CHAR);
return;
}
if (group_table[gn].rating[ch->class] <= 0
&& group_table[gn].rating[ch->class2] <= 0
&& group_table[gn].rating[ch->class3] <= 0
&& group_table[gn].rating[ch->class4] <= 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]
&& ch->train < group_table[gn].rating[ch->class2]
&& ch->train < group_table[gn].rating[ch->class3]
&& ch->train < group_table[gn].rating[ch->class4])
{
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);
if (group_table[gn].rating[ch->class] >= 0){
ch->train -= group_table[gn].rating[ch->class]; return;}
if (group_table[gn].rating[ch->class2] >= 0) {
ch->train -= group_table[gn].rating[ch->class2]; return;}
if (group_table[gn].rating[ch->class3] >= 0) {
ch->train -= group_table[gn].rating[ch->class3]; return;}
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
&& skill_table[sn].rating[ch->class2] <= 0
&& skill_table[sn].rating[ch->class3] <= 0
&& skill_table[sn].rating[ch->class4] <= 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]
&& ch->train < skill_table[sn].rating[ch->class2]
&& ch->train < skill_table[sn].rating[ch->class3]
&& ch->train < skill_table[sn].rating[ch->class4])
{
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)
{
BUFFER *buffer;
char arg[MAX_STRING_LENGTH];
char spell_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
char spell_columns[LEVEL_HERO + 1];
int sn, level, min_lev = 1, max_lev = LEVEL_HERO, mana;
bool fAll = FALSE, found = FALSE;
char buf[MAX_STRING_LENGTH];
bool ShowColors = TRUE;
bool fWhite = FALSE;
bool fRed = FALSE;
bool fBlue = FALSE;
bool fGreen = FALSE;
bool fOrange = FALSE;
bool fBlack = FALSE;
if (IS_NPC (ch))
return;
argument = one_argument(argument,arg);
if (arg[0] != '\0')
{
if(!str_cmp(arg,"white"))
{
fWhite = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {7White{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_WHITE]);
}
if(!str_cmp(arg,"red"))
{
fRed = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {!Red{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_RED]);
}
if(!str_cmp(arg,"blue"))
{
fBlue = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {$Blue{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_BLUE]);
}
if(!str_cmp(arg,"green"))
{
fGreen = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {@Green{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_GREEN]);
}
if(!str_cmp(arg,"black"))
{
fBlack = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {8Black{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_BLACK]);
}
if(!str_cmp(arg,"orange"))
{
fOrange = TRUE;
ShowColors = FALSE;
printf_to_char(ch,"Proficiecy in {3Orange{x Magic: {&%d{x.\n\r",ch->magic[MAGIC_ORANGE]);
}
}
/*
fAll = TRUE;
if (str_prefix (argument, "all"))
{
argument = one_argument (argument, arg);
if (!is_number (arg))
{
send_to_char ("Arguments must be numerical or all.\n\r", ch);
return;
}
max_lev = atoi (arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf (buf, "Levels must be between 1 and %d.\n\r",
LEVEL_HERO);
send_to_char (buf, ch);
return;
}
if (argument[0] != '\0')
{
argument = one_argument (argument, arg);
if (!is_number (arg))
{
send_to_char ("Arguments must be numerical or all.\n\r",
ch);
return;
}
min_lev = max_lev;
max_lev = atoi (arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf (buf,
"Levels must be between 1 and %d.\n\r",
LEVEL_HERO);
send_to_char (buf, ch);
return;
}
if (min_lev > max_lev)
{
send_to_char ("That would be silly.\n\r", ch);
return;
}
}
}
}
*/
/* initialize data */
for (level = 0; level < LEVEL_HERO + 1; level++)
{
spell_columns[level] = 0;
spell_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if ((level = skill_table[sn].skill_level[ch->class]) < LEVEL_HERO + 1
&& (fAll || level <= ch->level)
&& level >= min_lev && level <= max_lev
&& skill_table[sn].spell_fun != spell_null
&& ch->pcdata->learned[sn] > 0)
{
found = TRUE;
level = skill_table[sn].skill_level[ch->class];
if (ch->level < level)
{
if(!ShowColors)
{
if(fWhite && !IS_SPELL_WHITE(sn))
continue;
else if(fRed && !IS_SPELL_RED(sn))
continue;
else if(fBlue && !IS_SPELL_BLUE(sn))
continue;
else if(fGreen && !IS_SPELL_GREEN(sn))
continue;
else if(fOrange && !IS_SPELL_ORANGE(sn))
continue;
else if(fBlack && !IS_SPELL_BLACK(sn))
continue;
}
if(IS_SPELL_WHITE(sn))
sprintf(buf,"{&%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_RED(sn))
sprintf(buf,"{!%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_BLUE(sn))
sprintf(buf,"{$%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_GREEN(sn))
sprintf(buf,"{@%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_ORANGE(sn))
sprintf(buf,"{3%-18s{x {#n/a{x ", skill_table[sn].name);
else if(IS_SPELL_BLACK(sn))
sprintf(buf,"{8%-18s{x {#n/a{x ", skill_table[sn].name);
else
sprintf(buf,"{C%-18s{x {#n/a{x ", skill_table[sn].name);
}
// sprintf (buf, "%-18s n/a ", skill_table[sn].name);
else
{
if(!ShowColors)
{
if(fWhite && !IS_SPELL_WHITE(sn))
continue;
else if(fRed && !IS_SPELL_RED(sn))
continue;
else if(fBlue && !IS_SPELL_BLUE(sn))
continue;
else if(fGreen && !IS_SPELL_GREEN(sn))
continue;
else if(fOrange && !IS_SPELL_ORANGE(sn))
continue;
else if(fBlack && !IS_SPELL_BLACK(sn))
continue;
}
mana = UMAX (skill_table[sn].min_mana,
100 / (2 + ch->level - level));
// sprintf (buf, "%-18s %3d mana ", skill_table[sn].name,
//mana);
if(IS_SPELL_WHITE(sn))//maybe put * 3 or 2 after [sn] --bree learned
sprintf(buf,"{&%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_BLUE(sn))
sprintf(buf,"{$%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_RED(sn))
sprintf(buf,"{!%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_GREEN(sn))
sprintf(buf,"{@%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_ORANGE(sn))
sprintf(buf,"{3%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
else if(IS_SPELL_BLACK(sn))
sprintf(buf,"{8%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
else
sprintf(buf,"{C%-18s {#%3d{x mana {@({&%d{@){x ",skill_table[sn].name,
mana,ch->pcdata->learned[sn]);
}
if (spell_list[level][0] == '\0')
sprintf(spell_list[level],"\n\r{BLevel{x {&%2d{x: %s",level,buf);
// sprintf (spell_list[level], "\n\rLevel %2d: %s", level, buf);
else
{ /* append */
if (++spell_columns[level] % 2 == 0)
strcat (spell_list[level], "\n\r ");
strcat (spell_list[level], buf);
}
}
}
/* return results */
if (!found)
{
send_to_char ("No spells found.\n\r", ch);
return;
}
buffer = new_buf ();
for (level = 0; level < LEVEL_HERO + 1; level++)
if (spell_list[level][0] != '\0')
add_buf (buffer, spell_list[level]);
//send_to_char(spell_list[level],ch);
add_buf (buffer, "\n\r");
page_to_char (buf_string (buffer), ch);
free_buf (buffer);
}
void do_skills (CHAR_DATA * ch, char *argument)
{
BUFFER *buffer;
char arg[MAX_INPUT_LENGTH];
char skill_list[LEVEL_HERO + 1][MAX_STRING_LENGTH];
char skill_columns[LEVEL_HERO + 1];
int sn, level, min_lev = 1, max_lev = LEVEL_HERO;
bool fAll = FALSE, found = FALSE;
char buf[MAX_STRING_LENGTH];
if (IS_NPC (ch))
return;
if (argument[0] != '\0')
{
fAll = TRUE;
if (str_prefix (argument, "all"))
{
argument = one_argument (argument, arg);
if (!is_number (arg))
{
send_to_char ("Arguments must be numerical or all.\n\r", ch);
return;
}
max_lev = atoi (arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf (buf, "Levels must be between 1 and %d.\n\r",
LEVEL_HERO);
send_to_char (buf, ch);
return;
}
if (argument[0] != '\0')
{
argument = one_argument (argument, arg);
if (!is_number (arg))
{
send_to_char ("Arguments must be numerical or all.\n\r",
ch);
return;
}
min_lev = max_lev;
max_lev = atoi (arg);
if (max_lev < 1 || max_lev > LEVEL_HERO)
{
sprintf (buf,
"Levels must be between 1 and %d.\n\r",
LEVEL_HERO);
send_to_char (buf, ch);
return;
}
if (min_lev > max_lev)
{
send_to_char ("That would be silly.\n\r", ch);
return;
}
}
}
}
/* initialize data */
for (level = 0; level < LEVEL_HERO + 1; level++)
{
skill_columns[level] = 0;
skill_list[level][0] = '\0';
}
for (sn = 0; sn < MAX_SKILL; sn++)
{
if (skill_table[sn].name == NULL)
break;
if ((level = skill_table[sn].skill_level[ch->class]) < LEVEL_HERO + 1
&& (fAll || level <= ch->level)
&& level >= min_lev && level <= max_lev
&& skill_table[sn].spell_fun == spell_null
&& ch->pcdata->learned[sn] > 0)
{
found = TRUE;
level = skill_table[sn].skill_level[ch->class];
if (ch->level < level)
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[level][0] == '\0')
sprintf (skill_list[level], "\n\rLevel %2d: %s", level, buf);
else
{ /* append */
if (++skill_columns[level] % 2 == 0)
strcat (skill_list[level], "\n\r ");
strcat (skill_list[level], buf);
}
}
}
/* return results */
if (!found)
{
send_to_char ("No skills found.\n\r", ch);
return;
}
buffer = new_buf ();
for (level = 0; level < LEVEL_HERO + 1; level++)
if (skill_list[level][0] != '\0')
add_buf (buffer, skill_list[level]);
add_buf (buffer, "\n\r");
page_to_char (buf_string (buffer), ch);
free_buf (buffer);
}
/* 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, "%-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 per level: %d\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", "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 per level: %d\n\r",
exp_per_level (ch, ch->gen_data->points_chosen));
send_to_char (buf, ch);
return;
}
int exp_per_level (CHAR_DATA * ch, int points)
{
int expl, inc;
if (IS_NPC (ch))
return 1000;
expl = 3000;
inc = 500;
if (points < 40)
return 1000 * (pc_race_table[ch->race].class_mult[ch->class] ?
pc_race_table[ch->race].class_mult[ch->class] /
100 : 1);
/* 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[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_function (ch, &do_help, "group help");
return TRUE;
}
do_function (ch, &do_help, 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;
}
/* Close security hole */
if (ch->gen_data->points_chosen +
group_table[gn].rating[ch->class] > 300)
{
send_to_char
("You cannot take more than 300 creation points.\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;
}
/* Close security hole */
if (ch->gen_data->points_chosen +
skill_table[sn].rating[ch->class] > 300)
{
send_to_char
("You cannot take more than 300 creation points.\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_function (ch, &do_help, "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_function (ch, &do_groups, 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;
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)
{
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->level2 < skill_table[sn].skill_level[ch->class2]
&& skill_table[sn].rating[ch->class2] == 0
&& ch->level3 < skill_table[sn].skill_level[ch->class3]
&& skill_table[sn].rating[ch->class3] == 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 * get_curr_stat(ch, STAT_INT) / 3;
if (skill_table[sn].rating[ch->class] > 0)
chance /= (multiplier * skill_table[sn].rating[ch->class] * 2);
if (skill_table[sn].rating[ch->class2] > 0)
chance /= (multiplier * skill_table[sn].rating[ch->class2] * 2);
if (skill_table[sn].rating[ch->class3] > 0)
chance /= (multiplier * skill_table[sn].rating[ch->class3] * 2);
chance += ch->level;
if (!double_improve)
{
if (number_range (1, 200) > chance) // was 1K
return;
}
if (double_improve)
{
if (number_range (1, 100) > 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 {Y%s{x!\n\r",
skill_table[sn].name);
send_to_char (buf, ch);
ch->pcdata->learned[sn]++;
sprintf ( buf, "{Y%s{x is now at {Y%d{x!\n\r",
skill_table[sn].name, ch->pcdata->learned[sn] );
send_to_char ( buf, ch );
// 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);
sprintf ( buf, "{Y%s{x is now at {Y%d{x!\n\r",
skill_table[sn].name, ch->pcdata->learned[sn] );
send_to_char ( buf, ch );
// 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 */
}
}