#include "ctype.h" #include "stdio.h" #include "stdlib.h" #include "sys/types.h" #include <syslog.h> #include "define.h" #include "struct.h" #define HELP_IMMORTAL 0 #define HELP_SPELLS 1 #define HELP_FUNCTIONS 2 #define HELP_LOGIN 3 help_data** help_list; int max_help; bool help_modified = TRUE; void spell_help ( char_data*, int ); void make_w3 ( help_data* help ); /* * HELP_DATA CLASS */ class Help_Data { public: char* name; char* text; char* immortal; int level [ 2 ]; int category; Help_Data ( ); ~Help_Data ( ); friend char* name( help_data* help ) { return help->name; } }; Help_Data :: Help_Data( ) { record_new( sizeof( help_data ), MEM_HELP ); name = (char*) empty_string; text = (char*) empty_string; immortal = (char*) empty_string; level[0] = 0; level[1] = 0; category = 0; } Help_Data :: ~Help_Data( ) { int pos; record_delete( sizeof( help_data ), MEM_HELP ); free_string( name, MEM_HELP ); free_string( text, MEM_HELP ); free_string( immortal, MEM_HELP ); for( pos = 0; pos < max_help; pos++ ) if( help_list[pos] == this ) { remove( help_list, max_help, pos ); break; } } /* * READ/WRITE ROUTINES */ void load_helps( void ) { help_data* help; FILE* fp; int pos; echo( "Loading Help ...\n\r" ); help_list = NULL; max_help = 0; fp = open_file( HELP_FILE, "r" ); if( strcmp( fread_word( fp ), "#HELPS" ) ) panic( "Load_helps: missing header" ); for( ; ; ) { help = new help_data; help->level[0] = fread_number( fp ); help->level[1] = fread_number( fp ); help->category = fread_number( fp ); help->name = fread_string( fp, MEM_HELP ); if( *help->name == '$' ) { delete help; break; } help->text = fread_string( fp, MEM_HELP ); help->immortal = fread_string( fp, MEM_HELP ); pos = pntr_search( help_list, max_help, help->name ); if( pos < 0 ) pos = -pos-1; insert( help_list, max_help, help, pos ); } fclose( fp ); } bool save_help( char_data* ch ) { char buf [ TWO_LINES ]; help_data* help; FILE* fp; int pos; if( !help_modified ) return FALSE; if( ( fp = open_file( HELP_FILE, "w" ) ) == NULL ) return FALSE; fprintf( fp, "#HELPS\n" ); for( pos = 0; pos < max_help; pos++ ) { help = help_list[pos]; fprintf( fp, "%d %d %d %s~\n", help->level[0], help->level[1], help->category, help->name ); fprintf( fp, ".%s~\n\n", help->text ); fprintf( fp, ".%s~\n\n", help->immortal ); } fprintf( fp, "-1 -1 -1 $~\n" ); fclose( fp ); help_modified = FALSE; if( ch != NULL ) { send( ch, "Help file written.\n\r" ); sprintf( buf, "Help file written (%s).", ch->real_name() ); info( "", LEVEL_HELP, buf, IFLAG_WRITES, 1, ch ); } return TRUE; } /* * W3 ROUTINES */ void smash_color( char* tmp ) { int i; int j; for( i = j = 0; tmp[i] != '\0'; i++ ) { if( tmp[i] == '\n' || tmp[i] == '\r' ) continue; if( tmp[i] == '@' ) { if( tmp[++i] == '\0' ) break; if( tmp[i] != '@' ) continue; } if( tmp[i] == '<' ) tmp[j++] = '['; else if( tmp[i] == '>' ) tmp[j++] = ']'; else tmp[j++] = tmp[i]; } tmp[j] = '\0'; return; } void w3_help( ) { char tmp [ FOUR_LINES ]; int i; int pos; FILE* fp; sprintf( tmp, "%shelp/index.html", W3_DIR ); if( ( fp = open_file( tmp, "w" ) ) == NULL ) return; fprintf( fp, "<html>\n" ); fprintf( fp, "<body>\n" ); for( i = 0; i < MAX_ENTRY_HELP_CAT; i++ ) { sprintf( tmp, "./%s/index.html", help_cat_table[i].name ); smash_spaces( tmp ); fprintf( fp, "<p><a href=\"%s\"> %s </a></p>\n", tmp, help_cat_table[i].name ); sprintf( tmp, "mkdir %shelp/%s/", W3_DIR, help_cat_table[i].name ); smash_spaces( &tmp[6] ); system( tmp ); } fprintf( fp, "</html>\n" ); fprintf( fp, "</body>\n" ); fclose( fp ); for( i = 0; i < MAX_ENTRY_HELP_CAT; i++ ) { sprintf( tmp, "%shelp/%s/index.html", W3_DIR, help_cat_table[i].name ); smash_spaces( tmp ); if( ( fp = fopen( tmp, "w" ) ) == NULL ) { bug( "W3_Help: Fopen error" ); return; } fprintf( fp, "<html>\n" ); fprintf( fp, "<body>\n" ); for( pos = 0; pos < max_help; pos++ ) { if( help_list[pos]->category == i ) { sprintf( tmp, "./%s", help_list[pos]->name ); smash_spaces( tmp ); fprintf( fp, "<p><a href=\"%s\"> %s </a></p>\n", tmp, help_list[pos]->name ); } } fprintf( fp, "</html>\n" ); fprintf( fp, "</body>\n" ); fclose( fp ); } for( pos = 0; pos < max_help; pos++ ) make_w3( help_list[pos] ); return; } void make_w3( help_data* help ) { char tmp [ FOUR_LINES ]; char* input; FILE* fp; sprintf( tmp, "%shelp/%s/%s", W3_DIR, help_cat_table[ help->category ].name, help->name ); smash_spaces( tmp ); if( ( fp = fopen( tmp, "w" ) ) == NULL ) { bug( "Make_W3( help ): Fopen error" ); return; } fprintf( fp, "<html>\n" ); fprintf( fp, "<body>\n" ); for( input = help->text; *input != '\0'; ) { input = one_line( input, tmp ); smash_color( tmp ); if( !strcasecmp( tmp, "Syntax" ) ) fprintf( fp, "<h1> Syntax </h1>\n" ); else if( !strcasecmp( tmp, "Description" ) ) fprintf( fp, "<h1> Description </h1>\n" ); else fprintf( fp, "%s<br>\n", tmp ); } fprintf( fp, "</html>\n" ); fprintf( fp, "</body>\n" ); fclose( fp ); return; } /* * FIND_HELP ROUTINE */ bool can_read( char_data* ch, help_data* help ) { return has_permission( ch, help->level ); } help_data* find_help( char_data* ch, const char* argument ) { help_data* help; int first = -2; int pos; if( number_arg( argument, pos ) ) { if( pos < 0 || pos >= max_help ) { send( ch, "There is no help file with that index.\n\r" ); return NULL; } if( !can_read( ch, help_list[pos] ) ) { send( ch, "You do not have the required permission.\n\r" ); return NULL; } return help_list[pos]; } pos = pntr_search( help_list, max_help, argument ); if( pos >= 0 ) { if( can_read( ch, help_list[pos] ) ) return help_list[pos]; pos++; } else pos = -pos-1; for( ; pos < max_help; pos++ ) { help = help_list[pos]; if( !fmatches( argument, help->name ) ) break; if( can_read( ch, help ) ) { if( first != -2 ) { if( first != -1 ) { page( ch, "More than one match was found - please be more\ specific in what topic you\n\rwant help on.\n\r\n\r" ); page( ch, " [%3d] %s:%15s%s\n\r", first, help_cat_table[help_list[first]->category].name, "", help_list[first]->name ); first = -1; } page( ch, " [%3d] %s:%15s%s\n\r", pos, help_cat_table[help->category].name, "", help->name ); } else { first = pos; } } } if( first >= 0 ) return help_list[first]; if( first == -2 ) send( ch, "No matching help file was found - use index to see a list of\ topics for\n\rwhich help exists.\n\r" ); return NULL; } /* * MAIN HELP ROUTINE */ void do_help( char_data* ch, char* argument ) { char tmp [ 3*MAX_STRING_LENGTH ]; help_data* help; int i; int length = strlen( argument ); if( pet_help( ch ) || ch->link == NULL ) return; if( ( help = find_help( ch, *argument == '\0' ? "summary" : argument ) ) == NULL ) return; if( ch->link->connected != CON_PLAYING ) { send( ch, help->text ); return; } if( help->category == HELP_SPELLS ) for( i = 0; i < MAX_SPELL; i++ ) if( !strncasecmp( spell_table[i].name, argument, length ) ) { spell_help( ch, i ); return; } page( ch, "Topic: %s\n\r", help->name ); if( is_builder( ch ) ) { strcpy( tmp, "Level: " ); permission_flags.sprint( &tmp[7], help->level ); strcat( tmp, "\n\r" ); page( ch, tmp ); } page( ch, "\n\r" ); convert_to_ansi( ch, help->text, tmp ); page( ch, tmp ); if( help->immortal != empty_string && is_builder( ch ) ) { page( ch, "\n\r" ); convert_to_ansi( ch, help->immortal, tmp ); page( ch, tmp ); } return; } void help_link( link_data* link, const char* argument ) { char tmp [ 3*MAX_STRING_LENGTH ]; int pos; pos = pntr_search( help_list, max_help, argument ); if( pos < 0 ) { send( link, "Help subject %s not found.\n\r", argument ); } else if( link->player != NULL && link->player->pcdata != NULL ) { convert_to_ansi( link->player, help_list[pos]->text, tmp ); if( link->connected == CON_PLAYING ) page( link->player, tmp ); else send( link, tmp ); } else { send( link, help_list[pos]->text ); } return; } void do_motd( char_data* ch, char* ) { do_help( ch, "motd" ); return; } /* * INDEX COMMAND */ void do_index( char_data* ch, char* argument ) { char tmp [ MAX_STRING_LENGTH ]; int length = strlen( argument ); help_data* help; int i, j; int pos; int trust = get_trust( ch ); if( *argument =='\0' ) { page_title( ch, "Help Categories" ); for( i = j = 0; i < MAX_ENTRY_HELP_CAT; i++ ) if( help_cat_table[i].level <= trust ) { sprintf( tmp, "%18s%s", help_cat_table[i].name, (j++)%4 != 3 ? "" : "\n\r" ); page( ch, tmp ); } page( ch, "\n\r%s", j%4 != 0 ? "\n\r" : "" ); page_centered( ch, "[ Type index <category> to see a list of help\ files in that category. ]" ); return; } for( i = 0; i < MAX_ENTRY_HELP_CAT; i++ ) if( help_cat_table[i].level <= trust && !strncasecmp( argument, help_cat_table[i].name, length ) ) break; if( i == MAX_ENTRY_HELP_CAT ) { send( ch, "Unknown help category.\n\r" ); return; } page_title( ch, "Help Files - %s", help_cat_table[i].name ); for( j = 0, pos = 0; pos < max_help; pos++ ) { help = help_list[pos]; if( help->category != i || !can_read( ch, help ) ) continue; page( ch, "%18s%s", help->name, ++j%4 ? "" : "\n\r" ); } if( j%4 != 0 ) page( ch, "\n\r" ); page( ch, "\n\r" ); page_centered( ch, "[ Type help <file> to read a help file. ]" ); return; } /* * ONLINE EDITING OF HELP */ void do_hedit( char_data *ch, char *argument ) { help_data* help = ch->pcdata->help_edit; wizard_data* imm; int pos; if( *argument == '\0' ) { send( ch, "What help file do you wish to edit?\n\r" ); return; } if( !strncasecmp( argument, "delete", 6 ) ) { if( help == NULL ) { send( ch, "You aren't editing any help file.\n\r" ); return; } for( int i = 0; i < player_list; i++ ) { if( ( imm = wizard( player_list[i] ) ) != NULL && imm->Is_Valid( ) && imm->pcdata->help_edit == help && imm != ch ) { send( ch, "The help file you are editing was just deleted.\n\r" ); imm->pcdata->help_edit = NULL; } } help_modified = TRUE; ch->pcdata->help_edit = NULL; send( ch, "Help file '%s' removed.\n\r", help->name ); delete help; return; } if( !strncasecmp( argument, "new ", 4 ) ) { argument += 4; if( argument[0] == '\0' ) { send( "On what subject do you want to create a help?\n\r", ch ); return; } help = new help_data; help->name = alloc_string( argument, MEM_HELP ); pos = pntr_search( help_list, max_help, "blank" ); if( pos >= 0 ) help->text = alloc_string( help_list[pos]->text, MEM_HELP ); else help->text = (char*) empty_string; pos = pntr_search( help_list, max_help, argument ); if( pos < 0 ) pos = -pos-1; insert( help_list, max_help, help, pos ); ch->pcdata->help_edit = help; send( "Help subject created.\n\r", ch ); help_modified = TRUE; return; } if( ( help = find_help( ch, argument ) ) == NULL ) return; ch->pcdata->help_edit = help; send( ch, "Hdesc and hset now operate on %s.\n\r", help->name ); } void do_hdesc( char_data *ch, char *argument ) { help_data* help = ch->pcdata->help_edit; if( help == NULL ) { send( ch, "You are not editing any subject.\n\r" ); return; } help->text = edit_string( ch, argument, help->text, MEM_HELP ); help_modified = TRUE; } void do_hbug( char_data* ch, char* argument ) { help_data* help = ch->pcdata->help_edit; if( help == NULL ) { send( ch, "You are not editing any subject.\n\r" ); return; } help->immortal = edit_string( ch, argument, help->immortal, MEM_HELP ); help_modified = TRUE; } void do_hset( char_data *ch, char *argument ) { help_data* help = ch->pcdata->help_edit; if( help == NULL ) { send( ch, "You are not editing any subject.\n\r" ); return; } if( *argument == '\0' ) { send( ch, "Syntax: hset <field> <value>\n\r" ); return; } help_modified = TRUE; if( matches( argument, "level" ) ) { permission_flags.set( ch, argument, help->level ); return; } #define hcn( i ) help_cat_table[i].name class type_field type_list[] = { { "category", MAX_ENTRY_HELP_CAT, &hcn(0), &hcn(1), &help->category }, { "", 0, NULL, NULL, NULL } }; #undef hcn if( process( type_list, ch, help->name, argument ) ) return; if( matches( argument, "name" ) ) { if( *argument == '\0' ) { send( ch, "What do you want to set the help name to?\n\r" ); return; } send( ch, "Help name changed from %s to %s.\n\r", help->name, argument ); free_string( help->name, MEM_HELP ); help->name = alloc_string( argument, MEM_HELP ); return; } send( ch, "See help hset.\n\r" ); } /* * FUNCTION HELP */ void do_functions( char_data* ch, char* argument ) { char tmp [ MAX_STRING_LENGTH ]; char buf [ MAX_STRING_LENGTH ]; bool found = FALSE; int length = strlen( argument ); int pos; pos = pntr_search( help_list, max_help, argument ); if( pos >= 0 && help_list[pos]->category == HELP_FUNCTIONS ) { convert_to_ansi( ch, help_list[pos]->text, buf ); page( ch, buf ); return; } for( int i = 0; cfunc_list[i].name[0] != '\0'; i++ ) { if( strncasecmp( argument, cfunc_list[i].name, length ) ) continue; if( !found ) { found = TRUE; sprintf( tmp, "%-15s %-45s %s\n\r", "Function Name", "Arguments", "Returns" ); sprintf( tmp+strlen( tmp ), "%-15s %-45s %s\n\r", "-------- ----", "---------", "-------" ); page( ch, tmp ); } sprintf( tmp, "%-15s (", cfunc_list[i].name ); for( int j = 0; j < 4; j++ ) if( cfunc_list[i].arg[j] != NONE ) sprintf( tmp+strlen( tmp ), "%s %s", j == 0 ? "" : ",", arg_type_name[ cfunc_list[i].arg[j] ] ); sprintf( tmp+strlen( tmp ), " )" ); sprintf( buf, "%-61s %s\n\r", tmp, arg_type_name[ cfunc_list[i].type ] ); page( ch, buf ); } if( !found ) send( ch, "No matching function found.\n\r" ); } /* * SPELL HELP ROUTINE */ void do_spells( char_data* ch, char* argument ) { int i; if( pet_help( ch ) || ch->link == NULL ) return; if( argument[0] == '\0' ) { send( "What spell do you want info on?\n\r[To get a list of spells\ type abil sp <class>.]\n\r", ch ); return; } for( i = 0; i < MAX_SPELL; i++ ) if( !strncasecmp( spell_table[i].name, argument, strlen( argument ) ) ) break; if( i == MAX_SPELL ) { send( "Unknown Spell.\n\r", ch ); } else { spell_help( ch, i ); } return; } void spell_help( char_data* ch, int i ) { char tmp [ 3*MAX_STRING_LENGTH ]; bool found = FALSE; obj_clss_data* reagent; int j, k; int pos; int length; int level; help_data* help; sprintf( tmp, "%10sName: %s\n\r Energy Cost: %s\n\r Turns to Cast: %d\n\r", "", spell_table[i].name, spell_table[i].cast_mana, spell_table[i].wait ); page( ch, tmp ); if( spell_table[i].duration != empty_string ) page( ch, " Duration: %s\n\r", spell_table[i].duration ); if( spell_table[i].damage != empty_string ) page( ch, " Damage: %s\n\r", spell_table[i].damage ); if( spell_table[i].leech_mana != empty_string ) page( ch, " Leech of Max: %s\n\r", spell_table[i].leech_mana ); if( spell_table[i].regen != empty_string ) page( ch, " Regen Leech: %s\n\r", spell_table[i].regen ); if( is_builder( ch ) ) page( ch, "%10sSlot: %d\n\r", "", i ); strcpy( tmp, " Class/Level:" ); for( j = 0; j < MAX_CLSS; j++ ) if( ( level = skill_table[SPELL_FIRST+i].level[j] ) > 0 && clss_table[j].open ) { length = strlen( tmp ); sprintf( tmp+length, "%s %s %d%s", found ? "," : "", clss_table[j].name, level, number_suffix( level ) ); length += found+1; tmp[length] = toupper( tmp[length] ); found = TRUE; } sprintf( tmp+strlen( tmp ), "%s\n\r", found ? "" : " none" ); page( ch, tmp ); found = FALSE; page( ch, "--------------------------------\n\r" ); page( ch, "Description:\n\r\n\r" ); pos = pntr_search( help_list, max_help, spell_table[i].name ); if( pos >= 0 ) { help = help_list[pos]; convert_to_ansi( ch, help->text, tmp ); page( ch, tmp ); if( help->immortal != empty_string && is_builder( ch ) ) { page( ch, "\n\r" ); convert_to_ansi( ch, help->immortal, tmp ); page( ch, tmp ); } } else page( ch, "none\n\r" ); page( ch, "\n\rReagents:\n\r" ); for( j = 0; j < MAX_SPELL_WAIT; j++ ) { for( k = 0; k < j; k++ ) if( abs( spell_table[i].reagent[j] ) == abs( spell_table[i].reagent[k] ) ) break; if( k != j ) continue; if( ( reagent = get_obj_index( abs( spell_table[i].reagent[j] ) ) ) == NULL ) continue; found = TRUE; page( ch, " %s\n\r", reagent->Name( ) ); } if( !found ) page( ch, " none\n\r" ); return; }