/*************************************************************************** * STAR WARS REALITY 1.0 * *--------------------------------------------------------------------------* * Star Wars Reality Code Additions and changes from the Smaug Code * * copyright (c) 1997 by Sean Cooper * * -------------------------------------------------------------------------* * Starwars and Starwars Names copyright(c) Lucas Film Ltd. * *--------------------------------------------------------------------------* * SMAUG 1.0 (C) 1994, 1995, 1996 by Derek Snider * * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus, * * Scryn, Rennard, Swordbearer, Gorog, Grishnakh and Tricops * * ------------------------------------------------------------------------ * * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * ------------------------------------------------------------------------ * * Table load/save Module * ****************************************************************************/ #include <time.h> #include <stdio.h> #include <string.h> #include <dlfcn.h> #include "mud.h" /* global variables */ int top_sn; int top_herb; SKILLTYPE *skill_table[MAX_SKILL]; SKILLTYPE *herb_table[MAX_HERB]; char *const skill_tname[] = { "unknown", "Spell", "Skill", "Weapon", "Tongue", "Herb" }; SPELL_FUN *spell_function( char *name ) { void *funHandle; const char *error; funHandle = dlsym( sysdata.dlHandle, name ); if( ( error = dlerror() ) != NULL ) { bug( "Error locating %s in symbol table. %s", name, error ); return spell_notfound; } return (SPELL_FUN*)funHandle; } DO_FUN *skill_function( char *name ) { void *funHandle; const char *error; funHandle = dlsym( sysdata.dlHandle, name ); if( ( error = dlerror() ) != NULL ) { bug( "Error locating %s in symbol table. %s", name, error ); return skill_notfound; } return (DO_FUN*)funHandle; } /* * Function used by qsort to sort skills */ int skill_comp( SKILLTYPE ** sk1, SKILLTYPE ** sk2 ) { SKILLTYPE *skill1 = ( *sk1 ); SKILLTYPE *skill2 = ( *sk2 ); if( !skill1 && skill2 ) return 1; if( skill1 && !skill2 ) return -1; if( !skill1 && !skill2 ) return 0; if( skill1->type < skill2->type ) return -1; if( skill1->type > skill2->type ) return 1; return strcasecmp( skill1->name, skill2->name ); } /* * Sort the skill table with qsort */ void sort_skill_table( ) { log_string( "Sorting skill table..." ); qsort( &skill_table[1], top_sn - 1, sizeof( SKILLTYPE * ), ( int ( * )( const void *, const void * ) )skill_comp ); } /* * Write skill data to a file */ void fwrite_skill( FILE * fpout, SKILLTYPE * skill ) { SMAUG_AFF *aff; fprintf( fpout, "Name %s~\n", skill->name ); fprintf( fpout, "Type %s\n", skill_tname[skill->type] ); fprintf( fpout, "Flags %d\n", skill->flags ); if( skill->target ) fprintf( fpout, "Target %d\n", skill->target ); if( skill->minimum_position ) fprintf( fpout, "Minpos %d\n", skill->minimum_position ); if( skill->saves ) fprintf( fpout, "Saves %d\n", skill->saves ); if( skill->slot ) fprintf( fpout, "Slot %d\n", skill->slot ); if( skill->min_mana ) fprintf( fpout, "Mana %d\n", skill->min_mana ); if( skill->beats ) fprintf( fpout, "Rounds %d\n", skill->beats ); if( skill->guild != -1 ) fprintf( fpout, "Guild %d\n", skill->guild ); if( skill->skill_fun ) fprintf( fpout, "Code %s\n", skill->skill_fun_name ); else if( skill->spell_fun ) fprintf( fpout, "Code %s\n", skill->spell_fun_name ); fprintf( fpout, "Dammsg %s~\n", skill->noun_damage ); if( skill->msg_off && skill->msg_off[0] != '\0' ) fprintf( fpout, "Wearoff %s~\n", skill->msg_off ); if( skill->hit_char && skill->hit_char[0] != '\0' ) fprintf( fpout, "Hitchar %s~\n", skill->hit_char ); if( skill->hit_vict && skill->hit_vict[0] != '\0' ) fprintf( fpout, "Hitvict %s~\n", skill->hit_vict ); if( skill->hit_room && skill->hit_room[0] != '\0' ) fprintf( fpout, "Hitroom %s~\n", skill->hit_room ); if( skill->miss_char && skill->miss_char[0] != '\0' ) fprintf( fpout, "Misschar %s~\n", skill->miss_char ); if( skill->miss_vict && skill->miss_vict[0] != '\0' ) fprintf( fpout, "Missvict %s~\n", skill->miss_vict ); if( skill->miss_room && skill->miss_room[0] != '\0' ) fprintf( fpout, "Missroom %s~\n", skill->miss_room ); if( skill->die_char && skill->die_char[0] != '\0' ) fprintf( fpout, "Diechar %s~\n", skill->die_char ); if( skill->die_vict && skill->die_vict[0] != '\0' ) fprintf( fpout, "Dievict %s~\n", skill->die_vict ); if( skill->die_room && skill->die_room[0] != '\0' ) fprintf( fpout, "Dieroom %s~\n", skill->die_room ); if( skill->imm_char && skill->imm_char[0] != '\0' ) fprintf( fpout, "Immchar %s~\n", skill->imm_char ); if( skill->imm_vict && skill->imm_vict[0] != '\0' ) fprintf( fpout, "Immvict %s~\n", skill->imm_vict ); if( skill->imm_room && skill->imm_room[0] != '\0' ) fprintf( fpout, "Immroom %s~\n", skill->imm_room ); if( skill->dice && skill->dice[0] != '\0' ) fprintf( fpout, "Dice %s~\n", skill->dice ); if( skill->value ) fprintf( fpout, "Value %d\n", skill->value ); if( skill->difficulty ) fprintf( fpout, "Difficulty %d\n", skill->difficulty ); if( skill->participants ) fprintf( fpout, "Participants %d\n", skill->participants ); if( skill->components && skill->components[0] != '\0' ) fprintf( fpout, "Components %s~\n", skill->components ); if( skill->teachers && skill->teachers[0] != '\0' ) fprintf( fpout, "Teachers %s~\n", skill->teachers ); for( aff = skill->affects; aff; aff = aff->next ) fprintf( fpout, "Affect '%s' %d '%s' %d\n", aff->duration, aff->location, aff->modifier, aff->bitvector ); if( skill->alignment ) fprintf( fpout, "Alignment %d\n", skill->alignment ); if( skill->type != SKILL_HERB ) { fprintf( fpout, "Minlevel %d\n", skill->min_level ); } fprintf( fpout, "End\n\n" ); } /* * Save the skill table to disk */ void save_skill_table( ) { int x; FILE *fpout; if( ( fpout = fopen( SKILL_FILE, "w" ) ) == NULL ) { bug( "Cannot open skills.dat for writting", 0 ); perror( SKILL_FILE ); return; } for( x = 0; x < top_sn; x++ ) { if( !skill_table[x]->name || skill_table[x]->name[0] == '\0' ) break; fprintf( fpout, "#SKILL\n" ); fwrite_skill( fpout, skill_table[x] ); } fprintf( fpout, "#END\n" ); fclose( fpout ); } /* * Save the herb table to disk */ void save_herb_table( ) { int x; FILE *fpout; if( ( fpout = fopen( HERB_FILE, "w" ) ) == NULL ) { bug( "Cannot open herbs.dat for writting", 0 ); perror( HERB_FILE ); return; } for( x = 0; x < top_herb; x++ ) { if( !herb_table[x]->name || herb_table[x]->name[0] == '\0' ) break; fprintf( fpout, "#HERB\n" ); fwrite_skill( fpout, herb_table[x] ); } fprintf( fpout, "#END\n" ); fclose( fpout ); } /* * Save the socials to disk */ void save_socials( ) { FILE *fpout; SOCIALTYPE *social; int x; if( ( fpout = fopen( SOCIAL_FILE, "w" ) ) == NULL ) { bug( "Cannot open socials.dat for writting", 0 ); perror( SOCIAL_FILE ); return; } for( x = 0; x < 27; x++ ) { for( social = social_index[x]; social; social = social->next ) { if( !social->name || social->name[0] == '\0' ) { bug( "Save_socials: blank social in hash bucket %d", x ); continue; } fprintf( fpout, "#SOCIAL\n" ); fprintf( fpout, "Name %s~\n", social->name ); if( social->char_no_arg ) fprintf( fpout, "CharNoArg %s~\n", social->char_no_arg ); else bug( "Save_socials: NULL char_no_arg in hash bucket %d", x ); if( social->others_no_arg ) fprintf( fpout, "OthersNoArg %s~\n", social->others_no_arg ); if( social->char_found ) fprintf( fpout, "CharFound %s~\n", social->char_found ); if( social->others_found ) fprintf( fpout, "OthersFound %s~\n", social->others_found ); if( social->vict_found ) fprintf( fpout, "VictFound %s~\n", social->vict_found ); if( social->char_auto ) fprintf( fpout, "CharAuto %s~\n", social->char_auto ); if( social->others_auto ) fprintf( fpout, "OthersAuto %s~\n", social->others_auto ); fprintf( fpout, "End\n\n" ); } } fprintf( fpout, "#END\n" ); fclose( fpout ); } int get_skill( char *skilltype ) { if( !str_cmp( skilltype, "Spell" ) ) return SKILL_SPELL; if( !str_cmp( skilltype, "Skill" ) ) return SKILL_SKILL; if( !str_cmp( skilltype, "Weapon" ) ) return SKILL_WEAPON; if( !str_cmp( skilltype, "Tongue" ) ) return SKILL_TONGUE; if( !str_cmp( skilltype, "Herb" ) ) return SKILL_HERB; return SKILL_UNKNOWN; } /* * Save the commands to disk */ void save_commands( ) { FILE *fpout; CMDTYPE *command; int x; if( ( fpout = fopen( COMMAND_FILE, "w" ) ) == NULL ) { bug( "Cannot open commands.dat for writing", 0 ); perror( COMMAND_FILE ); return; } for( x = 0; x < 126; x++ ) { for( command = command_hash[x]; command; command = command->next ) { if( !command->name || command->name[0] == '\0' ) { bug( "Save_commands: blank command in hash bucket %d", x ); continue; } fprintf( fpout, "#COMMAND\n" ); fprintf( fpout, "Name %s~\n", command->name ); fprintf( fpout, "Code %s\n", command->fun_name?command->fun_name:"" ); // Modded to use new field - Trax fprintf( fpout, "Position %d\n", command->position ); fprintf( fpout, "Level %d\n", command->level ); fprintf( fpout, "Log %d\n", command->log ); fprintf( fpout, "End\n\n" ); } } fprintf( fpout, "#END\n" ); fclose( fpout ); } SKILLTYPE *fread_skill( FILE * fp ) { char buf[MAX_STRING_LENGTH]; char *word; bool fMatch; SKILLTYPE *skill; CREATE( skill, SKILLTYPE, 1 ); skill->guild = -1; for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'A': KEY( "Alignment", skill->alignment, fread_number( fp ) ); if( !str_cmp( word, "Affect" ) ) { SMAUG_AFF *aff; CREATE( aff, SMAUG_AFF, 1 ); aff->duration = str_dup( fread_word( fp ) ); aff->location = fread_number( fp ); aff->modifier = str_dup( fread_word( fp ) ); aff->bitvector = fread_number( fp ); aff->next = skill->affects; skill->affects = aff; fMatch = TRUE; break; } break; case 'C': if ( !str_cmp( word, "Code" ) ) { SPELL_FUN *spellfun; DO_FUN *dofun; char *w = fread_word( fp ); fMatch = TRUE; if( !str_prefix( "do_", w ) && ( dofun = skill_function(w) ) != skill_notfound ) { skill->skill_fun = dofun; skill->spell_fun = NULL; skill->skill_fun_name = str_dup(w); } else if( str_prefix( "do_", w ) && ( spellfun = spell_function(w) ) != spell_notfound ) { skill->spell_fun = spellfun; skill->skill_fun = NULL; skill->spell_fun_name = str_dup(w); } else { bug( "%s: unknown skill/spell %s", __FUNCTION__, w ); skill->spell_fun = spell_null; } break; } KEY( "Components", skill->components, fread_string_nohash( fp ) ); break; case 'D': KEY( "Dammsg", skill->noun_damage, fread_string_nohash( fp ) ); KEY( "Dice", skill->dice, fread_string_nohash( fp ) ); KEY( "Diechar", skill->die_char, fread_string_nohash( fp ) ); KEY( "Dieroom", skill->die_room, fread_string_nohash( fp ) ); KEY( "Dievict", skill->die_vict, fread_string_nohash( fp ) ); KEY( "Difficulty", skill->difficulty, fread_number( fp ) ); break; case 'E': if( !str_cmp( word, "End" ) ) return skill; break; case 'F': KEY( "Flags", skill->flags, fread_number( fp ) ); break; case 'G': KEY( "Guild", skill->guild, fread_number( fp ) ); break; case 'H': KEY( "Hitchar", skill->hit_char, fread_string_nohash( fp ) ); KEY( "Hitroom", skill->hit_room, fread_string_nohash( fp ) ); KEY( "Hitvict", skill->hit_vict, fread_string_nohash( fp ) ); break; case 'I': KEY( "Immchar", skill->imm_char, fread_string_nohash( fp ) ); KEY( "Immroom", skill->imm_room, fread_string_nohash( fp ) ); KEY( "Immvict", skill->imm_vict, fread_string_nohash( fp ) ); break; case 'M': KEY( "Mana", skill->min_mana, fread_number( fp ) ); KEY( "Minlevel", skill->min_level, fread_number( fp ) ); KEY( "Minpos", skill->minimum_position, fread_number( fp ) ); KEY( "Misschar", skill->miss_char, fread_string_nohash( fp ) ); KEY( "Missroom", skill->miss_room, fread_string_nohash( fp ) ); KEY( "Missvict", skill->miss_vict, fread_string_nohash( fp ) ); break; case 'N': KEY( "Name", skill->name, fread_string_nohash( fp ) ); break; case 'P': KEY( "Participants", skill->participants, fread_number( fp ) ); break; case 'R': KEY( "Rounds", skill->beats, fread_number( fp ) ); break; case 'S': KEY( "Slot", skill->slot, fread_number( fp ) ); KEY( "Saves", skill->saves, fread_number( fp ) ); break; case 'T': KEY( "Target", skill->target, fread_number( fp ) ); KEY( "Teachers", skill->teachers, fread_string_nohash( fp ) ); KEY( "Type", skill->type, get_skill( fread_word( fp ) ) ); break; case 'V': KEY( "Value", skill->value, fread_number( fp ) ); break; case 'W': KEY( "Wearoff", skill->msg_off, fread_string_nohash( fp ) ); break; } if( !fMatch ) { sprintf( buf, "Fread_skill: no match: %s", word ); bug( buf, 0 ); } } } void load_skill_table( ) { FILE *fp; if( ( fp = fopen( SKILL_FILE, "r" ) ) != NULL ) { top_sn = 0; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "Load_skill_table: # not found.", 0 ); break; } word = fread_word( fp ); if( !str_cmp( word, "SKILL" ) ) { if( top_sn >= MAX_SKILL ) { bug( "load_skill_table: more skills than MAX_SKILL %d", MAX_SKILL ); fclose( fp ); return; } skill_table[top_sn++] = fread_skill( fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "Load_skill_table: bad section.", 0 ); continue; } } fclose( fp ); } else { bug( "Cannot open skills.dat", 0 ); exit( 0 ); } } void load_herb_table( ) { FILE *fp; if( ( fp = fopen( HERB_FILE, "r" ) ) != NULL ) { top_herb = 0; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "Load_herb_table: # not found.", 0 ); break; } word = fread_word( fp ); if( !str_cmp( word, "HERB" ) ) { if( top_herb >= MAX_HERB ) { bug( "load_herb_table: more herbs than MAX_HERB %d", MAX_HERB ); fclose( fp ); return; } herb_table[top_herb++] = fread_skill( fp ); if( herb_table[top_herb - 1]->slot == 0 ) herb_table[top_herb - 1]->slot = top_herb - 1; continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "Load_herb_table: bad section.", 0 ); continue; } } fclose( fp ); } else { bug( "Cannot open herbs.dat", 0 ); exit( 0 ); } } void fread_social( FILE * fp ) { char buf[MAX_STRING_LENGTH]; char *word; bool fMatch; SOCIALTYPE *social; CREATE( social, SOCIALTYPE, 1 ); for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': KEY( "CharNoArg", social->char_no_arg, fread_string_nohash( fp ) ); KEY( "CharFound", social->char_found, fread_string_nohash( fp ) ); KEY( "CharAuto", social->char_auto, fread_string_nohash( fp ) ); break; case 'E': if( !str_cmp( word, "End" ) ) { if( !social->name ) { bug( "Fread_social: Name not found", 0 ); free_social( social ); return; } if( !social->char_no_arg ) { bug( "Fread_social: CharNoArg not found", 0 ); free_social( social ); return; } add_social( social ); return; } break; case 'N': KEY( "Name", social->name, fread_string_nohash( fp ) ); break; case 'O': KEY( "OthersNoArg", social->others_no_arg, fread_string_nohash( fp ) ); KEY( "OthersFound", social->others_found, fread_string_nohash( fp ) ); KEY( "OthersAuto", social->others_auto, fread_string_nohash( fp ) ); break; case 'V': KEY( "VictFound", social->vict_found, fread_string_nohash( fp ) ); break; } if( !fMatch ) { sprintf( buf, "Fread_social: no match: %s", word ); bug( buf, 0 ); } } } void load_socials( ) { FILE *fp; if( ( fp = fopen( SOCIAL_FILE, "r" ) ) != NULL ) { top_sn = 0; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "Load_socials: # not found.", 0 ); break; } word = fread_word( fp ); if( !str_cmp( word, "SOCIAL" ) ) { fread_social( fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "Load_socials: bad section.", 0 ); continue; } } fclose( fp ); } else { bug( "Cannot open socials.dat", 0 ); exit( 0 ); } } void fread_command( FILE * fp ) { char buf[MAX_STRING_LENGTH]; char *word; bool fMatch; CMDTYPE *command; CREATE( command, CMDTYPE, 1 ); for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER( word[0] ) ) { case '*': fMatch = TRUE; fread_to_eol( fp ); break; case 'C': KEY( "Code", command->fun_name, str_dup( fread_word( fp ) ) ); break; case 'E': if ( !str_cmp( word, "End" ) ) { if( !command->name ) { bug( "%s", "Fread_command: Name not found" ); free_command( command ); return; } if( !command->fun_name ) { bug( "fread_command: No function name supplied for %s", command->name ); free_command( command ); return; } /* * Mods by Trax * Fread in code into char* and try linkage here then * deal in the "usual" way I suppose.. */ command->do_fun = skill_function( command->fun_name ); if( command->do_fun == skill_notfound ) { bug( "Fread_command: Function %s not found for %s", command->fun_name, command->name ); free_command( command ); return; } add_command( command ); return; } break; case 'L': KEY( "Level", command->level, fread_number( fp ) ); KEY( "Log", command->log, fread_number( fp ) ); break; case 'N': KEY( "Name", command->name, fread_string_nohash( fp ) ); break; case 'P': KEY( "Position", command->position, fread_number( fp ) ); break; } if( !fMatch ) { sprintf( buf, "Fread_command: no match: %s", word ); bug( buf, 0 ); } } } void load_commands( ) { FILE *fp; if( ( fp = fopen( COMMAND_FILE, "r" ) ) != NULL ) { top_sn = 0; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "Load_commands: # not found.", 0 ); break; } word = fread_word( fp ); if( !str_cmp( word, "COMMAND" ) ) { fread_command( fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "Load_commands: bad section.", 0 ); continue; } } fclose( fp ); } else { bug( "Cannot open commands.dat", 0 ); exit( 0 ); } }