/**************************************************************************/
// grpedit.cpp - olc based skillgroup editing
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
**************************************************************************/
#include "include.h"
#include "olc.h"
#include "security.h"
/**************************************************************************/
// prototypes
const char *pack_word(const char *word); // areas.cpp
/**************************************************************************/
const struct flag_type skillgroup_flags[] =
{
{ "creation_selectable", SKILLGROUP_CREATION_SELECTABLE, true},
{ "free_for_all", SKILLGROUP_FREE_FOR_ALL, true},
{ NULL,0,0} // table terminator
};
/**************************************************************************/
/**************************************************************************/
// generic IO setup
// custom read/write functions
/**************************************************************************/
// write the class rating for each class listed in the skillgroup table
void skillgroup_WriteClassRatings(gio_type *gio_table, int tableIndex, void *data, FILE *fp)
{
int classIndex, value;
skillgroup_type * pG= (skillgroup_type *) data;
fprintf(fp, "%s\n", gio_table[tableIndex].heading);
for (classIndex=0; !IS_NULLSTR(class_table[classIndex].name); classIndex++){
// write only valid values
if (pG->rating[classIndex]<0 || pG->rating[classIndex]>50){
value=-1;
}else{
value=pG->rating[classIndex];
}
if(value!=-1){
fprintf(fp, "\t%s %d\n", class_table[classIndex].name, value);
}
};
fprintf(fp, "~\n");
}
/**************************************************************************/
// read the class ratings for each class listed in the group table
void skillgroup_ReadClassRatings(gio_type *, int, void *data, FILE *fp)
{
int classIndex;
skillgroup_type * pG= (skillgroup_type *) data;
char className[MIL];
int rating;
// initialise all values to -1 (no classes have access to the skill group)
for (classIndex=0; !IS_NULLSTR(class_table[classIndex].name); classIndex++){
pG->rating[classIndex]=-1;
}
while (true){
// get the class name and rating
fscanf(fp, "%s ", className);
if (className[0]=='~' && className[1]=='\0'){
break;
}
// read in the rating
fscanf(fp, "%d ", &rating);
classIndex =class_lookup(className);
if (classIndex<0){
bugf( "group_ReadClassRatings: class '%s' not found... "
"ignoring rating for that class.", className);
}else{
pG->rating[classIndex]=rating;
}
}
}
/**************************************************************************/
// write all the skills in the skillgroup to disk
void skillgroup_WriteSkills(gio_type *gio_table, int tableIndex, void *data, FILE *fp)
{
int i;
skillgroup_type * pG;
pG= (skillgroup_type *) data;
fprintf(fp, "%s\n", gio_table[tableIndex].heading);
// write each skill out
for (i = 0; pG->skills[i]>-1; i++){
fprintf(fp, "\t%s\n", pack_word(skill_table[pG->skills[i]].name));
}
fprintf(fp, "~\n");
}
/**************************************************************************/
// write all the skills in the skillgroup to disk
void skillgroup_WriteSkillsWithValues(gio_type *gio_table, int tableIndex, void *data, FILE *fp)
{
int i;
skillgroup_type * pG;
pG= (skillgroup_type *) data;
fprintf(fp, "%s\n", gio_table[tableIndex].heading);
// write each skill out
for (i = 0; pG->skills[i]>-1; i++){
fprintf(fp, "\t%s %d\n",
pack_word(skill_table[pG->skills[i]].name),
pG->skillsvalue[i]);
}
fprintf(fp, "~\n");
}
/**************************************************************************/
// read all the skills from disk into a skillgroup
void skillgroup_ReadSkills(gio_type *, int, void *data, FILE *fp)
{
skillgroup_type * pG= (skillgroup_type *) data;
int sn;
int sindex=0;
char *readword;
// initialise all skills to -1 (no skills in the skillgroup)
memset(pG->skills, -1, sizeof(pG->skills));
while (true){
// get the skill name
readword=fread_word(fp);
if (readword[0]=='~' && readword[1]=='\0'){
break;
}
sn=skill_exact_lookup(readword);
if (sn<0){
bugf( "group_ReadSkills: skill '%s' not found... ignoring skill for skillgroup '%s'.",
readword, pG->name);
}else{
if(sindex>=MAX_IN_GROUP){
bugf("group_ReadSkills(): Too many skills (%d) to read into skillgroup '%s' "
"- increase MAX_IN_GROUP.", sindex, pG->name);
do_abort();
}
pG->skills[sindex]=sn;
pG->skillsvalue[sindex]=1; // 1% is the default
sindex++;
}
}
}
/**************************************************************************/
// read all the skills from disk into a skillgroup
void skillgroup_ReadSkillsWithValues(gio_type *, int, void *data, FILE *fp)
{
skillgroup_type * pG= (skillgroup_type *) data;
int sn;
int sindex=0;
char *readword;
// initialise all skills to -1 (no skills in the skillgroup)
memset(pG->skills, -1, sizeof(pG->skills));
while (true){
int value;
// get the skill name
readword=fread_word(fp);
if (readword[0]=='~' && readword[1]=='\0'){
break;
}
value=fread_number(fp);
sn=skill_exact_lookup(readword);
if (sn<0){
bugf( "group_ReadSkills: skill '%s' not found... ignoring skill for skillgroup '%s'.",
readword, pG->name);
}else{
if(sindex>=MAX_IN_GROUP){
bugf("group_ReadSkills(): Too many skills (%d) to read into skillgroup '%s' "
"- increase MAX_IN_GROUP.", sindex, pG->name);
do_abort();
}
pG->skills[sindex]=sn;
pG->skillsvalue[sindex]=value;
sindex++;
}
}
}
/**************************************************************************/
// GIO structure
GIO_START(skillgroup_type)
GIO_INT(remort)
GIO_WFLAGH(flags, "flags", skillgroup_flags)
GIO_CUSTOM_WRITEH(name, "skillswithvalues", skillgroup_WriteSkillsWithValues)
GIO_CUSTOM_READH(name, "skillswithvalues", skillgroup_ReadSkillsWithValues)
GIO_CUSTOM_READH(name, "skills", skillgroup_ReadSkills)
GIO_CUSTOM_WRITEH(name, "class_ratings", skillgroup_WriteClassRatings)
GIO_CUSTOM_READH(name, "class_ratings", skillgroup_ReadClassRatings)
GIO_FINISH_NOCLEAR
/**************************************************************************/
// Output the skillgroup_table[] to disk
void do_write_skillgroups(char_data *ch, char *)
{
FILE *fp;
int i;
logf("Writing skillgroup_table[] to " SKILLGROUPS_FILE ".write ...");
fclose( fpReserve );
if ( ( fp = fopen( SKILLGROUPS_FILE ".write", "w" ) ) == NULL )
{
bugf("do_write_skillgroups(): fopen '%s' for write - error %d (%s)",
SKILLGROUPS_FILE ".write", errno, strerror( errno));
bug("An error occured opening " SKILLGROUPS_FILE ".write for writing!");
ch->println("An error occured opening " SKILLGROUPS_FILE ".write for writing!");
autonote(NOTE_SNOTE, "do_write_skillgroups()", "Problems saving skillgroups table", "code cc: imm",
"An error occured opening " SKILLGROUPS_FILE ".write for writing!\r\n", true);
}else{
// LOOP thru everything in the table, writing it
for ( i = 0; !IS_NULLSTR(skillgroup_table[i].name); i++ )
{
fprintf(fp,"######SKILLGROUP %s~\n", skillgroup_table[i].name);
GIO_SAVE_RECORD(skillgroup_type, &skillgroup_table[i], fp, NULL);
fprintf(fp,"\n");
}
int bytes_written=fprintf(fp, "EOF~\n");
fclose( fp );
if( bytes_written != str_len("EOF~\n") ){
bugf("do_write_skillgroups(): fprint to '%s' incomplete - error %d (%s)",
SKILLGROUPS_FILE ".write", errno, strerror( errno));
bugf("Incomplete write of " SKILLGROUPS_FILE ".write, write aborted - check diskspace!");
ch->printf("Incomplete write of " SKILLGROUPS_FILE ".write, write aborted - check diskspace!\r\n");
autonote(NOTE_SNOTE, "do_write_skillgroups()", "Problems saving skillgroup_table[]", "code cc: imm",
"Incomplete write of " SKILLGROUPS_FILE ".write, write aborted - check diskspace!\r\n", true);
}else{
ch->printf("Finished writing skillgroup_table[] to "SKILLGROUPS_FILE ".write\r\n");
ch->printf("Renaming old " SKILLGROUPS_FILE " to " SKILLGROUPS_FILE ".bak\r\n");
unlink(SKILLGROUPS_FILE".bak");
rename(SKILLGROUPS_FILE, SKILLGROUPS_FILE".bak");
ch->printf("Renaming new " SKILLGROUPS_FILE ".write to " SKILLGROUPS_FILE "\r\n");
unlink(SKILLGROUPS_FILE);
rename(SKILLGROUPS_FILE".write", SKILLGROUPS_FILE);
}
}
fpReserve = fopen( NULL_FILE, "r" );
logf("Finished writing skillgroup_table[].");
}
/**************************************************************************/
extern struct group_type group_table [MAX_GROUP_TABLE+1];
/**************************************************************************/
// convert group_table[] into skillgroup_table[]
void convert_group_table()
{
int i, gn;
int class_total_ratings[MAX_CLASS];
memset(class_total_ratings, 0, sizeof(class_total_ratings));
memset(skillgroup_table, 0, sizeof(skillgroup_table));
for( gn = 0; !IS_NULLSTR(group_table[gn].oldname); gn++ )
{
memset(skillgroup_table[gn].skills, -1, sizeof(skillgroup_table[gn].skills));
memset(skillgroup_table[gn].rating, -1, sizeof(skillgroup_table[gn].rating));
// copy the name across
skillgroup_table[gn].name=str_dup(group_table[gn].oldname);
for ( i = 0; !IS_NULLSTR(group_table[gn].oldspells[i]); i++){
skillgroup_table[gn].skills[i]=skill_lookup(group_table[gn].oldspells[i]);
}
// loop thru, transfering all class ratings, if all are 0, then set the free_for_all flag
bool all_free=true;
for(i=0; !IS_NULLSTR(class_table[i].name); i++){
skillgroup_table[gn].rating[i]=group_table[gn].oldrating[i];
if(skillgroup_table[gn].rating[i]!=0){
all_free=false;
}
// record the combined total ratings for each class
class_total_ratings[i]+=skillgroup_table[gn].rating[i];
}
if(all_free){
SET_BIT(skillgroup_table[gn].flags, SKILLGROUP_FREE_FOR_ALL);
}
SET_BIT(skillgroup_table[gn].flags, SKILLGROUP_CREATION_SELECTABLE);
}
// for all classes with a combined total rating 0 (i.e. everything free)
// set to -1 except on those which are free_for_all
for(i=0; !IS_NULLSTR(class_table[i].name); i++){
if(class_total_ratings[i]==0){
for( gn = 0; !IS_NULLSTR(skillgroup_table[gn].name); gn++ )
{
if(!IS_SET(skillgroup_table[gn].flags, SKILLGROUP_FREE_FOR_ALL)){
skillgroup_table[gn].rating[i]=-1;
}
}
}
}
}
/**************************************************************************/
// read in the skillgroup_table from disk
void do_read_skillgroups(char_data *ch, char *)
{
FILE *fp;
int count=0;
// because system doesn't support reassigning group numbers, only allow
// this to run at bootup and when one imm is on
if(runlevel!=RUNLEVEL_BOOTING){
ch->println("do_read_skillgroups() currently doesn't support being called a game time... boot only!");
ch->println("Doing so in its current state might stuff up everyones skill ");
ch->println("groups... BASICALLY DONT DO IT!");
return;
}
logf("Reading in skillgroup_table[] from " SKILLGROUPS_FILE "...");
fclose( fpReserve );
if ( ( fp = fopen( SKILLGROUPS_FILE, "r" ) ) == NULL )
{ // couldn't find the file to read in
bugf("do_read_skillgroups(): fopen '%s' for read - error %d (%s)",
SKILLGROUPS_FILE , errno, strerror( errno));
bugf("An error occured trying to open " SKILLGROUPS_FILE " for reading!");
ch->printf("An error occured trying to open " SKILLGROUPS_FILE " for reading!\r\n");
if(file_exists(SKILLGROUPS_FILE )){
bugf("File " SKILLGROUPS_FILE "found, but it wasnt openned for some reason?!?");
write_shutdown_file(NULL);
do_abort();
}else{
ch->println("Converting old skillgroup_table[] and creating a new " SKILLGROUPS_FILE " file.");
logf("Converting old skillgroup_table[] and creating a new " SKILLGROUPS_FILE " file.");
convert_group_table();
fpReserve = fopen( NULL_FILE, "r" );
do_write_skillgroups(NULL,"");
}
return;
}
// SKILLGROUPS_FILE was found, and sucessfully opened for input
bool morefile=true;
char *readword;
if(runlevel==RUNLEVEL_BOOTING){
// *** Mark the existing table as empty - since we are loading everything in
// - This could cause skillgroup corruption if done when people are online...
// that is why it can be only done if one is online or during booting.
memset(skillgroup_table, 0, sizeof(skillgroup_table));
}
// loop thru till we get the end of the table
while (morefile && !feof(fp)) {
int load_index;
readword= fread_word(fp);
if (!str_cmp(readword, "EOF") || !str_cmp(readword, "EOF~")){
morefile=false;
}else{
if(str_cmp(readword, "######SKILLGROUP")){
// unexpected file format
bugf("Unexpected fileformat in '%s' - found '%s' "
"expecting '######SKILLGROUP'", SKILLGROUPS_FILE , readword);
ch->printf( "Unexpected fileformat in '%s' - found '%s' "
"expecting '######SKILLGROUP'\r\n", SKILLGROUPS_FILE , readword);
flush_char_outbuffer(ch);
write_shutdown_file(NULL);
do_abort();
return;
}
// get the name of the skillgroup
readword=fread_string(fp);
// check if the skillgroup hasn't already been loaded - no duplicates
load_index=skillgroup_exact_lookup(readword);
if(load_index>-1){ // we have already loaded a skill group with that name!?!
bugf("do_read_skillgroups(): skillgroup '%s' has already been loaded!", readword);
do_abort();
}
// we have a new skill group to read in... allocate space for it
for ( load_index=0; !IS_NULLSTR(skillgroup_table[load_index].name); load_index++){
// do nothing till we find the end
}
//load_index now points to the end of the list
if(load_index>=MAX_SKILLGROUP){
bugf("Too many skillgroups (%d) trying to load skillgroup '%s' from %s, increase MAX_SKILLGROUP - aborting",
load_index, readword, SKILLGROUPS_FILE);
write_shutdown_file(NULL);
exit_error( 1 , "do_read_skillgroups", "Too many skill groups");
}
// fill in the defaults for our entry
memset(skillgroup_table[load_index].skills, -1, sizeof(skillgroup_table[0].skills));
memset(skillgroup_table[load_index].rating, -1, sizeof(skillgroup_table[0].rating));
skillgroup_table[load_index].name=str_dup(readword);
// mark the new end of the table
skillgroup_table[load_index+1].name=NULL;
// read in the data
GIO_LOAD_RECORD(skillgroup_type, &skillgroup_table[load_index], fp);
count++;
}
}
fclose( fp );
ch->printf("Finished reading skillgroup_table from " SKILLGROUPS_FILE ". (read in %d)\r\n", count);
logf("Finished reading skillgroup_table from " SKILLGROUPS_FILE ". (read in %d)", count);
fpReserve = fopen( NULL_FILE, "r" );
return;
}
/**************************************************************************/
// Entry Point for editing the skill groups
void do_skillgroupedit( char_data *ch, char *argument )
{
char arg[MIL];
if(!str_infix("create", argument)){
argument=one_argument(argument, arg);
}else{
strcpy(arg, argument);
}
if ( IS_NPC( ch )){
ch->println("Players only.");
return;
}
// do security checks
if (!HAS_SECURITY(ch, GROUPEDIT_MINSECURITY)){
ch->printlnf("You must have an olc security %d or higher to use this command.",
GROUPEDIT_MINSECURITY);
return;
}
if (!IS_TRUSTED(ch, GROUPEDIT_MINTRUST)){
ch->printlnf("You must have a trust of %d or above to use this command.",
GROUPEDIT_MINTRUST);
return;
}
if (IS_NULLSTR(arg)){
ch->println("Syntax: `=Cskgrpedit create <newskillgroup>`x");
ch->println(" or: `=Cskgrpedit <skillgroup>`x");
ch->println("Where <skillgroup> is one of the following:");
ch->println(" [remort number]<number of skills in group> group name");
// groups up below
int col=0;
for (int gn = 0; !IS_NULLSTR(skillgroup_table[gn].name); gn++)
{
// count the total skills in a group
int skcnt =0;
for ( int skcnti= 0; skillgroup_table[gn].skills[skcnti]>-1; skcnti++) {
skcnt++;
}
// display the group
ch->printf("`%c [%d]%2d %-33s `x",
IS_SET(skillgroup_table[gn].flags, SKILLGROUP_CREATION_SELECTABLE)?
(IS_SET(skillgroup_table[gn].flags, SKILLGROUP_FREE_FOR_ALL)?'G':'x')
:IS_SET(skillgroup_table[gn].flags, SKILLGROUP_FREE_FOR_ALL)?'g':'S',
skillgroup_table[gn].remort,skcnt,
skillgroup_table[gn].name);
if (++col % 2 == 0){
ch->println("");
}
}
if(col % 2 != 0){
ch->println("");
}
ch->println("NumberPrefix = remort, Colour coding flag guide: CS=creation selectable, FFA = free for all");
ch->println("`Gbright green= CS,FFA `gdark green = FFA `xwhite=CS `Ssilver=both flags unset.`x");
ch->println("CS=creation selectable, FFA = free for all (everyone can get it for free).");
return;
}
if ( !str_cmp( arg, "create" ))
{
// allocate space for a new skillgroup
int gn;
for ( gn=0; !IS_NULLSTR(skillgroup_table[gn].name); gn++){
// do nothing till we find the end
}
//load_index now points to the end of the list
if(gn>=MAX_SKILLGROUP){
ch->printlnf("There are too many skillgroups (%d), increase MAX_SKILLGROUP if you want to add more",
gn);
return;
}
// fill in the defaults for our entry
memset(skillgroup_table[gn].skills, -1, sizeof(skillgroup_table[0].skills));
memset(skillgroup_table[gn].rating, -1, sizeof(skillgroup_table[0].rating));
skillgroup_table[gn].name=str_dup(argument);
// mark the new end of the table
skillgroup_table[gn+1].name=NULL;
// update them on what is happening
ch->wraplnf( "`xCreated skillgroup '%s'",argument);
ch->println( "Type `=Cdone`x to finish editing." );
ch->desc->pEdit = (void*)&skillgroup_table[gn];
ch->desc->editor = ED_SKILLGROUP;
return;
}
int skillgroupindex=skillgroup_lookup(arg);
if(skillgroupindex<0){
ch->printlnf("Could not find a skillgroup '%s' to edit.", arg);
return;
}
ch->desc->pEdit = (void*)&skillgroup_table[skillgroupindex];
ch->desc->editor = ED_SKILLGROUP;
ch->printlnf("Editing skillgroup '%s' with skillgroup editor.",
skillgroup_table[skillgroupindex].name);
return;
}
/**************************************************************************/
// returns a negative amount if
int skillgroupedit_calc_individual_cost(skillgroup_type * pG, int classindex)
{
int total=0;
bool unattainable_skill=false;
for ( int i = 0; pG->skills[i]>-1; i++)
{
if(IS_SKILL_VALID_FOR_CLASS(pG->skills[i], classindex)){
total+=skill_table[pG->skills[i]].rating[classindex];
}else{
unattainable_skill=true;
}
}
if(unattainable_skill){
return (total+1)*-1;
}else{
return total;
}
}
/**************************************************************************/
bool skillgroupedit_show(char_data *ch, char *argument)
{
int i, count, showclass, classcost;
char skillcolour;
bool unused_skills=false;
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
SET_BIT(ch->dyn,DYN_SHOWFLAGS);
ch->titlebarf("SKILLGROUPEDIT: %s", uppercase(pG->name));
ch->printlnf( "`=rSkillgroup Name: `x%-10s `=rRemort: `x%d ",
capitalize(pG->name), pG->remort);
mxp_display_olc_flags(ch, skillgroup_flags, pG->flags, "flags", "Flags:");
// display the skills in the group, first count them then display
count =0;
for ( i = 0; pG->skills[i]>-1; i++) {
count++;
}
showclass=class_lookup(argument);
if(showclass<0){
skillcolour='x';
ch->titlebarf("SKILLS IN GROUP - %d TOTAL", count);
}else{
ch->titlebarf("SKILLS IN GROUP - %d TOTAL (CLASS FILTER=%s)",
count, uppercase(class_table[showclass].name));
}
for ( i = 0; pG->skills[i]>-1; i++)
{
if(showclass>-1 && !IS_SKILL_VALID_FOR_CLASS(pG->skills[i], showclass)){
skillcolour='R';
}else{
skillcolour='x';
}
if(i%3==2){
ch->printlnf(" `%c%s`x", skillcolour,
FORMATF("%s [%d%%]", skill_table[pG->skills[i]].name, pG->skillsvalue[i]));
}else{
ch->printf(" `%c%-27s`x", skillcolour,
FORMATF("%s [%d%%]", skill_table[pG->skills[i]].name, pG->skillsvalue[i]));
}
}
if(i%3!=0){
ch->println("");
}
// display the cost in trains for each class
ch->titlebar("COST (TRAINS)");
for(i=0; !IS_NULLSTR(class_table[i].name); i++){
// the free for all flag overwrites the cost
if(IS_SET(pG->flags, SKILLGROUP_FREE_FOR_ALL)){
classcost=0;
}else{
classcost=pG->rating[i];
}
if(classcost<0){
ch->printf(" %-23s `S------`x", class_table[i].name);
}else{
count=skillgroupedit_calc_individual_cost(pG, i);
if(count<0){
ch->printf(" %-23s `%c%2d`x(`R%2d`x)",
class_table[i].name,
(classcost<1?'G':'x'),
pG->rating[i],
(count*-1)-1);
unused_skills=true;
}else{
ch->printf(" %-23s `%c%2d`x(%2d)",
class_table[i].name,
(classcost<1?'G':'x'),
pG->rating[i],
skillgroupedit_calc_individual_cost(pG, i));
}
}
if(i%2==0){
ch->print(" ");
}else{
ch->println("");
}
}
ch->println("");
if(i%2!=0){
ch->println("");
}
ch->wrapln("The number before the brackets after a class name, is how much the group "
"costs for that class to gain/add. The number in brackets is the total of how "
"much each individual skill costs for that class.");
if(IS_SET(pG->flags, SKILLGROUP_FREE_FOR_ALL)){
ch->println("`S note: because 'free_for_all' is set, all classes can get this for 0 trains.");
ch->println(" and will automatically get it during creation (hence green on all)`x.");
}else{
ch->print_blank_lines(2);
}
if(unused_skills && showclass==-1){
// "-===========================================================================-"
ch->println("`S Classes with a red total (`R##`S) don't get access to all the skills listed");
ch->println(" above... use 'show <classname>' to see what skills they can/can't get.");
}else{
ch->print_blank_lines(2);
}
ch->titlebar("");
REMOVE_BIT(ch->dyn,DYN_SHOWFLAGS);
return false;
}
/**************************************************************************/
// add a skill to the currently edited group
bool skillgroupedit_addskill(char_data *ch, char *argument)
{
char arg[MIL];
int sn, i;
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
// check for arguments -> show syntax if none
if (IS_NULLSTR(argument)){
ch->println("groupedit_addskill(): syntax: `=Caddskill <skillname>`x");
ch->println("note: use `=Cremoveskill`x to remove skills from a skillgroup.");
return false;
}
// find the skill we are talking about
if (!str_prefix("'",argument)){ // ' symbol optional
argument = one_argument( argument, arg );
}else{
strcpy(arg, argument);
}
sn=skill_lookup(arg);
if(sn<0){
ch->printlnf("groupedit_addskill(): Couldn't find the skill '%s' to add.", arg);
return false;
}
// we have the gsn of a skill in sn... check it is not a spell
if(IS_SPELL(sn)){
ch->printlnf("groupedit_addskill(): '%s' is a spell, you can't add spells to skillgroups.",
skill_table[sn].name);
return false;
}
// check if the skill is already allocated
for (i = 0; pG->skills[i]>-1; i++){
if(pG->skills[i]==sn){
ch->printlnf("groupedit_addskill(): '%s' is already a skill in '%s'... use removeskill to remove it.",
skill_table[sn].name, pG->name);
return false;
}
}
// find the next free slot to store it
for (i = 0; pG->skills[i]>-1; i++){
}
if(i>=MAX_IN_GROUP){
ch->wraplnf("groupedit_addskill(): There is a maximum of %d skills in a skillgroup... "
"no room for any more skills... increase MAX_IN_GROUP in the code if more per "
"group is required.",
MAX_IN_GROUP);
return false;
}
// add the skill to the group
pG->skills[i+1]=-1; // safety code
pG->skills[i]=sn;
pG->skillsvalue[i]=1; // default to 1%
ch->printlnf("groupedit_addskill(): '%s' added to skillgroup '%s'.",
skill_table[sn].name, pG->name);
return true;
}
/**************************************************************************/
// change the skillvalue on a skill
bool skillgroupedit_skillvalue(char_data *ch, char *argument)
{
char arg[MIL];
char valarg[MIL];
int sn, i, value;
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
// check for arguments -> show syntax if none
if (IS_NULLSTR(argument)){
ch->println("syntax: `=Cskillvalue <skillname> <value>`x");
ch->println("note: value is the percentage they will get the skill at.");
ch->println("note: use `=Cremoveskill`x to remove skills from a skillgroup.");
return false;
}
// find the skill we are talking about
argument = one_argument( argument, arg );
argument = one_argument( argument, valarg);
sn=skill_lookup(arg);
if(sn<0){
ch->printlnf("No such skill '%s' exists.", arg);
return false;
}
// we have the gsn of a skill in sn... check it is not a spell
if(IS_SPELL(sn)){
ch->printlnf("'%s' is a spell, you can't add spells to skillgroups.",
skill_table[sn].name);
return false;
}
value=atoi(valarg);
if(value<0 || value>101 || !is_number(valarg)){
ch->printlnf("A sensible value is required for the percentage"
" - '%s' isn't valid here.", valarg);
return false;
}
// check if the skill is already allocated
for (i = 0; pG->skills[i]>-1; i++){
if(pG->skills[i]==sn){
ch->printlnf("Skill value of '%s' changed from %d to %d.",
skill_table[sn].name, pG->skillsvalue[i], value);
pG->skillsvalue[i]=value;
return true;
}
}
ch->printlnf("Couldn't find any '%s' to set a value on.", skill_table[sn].name);
return false;
}
/**************************************************************************/
// remove a skill from the currently edited group
bool skillgroupedit_removeskill(char_data *ch, char *argument)
{
char arg[MIL];
int sn, i, last;
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
// check for arguments -> show syntax if none
if (IS_NULLSTR(argument)){
ch->println("groupedit_removeskill(): syntax: `=Cremoveskill <skillname>`x");
ch->println("note: use `=Caddskill`x to add skills to a skillgroup.");
return false;
}
// find the skill we are talking about
if (!str_prefix("'",argument)){ // ' symbol optional
argument = one_argument( argument, arg );
}else{
strcpy(arg, argument);
}
sn=skill_lookup(arg);
if(sn<0){
ch->printlnf("groupedit_removeskill(): Couldn't find the skill '%s' to remove.", arg);
return false;
}
// find the skill
for (i = 0; pG->skills[i]>-1; i++){
if(pG->skills[i]==sn){
break;
}
}
if(i>=MAX_IN_GROUP){
ch->wraplnf("groupedit_removeskill(): the skill '%s' was not found in the skillgroup '%s' to remove.",
skill_table[sn].name, pG->name);
return false;
}
// find the last skill
for (last = 0; pG->skills[last]>-1; last++){
}
last--;
// remove the skill
if(last==i){
pG->skills[i]=-1;
}else{
pG->skills[i]=pG->skills[last];
pG->skills[last]=-1;
}
ch->wraplnf("groupedit_removeskill(): '%s' removed from skillgroup '%s'.",
skill_table[sn].name, pG->name);
return true;
}
/**************************************************************************/
bool skillgroupedit_flags(char_data *ch, char *argument)
{
int value;
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
if(!IS_NULLSTR(argument)){
if ( ( value = flag_value( skillgroup_flags, argument ) ) != NO_FLAG )
{
pG->flags ^= value;
ch->println("SkillGroup flag toggled.");
return true;
}
}
show_olc_options(ch, skillgroup_flags, "flags", "skillgroup", pG->flags );
return false;
}
/**************************************************************************/
// adjust the remort level a skillgroup requires
bool skillgroupedit_remort(char_data *ch, char *argument)
{
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
int value;
if( IS_NULLSTR(argument) || !is_number(argument)) {
ch->println("Syntax: remort <number>");
ch->println("Remort 0 = skillgroup available at first creation.");
ch->println("Remort 1 = skillgroup available at after first remort creation...");
return false;
}
value = atoi( argument );
if(value<0 || value>5){
ch->println("The remort value must be between 0 and 5.");
return false;
}
ch->printlnf("Remort value changed from %d to %d.",
pG->remort, value);
pG->remort= value;
return true;
}
/**************************************************************************/
bool skillgroupedit_rename(char_data *ch, char *argument)
{
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
if ( IS_NULLSTR(argument))
{
ch->println( "Syntax: rename <string>" );
return false;
}
if(IS_SET(pG->flags, SKILLGROUP_CREATION_SELECTABLE)){
ch->println("You cant rename a skillgroup that is creation selectable.");
return false;
}
ch->wraplnf("Skillgroup name changed from '%s' to '%s'.", pG->name, argument);
replace_string(pG->name, argument);
return true;
}
/**************************************************************************/
// adjust the cost a particular class pays for the skillgroup
bool skillgroupedit_cost(char_data *ch, char *argument)
{
if ( IS_NULLSTR(argument))
{
ch->println( "Syntax: cost <class> <amount>" );
ch->println( "Syntax: cost <class> free" );
ch->println( "Syntax: cost <class> na (not available)" );
return false;
}
// check we have the class
char classname[MIL];
argument=one_argument(argument, classname);
int class_index=class_lookup(classname);
if(class_index<0){
ch->printlnf("There is no class '%s'", classname);
return false;
}
skillgroup_type * pG;
EDIT_SKILLGROUP(ch, pG);
if(!str_cmp(argument,"free")){
pG->rating[class_index]=0;
ch->printlnf("Skillgroup '%s' is now free for the %s class.",
pG->name, class_table[class_index].name);
return false;
}
if(!str_cmp(argument,"na")){
pG->rating[class_index]=-1;
ch->printlnf("Skillgroup '%s' is now unavailable for the %s class (assuming the free_for_all flag is unset).",
pG->name, class_table[class_index].name);
return false;
}
if(!is_number(argument)){
ch->printlnf("Second argument must be 'free', 'na' or a numeric value, '%s' is none of these.",
argument);
skillgroupedit_cost(ch,"");
return false;
}
int value=atoi(argument);
if(value<1 || value >50){
ch->println("The cost value range is 1 to 50.");
return false;
}
if(pG->rating[class_index]>=0){
ch->printlnf("Skillgroup '%s' cost changed from %d to %d for the %s class.",
pG->name, pG->rating[class_index], value, class_table[class_index].name);
}else{
ch->printlnf("Skillgroup '%s' cost changed from being unavailable to %d for the %s class.",
pG->name, value, class_table[class_index].name);
}
pG->rating[class_index]=value;
value=skillgroupedit_calc_individual_cost(pG, class_index);
if(value<0){
value=(value+1)*-1;
ch->printlnf("The individual cost of all the skills in the skillgroup for '%s' is %d.",
class_table[class_index].name, value);
ch->println("Note: this total only applies to the skills which the class can get");
}else{
ch->printlnf("The individual cost of all the skills in the skillgroup for '%s' is %d.",
class_table[class_index].name, value);
}
if(value<pG->rating[class_index]){
ch->println("`Rnote: it costs more to purchase the skillgroup than the skills individually!`x");
}
return true;
}
/**************************************************************************/