This was done with a fresh copy of Rom26, and a freshly patched OLC 1.81. NOTE: This snippet is not for the beginning coder. Attempting to install this without at least a basic knowledge of C may be disastrous to your mental state. That said, this code isn't really complex, just long. One of the features of this code, is the 'flag' variables added to the skill_table and group_table. Use of flags like this makes configuring skills as guild or race specific easy. (for example) I've not included most of the skill and group flags we use, but here's some ideas; GROUP_ONLY Make the skill only selectable from within a group GUILD_ONLY Make the skill only available to guilded (any) characters SECT_FOREST Make the skill only work in 'forest' sectors etcetc. !! (This is used to indicate a change, searching for !! will help you to be able to locate the next required change) !! 1: Copy data_h.o, olc_group.c and olc_skill.c to your code directory. !! 2: Add data_h.o, olc_skill.o and olc_group.o to the O_FILES section of your Makefile !! 3 in olc.h (a-h steps) !! a: In the "Connected States for editor" section, add; (be sure to replace the 7 and 8 with valid numbers for your mud. These are 'default' only values for a stock Rom) #define ED_GROUP 7 #define ED_SKILL 8 !! b: in the "Interpreter Prototypes" section, add; void gredit (CHAR_DATA *ch, char *argument); void skedit (CHAR_DATA *ch, char *argument); !! c: in the "Interpreter Table Prototypes" section, add; extern const struct olc_cmd_type gredit_table[]; extern const struct olc_cmd_type skedit_table[]; !! d: in the "Editor Commands" section, add; DECLARE_DO_FUN( do_gredit ); DECLARE_DO_FUN( do_skedit ); !! e: after the "General Functions" section, add; /* * Skill Editor prototypes * by: Gary McNickle */ DECLARE_OLC_FUN( skedit_show ); DECLARE_OLC_FUN( skedit_save ); DECLARE_OLC_FUN( skedit_flags ); DECLARE_OLC_FUN( skedit_learn ); DECLARE_OLC_FUN( skedit_target ); DECLARE_OLC_FUN( skedit_position); DECLARE_OLC_FUN( skedit_wait ); DECLARE_OLC_FUN( skedit_msgs ); DECLARE_OLC_FUN( skedit_list ); DECLARE_OLC_FUN( skedit_mana ); DECLARE_OLC_FUN( skedit_levels ); /* * Group Editor prototypes * by: Gary McNickle */ DECLARE_OLC_FUN( gredit_create ); DECLARE_OLC_FUN( gredit_list ); DECLARE_OLC_FUN( gredit_flags ); DECLARE_OLC_FUN( gredit_name ); DECLARE_OLC_FUN( gredit_ratings ); DECLARE_OLC_FUN( gredit_skill ); DECLARE_OLC_FUN( gredit_show ); DECLARE_OLC_FUN( gredit_save ); DECLARE_OLC_FUN( gredit_delete ); !! f: In the "Macros" section, add; #define EDIT_SKILL(Ch, Skill) ( Skill = (SKILL_DATA *)Ch->desc->pEdit ) #define EDIT_GROUP(Ch, Group) ( Group = Ch->desc->pEdit ) !! g: In the "New typedefs" section, add; typedef const struct flag_type flagtype; !! h: In the "Utils" section, change the prototypes for flag_string and flag_value to; int flag_value (flagtype *flag_table, char *argument); char *flag_string (flagtype *flag_table, int bits); !! 4: in olc.c (a-i steps) !! a: in run_olc_editor, after the lines; case ED_HELP: hedit( d->character, d->incomm ); break; add; case ED_GROUP: gredit( d->character, d->incomm ); break; case ED_SKILL: skedit( d->character, d->incomm ); break; !! b: in olc_ed_name, after the lines; case ED_HELP: sprintf( buf, "Hedit" ); break; add; case ED_GROUP: sprintf( buf, "GREdit" ); break; case ED_SKILL: sprintf( buf, "SKedit" ); break; !! c: in olc_ed_vnum, at the top of the function, add SKILL_DATA *pSkill; GROUP_DATA *pGroup; then, after the lines; case ED_HELP: pHelp = (HELP_DATA *)ch->desc->pEdit; sprintf( buf, "%s", pHelp ? pHelp->keyword : "" ); break; add; case ED_GROUP: pGroup = (GROUP_DATA *)ch->desc->pEdit; sprintf( buf, "%d", group_lookup(pGroup->name) ? group_lookup(pGroup->name) : 0); break; case ED_SKILL: pSkill = (SKILL_DATA *)ch->desc->pEdit; sprintf( buf, "%s", pSkill ? pSkill->name : "" ); break; !! d: in show_commands, after the lines; case ED_HELP: show_olc_cmds( ch, hedit_table ); break; add; case ED_GROUP: show_olc_cmds( ch, gredit_table ); break; case ED_SKILL: show_olc_cmds( ch, skedit_table); break; !! e: in the "Interpreter Tables" section, add; const struct olc_cmd_type skedit_table[] = { { "commands", show_commands }, { "?", show_help }, { "mana", skedit_mana }, { "learn", skedit_learn }, { "list", skedit_list }, { "target", skedit_target }, { "position", skedit_position }, { "wait", skedit_wait }, { "msgs", skedit_msgs }, { "show", skedit_show }, { "save", skedit_save }, { "level", skedit_levels }, { "flags", skedit_flags }, { NULL, 0 } }; const struct olc_cmd_type gredit_table[] = { { "commands", show_commands }, { "create", gredit_create }, { "delete", gredit_delete }, { "flag", gredit_flags }, { "list", gredit_list }, { "name", gredit_name }, { "ratings", gredit_ratings }, { "save", gredit_save }, { "show", gredit_show }, { "skill", gredit_skill }, { "?", show_help }, { NULL, 0 } }; !! f: right after "get_area_data" function, add; /** Function: get_skill_data * Descr : Returns a pointer to the skill_table of the requested skill # * Returns : (SKILL_DATA *) * Syntax : (n/a) * Written : v1.0 1/99 * Author : Gary McNickle */ SKILL_DATA *get_skill_data( int skill ) { if ( skill <= MAX_SKILL && skill > -1 && (skill_table[skill].name != NULL && skill_table[skill].name[0] != '\0' )) return &skill_table[skill]; return &skill_table[0]; /* default skill */ } /** Function: get_group_data * Descr : Returns a pointer to the group_table of the requested group # * Returns : (GROUP_DATA *) * Syntax : (n/a) * Written : v1.0 7/98 * Author : Gary McNickle */ GROUP_DATA *get_group_data( int group ) { if ( group <= MAX_GROUP && group > -1 && (group_table[group].name != NULL && group_table[group].name[0] != '\0')) return &group_table[group]; return &group_table[0]; /* first group */ } !! g: Add the following functions to the "Interpreters" section; /** Function: gredit * Descr : Interprets commands sent while inside the group editor. * Returns : (N/A) * Syntax : (N/A| called by do_gredit only) * Written : v1.0 7/98 * Author : Gary McNickle */ void gredit( CHAR_DATA *ch, char *argument ) { GROUP_DATA *pGroup; char command[MIL]; char arg[MIL]; int cmd; EDIT_GROUP(ch, pGroup); smash_tilde( argument ); strcpy( arg, argument ); argument = one_argument( argument, command ); if ( ch->level < MAX_LEVEL -2 ) { send_to_char("Insuffecient security to modify group data", ch); edit_done( ch ); return; } if ( !str_cmp(command, "done") ) { edit_done( ch ); return; } if ( command[0] == '\0' ) { gredit_show( ch, argument ); return; } /* Search Table and Dispatch Command. */ for ( cmd = 0; gredit_table[cmd].name != NULL; cmd++ ) { if ( !str_prefix( command, gredit_table[cmd].name ) ) { if ( (*gredit_table[cmd].olc_fun) ( ch, argument ) ) { SET_BIT( pGroup->flags, GROUP_CHANGED ); return; } else return; } } /* Default to Standard Interpreter. */ interpret( ch, arg ); return; } /** Function: skedit * Descr : Interprets commands sent while inside the skill editor. * : Passing appropriate commands on to editor, rest to mud. * Returns : (N/A) * Syntax : (N/A| called by do_skedit only) * Written : v1.0 1/99 * Author : Gary McNickle */ void skedit( CHAR_DATA *ch, char *argument ) { SKILL_DATA *pSkill; char command[MIL]; char arg[MIL]; int cmd; EDIT_SKILL(ch, pSkill); smash_tilde( argument ); strcpy( arg, argument ); argument = one_argument( argument, command ); if ( ch->level < MAX_LEVEL -2 ) { send_to_char("Insuffecient security to modify skill data", ch); edit_done( ch ); return; } if ( !str_cmp(command, "done") ) { edit_done( ch ); return; } if ( command[0] == '\0' ) { skedit_show( ch, argument ); return; } /* Search Table and Dispatch Command. */ for ( cmd = 0; skedit_table[cmd].name != NULL; cmd++ ) { if ( !str_prefix( command, skedit_table[cmd].name ) ) { if ( (*skedit_table[cmd].olc_fun) ( ch, argument ) ) { SET_BIT( pSkill->flags, GROUP_CHANGED ); return; } else return; } } /* Default to Standard Interpreter. */ interpret( ch, arg ); return; } !! h: Add the following to the 'editor_table' structure; { "group", do_gredit }, { "skill", do_skedit }, !! i: Add the following 2 functions after the 'do_olc' function. /** Function: do_gredit * Descr : Places user into the group editor. Verifies security. * Returns : Message sent if improper security level. * Syntax : gredit [group #|create] * Written : v1.0 7/98 * Author : Gary McNickle */ void do_gredit(CHAR_DATA *ch, char *argument) { GROUP_DATA *pGroup; int value; char arg[MAX_STRING_LENGTH]; if ( IS_NPC(ch) ) return; pGroup = &group_table[0]; /* set default */ argument = one_argument(argument,arg); if ( is_number( arg ) ) { value = atoi( arg ); pGroup = get_group_data( value ); if (!pGroup->name || pGroup->name[0] == '\0') { send_to_char( "That group does not exist.\n\r", ch ); return; } } else if ( !str_cmp( arg, "create" ) ) { int i = 0; if ( ch->pcdata->security < 9 ) { send_to_char( "GREdit : Insuffecient security to create new groups.\n\r", ch ); return; } gredit_create( ch, "" ); /* since the group just created will be that last group in the group_table, we search backwards until we find one with a name */ for (i = MAX_GROUP; i > 0; i--) if ( group_table[i].name != NULL ) break; pGroup = get_group_data( i ); ch->desc->editor = ED_GROUP; return; } ch->desc->pEdit = (void *)pGroup; ch->desc->editor = ED_GROUP; return; } /** Function: do_skedit * Descr : Places user into the skill editor. Verifies Security. * Returns : Message if improper security level. * Syntax : skedit [skill #] * Written : v1.0 1/99 * Author : Gary McNickle */ void do_skedit(CHAR_DATA *ch, char *argument) { SKILL_DATA *pSkill; int value; char arg[MAX_STRING_LENGTH]; if ( IS_NPC(ch) ) return; pSkill = &skill_table[0]; /* set default */ argument = one_argument(argument,arg); if ( is_number( arg ) ) value = atoi( arg ) - 1; else value = skill_lookup(arg); pSkill = get_skill_data( value ); if (!pSkill || !pSkill->name || pSkill->name[0] == '\0') { send_to_char( "That skill does not exist.\n\r", ch ); return; } ch->desc->pEdit = (void *)pSkill; ch->desc->editor = ED_SKILL; return; } !! 5: In merc.h (steps a-g) !! a: In the "Structure types" section, add; typedef struct skill_type SKILL_DATA; typedef struct group_type GROUP_DATA; !! b: In the "Datafiles used by the server" section, add; #define DATA_DIR "../data/" /* To store data files */ #define GROUP_FILE "groups.dat" /* Group data file */ #define SKILL_DATA_FILE "skills.dat" /* Skill data file */ Then, be sure to create a 'data' directory in your directory structure. It should be the same depth as 'src'. So you should have in your mud directory (among others); src/ area/ data/ !! c: In the "Our Function Prototypes" section, add; /* olc.c */ void do_gredit (CHAR_DATA *ch, char *argument); void do_skedit (CHAR_DATA *ch, char *argument); void gredit (CHAR_DATA *ch, char *argument); void skedit (CHAR_DATA *ch, char *argument); SKILL_DATA *get_skill_data (int skill); GROUP_DATA *get_group_data (int group); /* data_h.c */ void logf(char *fmt, ...); bool save_skills( void ); bool load_skills( void ); bool save_groups( void ); bool load_groups( void ); !! d: In some appropriate spot, add; (Before 'Act bits for mobiles' is good) /* Group Flags */ #define GROUP_CHANGED A #define GROUP_DELETED B !! e: Find the lines; extern const struct skill_type skill_table [MAX_SKILL]; extern const struct group_type group_table [MAX_GROUP]; and change them to read as; extern struct skill_type skill_table [MAX_SKILL]; extern struct group_type group_table [MAX_GROUP]; !! f: To the 'group_type' structure, add; long flags; !! g: To the 'skill_type' structure, add; long flags; !! 7: in const.c !! a: Change the structures for 'skill_table' and 'group_table' to nolonger be constant. (ie: remove 'const' from the beginning of the structures) !! b: in skill_table, and group_table, add ", 0" (without the quotes) to the end of each entry for a skill or group. (time consuming, I know) !! 8: in tables.c, at the bottom of the file, add; const struct flag_type group_flags[] = { { "Changed", GROUP_CHANGED, FALSE }, { "Deleted", GROUP_DELETED, FALSE }, { NULL, 0, FALSE } }; const struct flag_type skill_flags[] = { { "Changed", GROUP_CHANGED, FALSE }, { "Deleted", GROUP_DELETED, FALSE }, { NULL, 0, FALSE } }; const struct flag_type target_flags[]= { { "ignore", TAR_IGNORE, TRUE }, { "char_offensive", TAR_CHAR_OFFENSIVE, TRUE }, { "char_defensive", TAR_CHAR_DEFENSIVE, TRUE }, { "char_self", TAR_CHAR_SELF, TRUE }, { "obj_inventory", TAR_OBJ_INV, TRUE }, { "obj_char_defensive", TAR_OBJ_CHAR_DEF, TRUE }, { "obj_char_offensive", TAR_OBJ_CHAR_OFF, TRUE }, { NULL, 0, 0 } }; !! 9: in tables.h, in the 'flag tables' section, add; extern const struct flag_type skill_flags[]; extern const struct flag_type group_flags[]; extern const struct flag_type target_flags[]; !! in db.c, in the 'boot_db()' function, Right above the lines; /* * Assign gsn's for skills which have them. */ Add a call to load_skills() and load_groups(); load_skills(); load_groups(); /* * Assign gsn's for skills which have them. */