/**************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvements 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 *
* benefiting. 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 *
***************************************************************************
* 1stMud ROM Derivative (c) 2001-2004 by Markanth *
* http://www.firstmud.com/ <markanth@firstmud.com> *
* By using this code you have agreed to follow the term of *
* the 1stMud license in ../doc/1stMud/LICENSE *
***************************************************************************/
#include "merc.h"
#include "interp.h"
#include "magic.h"
#include "recycle.h"
Do_Fun(do_gain)
{
char arg[MAX_INPUT_LENGTH];
CharData *trainer;
int gn = 0, sn = 0, val;
int mult;
if (IsNPC(ch))
return;
for (trainer = ch->in_room->person_first; trainer != NULL;
trainer = trainer->next_in_room)
if (IsNPC(trainer) && IsSet(trainer->act, ACT_GAIN))
break;
if (trainer == NULL || !can_see(ch, trainer))
{
chprintln(ch, "You can't do that here.");
return;
}
mult = mult_argument(argument, arg);
if (NullStr(arg))
{
do_function(trainer, &do_say, "Pardon me?");
return;
}
if (!str_prefix(arg, "list"))
{
Buffer *output;
Column *Cd;
Cd = new_column();
output = new_buf();
set_cols(Cd, ch, 3, COLS_BUF, output);
cols_header(Cd, "{w%-18s Cost ", "Group");
for (gn = 0; gn < top_group; gn++)
{
if (!ch->pcdata->group_known[gn]
&& (val = group_rating(ch, gn)) > 0)
{
print_cols(Cd, "%-18s %-4d ", group_table[gn].name, val);
}
}
cols_nl(Cd);
bprintln(output, NULL);
set_cols(Cd, ch, 3, COLS_BUF, output);
cols_header(Cd, "{w%-15s %-4s Lev ", "Skill", "Cost");
for (sn = 0; sn < top_skill; sn++)
{
if (!ch->pcdata->learned[sn] && (val = skill_rating(ch, sn)) > 0
&& skill_table[sn].spell_fun == spell_null)
{
print_cols(Cd, "%-16s %-3d %-3d ", skill_table[sn].name, val,
skill_level(ch, sn));
}
}
cols_nl(Cd);
bprintlnf(output, "You have %s left.", intstr(ch->train, "train"));
bprintlnf(output,
"Use 'grlist' to see what skills are within a group.");
sendpage(ch, buf_string(output));
free_buf(output);
free_column(Cd);
return;
}
if (!str_prefix(arg, "convert"))
{
if (ch->practice < 10 * mult)
{
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 * mult;
ch->train += mult;
return;
}
if (!str_prefix(arg, "points"))
{
int xp;
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;
xp = ch->exp - (ch->level * exp_per_level(ch, ch->pcdata->points));
ch->pcdata->points -= 1;
ch->exp = exp_per_level(ch, ch->pcdata->points) * ch->level;
ch->exp += xp;
return;
}
gn = group_lookup(argument);
if (gn >= 0 && gn < top_group)
{
if (ch->pcdata->group_known[gn])
{
act("$N tells you 'You already know that group!'", ch, NULL,
trainer, TO_CHAR);
return;
}
if ((val = group_rating(ch, gn)) < 1)
{
act("$N tells you 'That group is beyond your powers.'", ch, NULL,
trainer, TO_CHAR);
return;
}
if (ch->train < val)
{
act("$N tells you 'You are not yet ready for that group.'", ch,
NULL, trainer, TO_CHAR);
return;
}
gn_add(ch, gn);
act("$N trains you in the art of $t", ch, group_table[gn].name,
trainer, TO_CHAR);
ch->train -= val;
return;
}
sn = skill_lookup(argument);
if (sn > -1 && sn < top_skill)
{
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 ((val = skill_rating(ch, sn)) < 1)
{
act("$N tells you 'That skill is beyond your powers.'", ch, NULL,
trainer, TO_CHAR);
return;
}
if (ch->train < skill_rating(ch, sn))
{
act("$N tells you 'You are not yet ready for that skill.'", ch,
NULL, trainer, TO_CHAR);
return;
}
ch->pcdata->learned[sn] = 1;
act("$N trains you in the art of $t", ch, skill_table[sn].name,
trainer, TO_CHAR);
ch->train -= val;
return;
}
act("$N tells you 'I do not understand...'", ch, NULL, trainer, TO_CHAR);
}
Do_Fun(do_spells)
{
Buffer *buffer;
char arg[MAX_INPUT_LENGTH];
char spell_list[MAX_MORTAL_LEVEL + 1][MAX_STRING_LENGTH];
char spell_columns[MAX_MORTAL_LEVEL + 1];
int sn, level, min_lev = 1, max_lev = MAX_MORTAL_LEVEL, mana;
bool fAll = false, found = false;
char buf[MAX_STRING_LENGTH];
if (IsNPC(ch))
return;
if (!NullStr(argument))
{
fAll = true;
if (str_prefix(argument, "all"))
{
argument = one_argument(argument, arg);
if (!is_number(arg))
{
chprintln(ch, "Arguments must be numerical or all.");
return;
}
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
{
chprintlnf(ch, "Levels must be between 1 and %d.",
MAX_MORTAL_LEVEL);
return;
}
if (!NullStr(argument))
{
argument = one_argument(argument, arg);
if (!is_number(arg))
{
chprintln(ch, "Arguments must be numerical or all.");
return;
}
min_lev = max_lev;
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
{
chprintlnf(ch, "Levels must be between 1 and %d.",
MAX_MORTAL_LEVEL);
return;
}
if (min_lev > max_lev)
{
chprintln(ch, "That would be silly.");
return;
}
}
}
}
for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
{
spell_columns[level] = 0;
spell_list[level][0] = '\0';
}
for (sn = 0; sn < top_skill; sn++)
{
if ((level = skill_level(ch, sn)) < MAX_MORTAL_LEVEL + 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_level(ch, sn);
if (ch->level < level)
sprintf(buf, "%-18s n/a ", skill_table[sn].name);
else
{
mana =
Max(skill_table[sn].min_mana,
100 / (2 + ch->level - level));
sprintf(buf, "%-18s %3d mana ", skill_table[sn].name, mana);
}
if (spell_list[level][0] == '\0')
sprintf(spell_list[level], NEWLINE "Level %2d: %s", level,
buf);
else
{
if (++spell_columns[level] % 2 == 0)
strcat(spell_list[level], NEWLINE " ");
strcat(spell_list[level], buf);
}
}
}
if (!found)
{
chprintln(ch, "No spells found.");
return;
}
buffer = new_buf();
for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
if (spell_list[level][0] != '\0')
bprint(buffer, spell_list[level]);
bprintln(buffer, NULL);
sendpage(ch, buf_string(buffer));
free_buf(buffer);
}
Do_Fun(do_skills)
{
Buffer *buffer;
char arg[MAX_INPUT_LENGTH];
char skill_list[MAX_MORTAL_LEVEL + 1][MAX_STRING_LENGTH];
char skill_columns[MAX_MORTAL_LEVEL + 1];
int sn, level, min_lev = 1, max_lev = MAX_MORTAL_LEVEL;
bool fAll = false, found = false;
char buf[MAX_STRING_LENGTH];
if (IsNPC(ch))
return;
if (!NullStr(argument))
{
fAll = true;
if (str_prefix(argument, "all"))
{
argument = one_argument(argument, arg);
if (!is_number(arg))
{
chprintln(ch, "Arguments must be numerical or all.");
return;
}
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
{
chprintlnf(ch, "Levels must be between 1 and %d.",
MAX_MORTAL_LEVEL);
return;
}
if (!NullStr(argument))
{
argument = one_argument(argument, arg);
if (!is_number(arg))
{
chprintln(ch, "Arguments must be numerical or all.");
return;
}
min_lev = max_lev;
max_lev = atoi(arg);
if (max_lev < 1 || max_lev > MAX_MORTAL_LEVEL)
{
chprintlnf(ch, "Levels must be between 1 and %d.",
MAX_MORTAL_LEVEL);
return;
}
if (min_lev > max_lev)
{
chprintln(ch, "That would be silly.");
return;
}
}
}
}
for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
{
skill_columns[level] = 0;
skill_list[level][0] = '\0';
}
for (sn = 0; sn < top_skill; sn++)
{
if ((level = skill_level(ch, sn)) < MAX_MORTAL_LEVEL + 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_level(ch, sn);
if (ch->level < level)
sprintf(buf, "{c%-18s n/a ", skill_table[sn].name);
else
sprintf(buf, "{c%-18s {W%3d%% ", skill_table[sn].name,
ch->pcdata->learned[sn]);
if (skill_list[level][0] == '\0')
sprintf(skill_list[level], NEWLINE "{cLevel {W%2d{c: %s{x",
level, buf);
else
{
if (++skill_columns[level] % 2 == 0)
strcat(skill_list[level], NEWLINE "{x ");
strcat(skill_list[level], buf);
}
}
}
if (!found)
{
chprintln(ch, "{cNo skills found.{x");
return;
}
buffer = new_buf();
for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
if (skill_list[level][0] != '\0')
bprint(buffer, skill_list[level]);
bprintln(buffer, NULL);
sendpage(ch, buf_string(buffer));
free_buf(buffer);
}
void list_group_costs(CharData * ch)
{
int gn, sn, val;
Buffer *output;
Column *Cd;
if (IsNPC(ch))
return;
output = new_buf();
Cd = new_column();
set_cols(Cd, ch, 3, COLS_BUF, output);
bprintlnf(output, "{c%s", draw_line(ch, NULL, 0));
cols_header(Cd, "{w%-18s CP ", "Group");
for (gn = 0; gn < top_group; gn++)
{
if (!ch->gen_data->group_chosen[gn] && !ch->pcdata->group_known[gn]
&& (val = group_rating(ch, gn)) > 0)
{
print_cols(Cd, "{c%-18s {W%-2d ", group_table[gn].name, val);
}
}
cols_nl(Cd);
bprintlnf(output, "{c%s", draw_line(ch, NULL, 0));
set_cols(Cd, ch, 2, COLS_BUF, output);
cols_header(Cd, "{w%-18s %-2s Lev ", "Skill", "CP");
for (sn = 0; sn < top_skill; sn++)
{
if (!ch->gen_data->skill_chosen[sn] && ch->pcdata->learned[sn] == 0
&& skill_table[sn].spell_fun == spell_null
&& (val = skill_rating(ch, sn)) > 0)
{
print_cols(Cd, "{c%-18s {W%-2d %-3d ", skill_table[sn].name, val,
skill_level(ch, sn));
}
}
cols_nl(Cd);
bprintlnf(output, "{c%s", draw_line(ch, NULL, 0));
bprintln(output, NULL);
bprintlnf(output, "{cCreation points: {W%d{x", ch->pcdata->points);
bprintlnf(output, "{cExperience per level: {W%d{x",
exp_per_level(ch,
Max(ch->gen_data->points_chosen,
ch->pcdata->points)));
sendpage(ch, buf_string(output));
free_buf(output);
free_column(Cd);
return;
}
void list_group_chosen(CharData * ch)
{
int gn, sn, val;
Buffer *output;
Column *Cd;
if (IsNPC(ch))
return;
output = new_buf();
Cd = new_column();
set_cols(Cd, ch, 3, COLS_BUF, output);
bprintlnf(output, "{c%s", draw_line(ch, NULL, 0));
print_cols(Cd, "{w%-18s CP ", "Group");
for (gn = 0; gn < top_group; gn++)
{
if (ch->gen_data->group_chosen[gn]
&& (val = group_rating(ch, gn)) > 0)
{
print_cols(Cd, "{c%-18s {W%-2d ", group_table[gn].name, val);
}
}
cols_nl(Cd);
bprintlnf(output, "{c%s", draw_line(ch, NULL, 0));
set_cols(Cd, ch, 2, COLS_BUF, output);
cols_header(Cd, "{w%-18s %-2s Lev", "Skill", "CP");
for (sn = 0; sn < top_skill; sn++)
{
if (ch->gen_data->skill_chosen[sn]
&& (val = skill_rating(ch, sn)) > 0)
{
print_cols(Cd, "{c%-18s {W%-2d %-3d ", skill_table[sn].name, val,
skill_level(ch, sn));
}
}
cols_nl(Cd);
bprintlnf(output, "{c%s", draw_line(ch, NULL, 0));
bprintlnf(output, "{cCreation points: {W%d{x",
ch->gen_data->points_chosen);
bprintlnf(output, "{cExperience per level: {W%d{x",
exp_per_level(ch, ch->gen_data->points_chosen));
sendpage(ch, buf_string(output));
free_buf(output);
free_column(Cd);
return;
}
int exp_per_level(CharData * ch, int points)
{
int expl, inc;
if (IsNPC(ch))
return 1000;
expl = 1000;
inc = 500;
if (points >= mud_info.max_points)
{
points -= mud_info.max_points;
while (points >= 10)
{
expl += inc;
points -= 10;
if (points >= 10)
{
expl += inc;
inc *= 2;
points -= 10;
}
}
expl += points * inc / 10;
}
expl *= class_mult(ch);
expl /= 100;
return expl;
}
bool parse_gen_groups(CharData * ch, const char *argument)
{
char arg[MAX_INPUT_LENGTH];
int gn, sn, i;
if (NullStr(argument))
return false;
argument = one_argument(argument, arg);
if (!str_prefix(arg, "help"))
{
if (NullStr(argument))
{
chprintln(ch, "{cThe following commands are available:{x");
chprintln(ch,
"{clist display all groups and skills not yet bought{x");
chprintln(ch,
"{clearned show all groups and skills bought {x");
chprintln(ch,
"{cpremise brief explanation of creation points and skill groups{x");
chprintln(ch, "{cadd <name> buy a skill or group{x");
chprintln(ch, "{cdrop <name> discard a skill or group{x");
chprintln(ch,
"{cinfo <name> list the skills or spells contained within a group{x");
chprintln(ch, "{clookup <name> show class levels for skill{x");
chprintln(ch,
"{chelp <name> help on skills and groups, or other help topics{x");
chprintln(ch,
"{cdone exit the character generation process{x");
return true;
}
chprint(ch, "{c");
do_function(ch, &do_oldhelp, argument);
chprint(ch, "{x");
return true;
}
if (!str_prefix(arg, "add"))
{
int val;
if (NullStr(argument))
{
chprintln(ch, "{cYou must provide a skill name.{x");
return true;
}
gn = group_lookup(argument);
if (gn != -1)
{
if (ch->gen_data->group_chosen[gn] || ch->pcdata->group_known[gn])
{
chprintln(ch, "{cYou already know that group!{x");
return true;
}
if ((val = group_rating(ch, gn)) < 1)
{
chprintln(ch, "{cThat group is not available.{x");
return true;
}
if (ch->gen_data->points_chosen + val > 300)
{
chprintln(ch,
"{cYou cannot take more than 300 creation points.{x");
return true;
}
chprintlnf(ch, "{W%s{c group added.{x",
Upper(group_table[gn].name));
ch->gen_data->group_chosen[gn] = true;
ch->gen_data->points_chosen += val;
gn_add(ch, gn);
ch->pcdata->points += val;
return true;
}
sn = skill_lookup(argument);
if (sn != -1)
{
if (ch->gen_data->skill_chosen[sn] || ch->pcdata->learned[sn] > 0)
{
chprintln(ch, "{cYou already know that skill!{x");
return true;
}
if ((val = skill_rating(ch, sn)) < 1
|| skill_table[sn].spell_fun != spell_null)
{
chprintln(ch, "{cThat skill is not available.{x");
return true;
}
if (ch->gen_data->points_chosen + val > 300)
{
chprintln(ch,
"{cYou cannot take more than 300 creation points.{x");
return true;
}
chprintlnf(ch, "{W%s{c skill added.{x",
Upper(skill_table[sn].name));
ch->gen_data->skill_chosen[sn] = true;
ch->gen_data->points_chosen += val;
ch->pcdata->learned[sn] = 1;
ch->pcdata->points += val;
return true;
}
chprintln(ch, "{cNo skills or groups by that name...{x");
return true;
}
if (!str_cmp(arg, "drop"))
{
int val;
if (NullStr(argument))
{
chprintln(ch, "{cYou must provide a skill to drop.{x");
return true;
}
gn = group_lookup(argument);
if (gn != -1 && ch->gen_data->group_chosen[gn])
{
chprintlnf(ch, "{W%s{c group dropped.",
Upper(group_table[gn].name));
ch->gen_data->group_chosen[gn] = false;
val = group_rating(ch, gn);
ch->gen_data->points_chosen -= val;
gn_remove(ch, gn);
for (i = 0; i < top_group; i++)
{
if (ch->gen_data->group_chosen[gn])
gn_add(ch, gn);
}
ch->pcdata->points -= val;
return true;
}
sn = skill_lookup(argument);
if (sn != -1 && ch->gen_data->skill_chosen[sn])
{
chprintlnf(ch, "{W%s{c skill dropped.",
Upper(skill_table[sn].name));
ch->gen_data->skill_chosen[sn] = false;
val = skill_rating(ch, sn);
ch->gen_data->points_chosen -= val;
ch->pcdata->learned[sn] = 0;
ch->pcdata->points -= val;
return true;
}
chprintln(ch, "{cYou haven't bought any such skill or group.{x");
return true;
}
if (!str_prefix(arg, "premise"))
{
chprint(ch, "{c");
do_function(ch, &do_oldhelp, "premise");
chprint(ch, "{x");
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_grlist("info", ch, argument);
return true;
}
if (!str_prefix(arg, "lookup"))
{
do_slist("lookup", ch, argument);
return true;
}
return false;
}
void check_improve(CharData * ch, int sn, bool success, int multiplier)
{
int chance;
if (IsNPC(ch))
return;
if (!can_use_skpell(ch, sn) || skill_rating(ch, sn) < 1
|| ch->pcdata->learned[sn] == 0 || ch->pcdata->learned[sn] == 100)
return;
chance = 10 * int_app[get_curr_stat(ch, STAT_INT)].learn;
chance /= (multiplier * skill_rating(ch, sn) * 4);
chance += ch->level;
if (number_range(1, 1000) > chance)
return;
if (success)
{
chance = Range(5, 100 - ch->pcdata->learned[sn], 95);
if (number_percent() < chance)
{
chprintlnf(ch, "You have become better at %s!",
skill_table[sn].name);
ch->pcdata->learned[sn]++;
gain_exp(ch, 2 * skill_rating(ch, sn));
}
}
else
{
chance = Range(5, ch->pcdata->learned[sn] / 2, 30);
if (number_percent() < chance)
{
chprintlnf(ch,
"You learn from your mistakes, and your %s skill improves.",
skill_table[sn].name);
ch->pcdata->learned[sn] += number_range(1, 3);
ch->pcdata->learned[sn] = Min(ch->pcdata->learned[sn], 100);
gain_exp(ch, 2 * skill_rating(ch, sn));
}
}
if (ch->pcdata->learned[sn] == 100)
{
chprintlnf(ch, "{GYou have now mastered the '%s' %s!",
skill_table[sn].name,
skill_table[sn].spell_fun ? "spell" : "skill");
}
}
Lookup_Fun(group_lookup)
{
int gn;
for (gn = 0; gn < top_group; gn++)
{
if (tolower(name[0]) == tolower(group_table[gn].name[0])
&& !str_prefix(name, group_table[gn].name))
return gn;
}
return -1;
}
void gn_add(CharData * ch, int gn)
{
int i;
if (IsNPC(ch) || gn >= top_group || gn < 0)
return;
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);
}
}
void gn_remove(CharData * ch, int gn)
{
int i;
if (IsNPC(ch) || gn >= top_group || gn < 0)
return;
if (check_base_group(ch, gn))
return;
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]);
}
}
void group_add(CharData * ch, const char *name, bool deduct)
{
int sn, gn;
if (IsNPC(ch))
return;
sn = skill_lookup(name);
if (sn != -1)
{
if (ch->pcdata->learned[sn] == 0)
{
ch->pcdata->learned[sn] = 1;
if (deduct)
ch->pcdata->points += skill_rating(ch, sn);
}
return;
}
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_rating(ch, gn);
}
gn_add(ch, gn);
}
}
void group_remove(CharData * ch, const char *name)
{
int sn, gn;
sn = skill_lookup(name);
if (sn != -1)
{
if (!is_base_skill(ch, sn))
ch->pcdata->learned[sn] = 0;
return;
}
gn = group_lookup(name);
if (gn != -1 && ch->pcdata->group_known[gn] == true)
{
ch->pcdata->group_known[gn] = false;
gn_remove(ch, gn);
}
}
Do_Fun(do_slist)
{
int sn, clas;
bool found = false;
if (NullStr(argument))
{
cmd_syntax(ch, NULL, n_fun, "<skill>", "<spell>", "<class>", NULL);
return;
}
else if ((clas = class_lookup(argument)) != -1)
{
char buf[MSL];
Buffer *buffer;
char skill_list[MAX_MORTAL_LEVEL + 1][5000];
int skill_columns[MAX_MORTAL_LEVEL + 1];
int level;
for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
{
skill_columns[level] = 0;
skill_list[level][0] = NUL;
}
for (sn = 0; sn < top_skill; sn++)
{
if ((level = skill_table[sn].skill_level[clas]) <=
MAX_MORTAL_LEVEL)
{
found = true;
sprintf(buf, "{c%-18s ", skill_table[sn].name);
if (skill_list[level][0] == NUL)
sprintf(skill_list[level],
NEWLINE "{cLevel {W%3d{c: %s{x", level, buf);
else
{
if (++skill_columns[level] % 2 == 0)
strcat(skill_list[level], NEWLINE "{x ");
strcat(skill_list[level], buf);
}
}
}
buffer = new_buf();
for (level = 0; level < MAX_MORTAL_LEVEL + 1; level++)
{
if (skill_list[level][0] != NUL)
bprint(buffer, skill_list[level]);
}
bprintln(buffer, NULL);
sendpage(ch, buf_string(buffer));
free_buf(buffer);
return;
}
else if ((sn = skill_lookup(argument)) != -1)
{
int x;
chprintf(ch, NEWLINE "{c%s: [ ", capitalize(skill_table[sn].name));
for (x = 0; x < top_class; x++)
{
if (skill_table[sn].skill_level[x] > MAX_MORTAL_LEVEL)
chprintf(ch, "{W%.3s: %3s{c ", ClassName(ch, x), "n/a");
else
chprintf(ch, "{W%.3s: %03d{c ", ClassName(ch, x),
skill_table[sn].skill_level[x]);
}
chprintln(ch, "]{x");
return;
}
else
{
do_slist(n_fun, ch, "");
return;
}
}
int spell_avail(CharData * ch, const char *name)
{
int sn;
sn = skill_lookup(name);
if (sn != -1 && skill_level(ch, sn) > MAX_MORTAL_LEVEL)
return -1;
return sn;
}
Do_Fun(do_grlist)
{
int gn, sn, tn;
bool found = false;
Column *Cd;
if (!ch || IsNPC(ch))
return;
Cd = new_column();
set_cols(Cd, ch, 4, COLS_CHAR, ch);
if (NullStr(argument))
{
for (gn = 0; gn < top_group; gn++)
{
if (ch->pcdata->group_known[gn])
{
if (!found)
{
chprintln(ch, "{cGroups you currently have:");
chprintln(ch, draw_line(ch, NULL, 0));
}
print_cols(Cd, "{W%s", group_table[gn].name);
found = true;
}
}
if (!found)
chprintln(ch, "{cYou know no groups.{x");
else
cols_nl(Cd);
chprintlnf(ch, "{cCreation points: {W%d{x", ch->pcdata->points);
}
else if (!str_cmp(argument, "all"))
{
for (gn = 0; gn < top_group; gn++)
{
if (IsImmortal(ch) || group_rating(ch, gn) > 0)
{
if (!found)
{
chprintln(ch, "{cGroups available to you:");
chprintln(ch, draw_line(ch, NULL, 0));
}
print_cols(Cd, "{W%s", group_table[gn].name);
found = true;
}
}
if (!found)
chprintln(ch, "{cNo groups are available to you.{x");
else
cols_nl(Cd);
}
else if ((tn = class_lookup(argument)) != -1)
{
for (gn = 0; gn < top_group; gn++)
{
if (group_table[gn].rating[tn] <= 0)
continue;
if (!found)
{
chprintlnf(ch, "{cGroups available for the {W%s{c" " class:",
class_table[tn].name[0]);
chprintln(ch, draw_line(ch, NULL, 0));
}
print_cols(Cd, "{W%s", group_table[gn].name);
found = true;
}
if (!found)
chprintlnf(ch,
"{cThere are no groups available to the {W%s{c"
" class.{x", class_table[tn].name[0]);
else
cols_nl(Cd);
}
else if ((gn = group_lookup(argument)) != -1)
{
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)
{
if (!found)
{
chprintlnf(ch, "{cSpells available in {W%s{c:{x",
group_table[gn].name);
cols_header(Cd, "{cLevel {WSpell{x");
chprintlnf(ch, "{c%s{x", draw_line(ch, NULL, 0));
}
print_cols(Cd, "{c%-5d {W%s{x", skill_level(ch, tn),
group_table[gn].spells[sn]);
found = true;
}
}
if (!found)
chprintlnf(ch, "{cNo spells available in the {W%s{c group.{x",
group_table[gn].name);
else
cols_nl(Cd);
}
else if ((sn = skill_lookup(argument)) != -1)
{
for (gn = 0; gn < top_group; gn++)
{
for (tn = 0; tn < MAX_IN_GROUP; tn++)
{
if (group_table[gn].spells[tn] == NULL)
break;
if (skill_lookup(group_table[gn].spells[tn]) != sn)
continue;
if (!found)
{
chprintlnf(ch, "{W%s{c is in the following groups:{x",
skill_table[sn].name);
chprintlnf(ch, "{c%s{x", draw_line(ch, NULL, 0));
}
print_cols(Cd, "{W%s", group_table[gn].name);
found = true;
}
}
if (!found)
chprintlnf(ch, "{W%s{c can't be found in any groups.{x",
skill_table[sn].name);
else
cols_nl(Cd);
}
else
{
cmd_syntax(ch, NULL, n_fun, " -list your current groups",
"all -list all available groups",
"<group> -list all spells in a group",
"<skill> -list all groups a skill is in",
"<class> -list all groups available to a class", NULL);
}
free_column(Cd);
}