/************************************************************************** * File: olc_save.c * * * * Much time and thought has gone into this software and you are * * benefitting. We hope that you share your changes too. What goes * * around, comes around. * * * * This code was freely distributed with the The Isles 1.1 source code, * * and has been used here for OLC - OLC would not be what it is without * * all the previous coders who released their source code. * * * ***************************************************************************/ /* OLC_SAVE.C * This takes care of saving all the .are information. * Notes: * -If a good syntax checker is used for setting vnum ranges of areas * then it would become possible to just cycle through vnums instead * of using the iHash stuff and checking that the room or reset or * mob etc is part of that area. */ /************************************************************************** * Mudprogram's (Mobprogram, Objprogram and Roomprogram) originaly * * by the SMAUG development team * * Ported to EmberMUD by Thanatos and Tyrluk of ToED * * (Temple of Eternal Death) * * Tyrluk - morn@telmaron.com or dajy@mindspring.com * * Thanatos - morn@telmaron.com or jonathan_w._rose@ffic.com * * Heavily modified by Zane (zane@supernova.org) * **************************************************************************/ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "olc.h" extern void save_factionaffs( FILE * fp, AREA_DATA * pArea ); /* * Verbose writes reset data in plain english into the comments * section of the resets. It makes areas considerably larger but * may aid in debugging. */ #define VERBOSE /* * Local functions. */ char *mprog_type_to_name args( ( int type ) ); /***************************************************************************** Name: fix_string Purpose: Returns a string without \r and ~. ****************************************************************************/ char *fix_string( const char *str ) { static char strfix[4 * MAX_STRING_LENGTH]; int i = 0; int o = 0; if ( !str || !str[0] ) return '\0'; for ( ; i + o != 4 * MAX_STRING_LENGTH && str[i + o]; i++ ) { if ( str[i + o] == '\r' || str[i + o] == '~' ) o++; strfix[i] = str[i + o]; } strfix[i] = '\0'; return strfix; } /***************************************************************************** Name: save_area_list Purpose: Saves the listing of files to be loaded at startup. Called by: do_asave(olc_save.c). ****************************************************************************/ void save_area_list( ) { FILE *fp; AREA_DATA *pArea; char buf[MAX_STRING_LENGTH]; sprintf( buf, "%s/%s", sysconfig.area_dir, sysconfig.area_list ); if ( !( fp = fopen( buf, "w" ) ) ) { bug( "Save_area_list: fopen" ); perror( "area.lst" ); return; } /* * Add any help files that need to be loaded at * startup to this section. */ fprintf( fp, "%s\n", sysconfig.help_file ); fprintf( fp, "%s\n", sysconfig.todo_file ); /* fprintf( fp, "social.are\n" );*//* ROM OLC */ fprintf( fp, "%s\n", sysconfig.clans_file ); for ( pArea = area_first; pArea; pArea = pArea->next ) { fprintf( fp, "%s\n", pArea->filename ); } fprintf( fp, "$\n" ); fclose( fp ); return; } /* * ROM OLC * Used in save_mobile and save_object below. Writes * flags on the form fread_flag reads. * * buf[] must hold at least 32+1 characters. * * -- Hugin */ char *fwrite_flag( long flags, char buf[] ) { char offset; char *cp; buf[0] = '\0'; if ( flags == 0 ) { strcpy( buf, "0" ); return buf; } /* 32 -- number of bits in a long */ for ( offset = 0, cp = buf; offset < 32; offset++ ) if ( flags & ( ( long ) 1 << offset ) ) { if ( offset <= 'Z' - 'A' ) *( cp++ ) = 'A' + offset; else *( cp++ ) = 'a' + offset - ( 'Z' - 'A' + 1 ); } *cp = '\0'; return buf; } /***************************************************************************** Name: save_mobile Purpose: Save one mobile to file, new format -- Hugin Called by: save_mobiles (below). ****************************************************************************/ void save_mobile( FILE * fp, MOB_INDEX_DATA * pMobIndex ) { char buf[MAX_STRING_LENGTH]; char letter; sh_int race = pMobIndex->race; fprintf( fp, "#%d\n", pMobIndex->vnum ); fprintf( fp, "%s~\n", pMobIndex->player_name ); fprintf( fp, "%s~\n", pMobIndex->short_descr ); fprintf( fp, "%s~\n", fix_string( pMobIndex->long_descr ) ); fprintf( fp, "%s~\n", fix_string( pMobIndex->description ) ); fprintf( fp, "%s~\n", race_table[race].name ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->act, buf ) ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->affected_by, buf ) ); fprintf( fp, "%d S\n", pMobIndex->alignment ); fprintf( fp, "%d ", pMobIndex->level ); fprintf( fp, "%d \n", pMobIndex->hitroll ); fprintf( fp, "%d ", pMobIndex->breath_percent ); fprintf( fp, "%d ", pMobIndex->rnd_obj_percent ); fprintf( fp, "%d ", pMobIndex->rnd_obj_num ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->rnd_obj_types, buf ) ); fprintf( fp, "%dd%d+%d ", pMobIndex->hit[DICE_NUMBER], pMobIndex->hit[DICE_TYPE], pMobIndex->hit[DICE_BONUS] ); fprintf( fp, "%dd%d+%d ", pMobIndex->mana[DICE_NUMBER], pMobIndex->mana[DICE_TYPE], pMobIndex->mana[DICE_BONUS] ); fprintf( fp, "%dd%d+%d ", pMobIndex->damage[DICE_NUMBER], pMobIndex->damage[DICE_TYPE], pMobIndex->damage[DICE_BONUS] ); fprintf( fp, "%d\n", pMobIndex->dam_type ); fprintf( fp, "%d %d %d %d\n", pMobIndex->ac[AC_PIERCE] / 10, pMobIndex->ac[AC_BASH] / 10, pMobIndex->ac[AC_SLASH] / 10, pMobIndex->ac[AC_EXOTIC] / 10 ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->off_flags, buf ) ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->imm_flags, buf ) ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->res_flags, buf ) ); fprintf( fp, "%s\n", fwrite_flag( pMobIndex->vuln_flags, buf ) ); fprintf( fp, "%d %d %d %ld\n", pMobIndex->start_pos, pMobIndex->default_pos, pMobIndex->sex, pMobIndex->gold ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->form, buf ) ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->parts, buf ) ); switch ( pMobIndex->size ) { default: letter = 'M'; break; case SIZE_TINY: letter = 'T'; break; case SIZE_SMALL: letter = 'S'; break; case SIZE_MEDIUM: letter = 'M'; break; case SIZE_LARGE: letter = 'L'; break; case SIZE_HUGE: letter = 'H'; break; case SIZE_GIANT: letter = 'G'; break; } fprintf( fp, "%c ", letter ); fprintf( fp, "%d\n", pMobIndex->material ); return; } /***************************************************************************** Name: save_mobiles Purpose: Save #MOBILES secion of an area file. Called by: save_area(olc_save.c). Notes: Changed for ROM OLC. ****************************************************************************/ void save_mobiles( FILE * fp, AREA_DATA * pArea ) { int i; MOB_INDEX_DATA *pMob; fprintf( fp, "#MOBILES\n" ); for ( i = pArea->lvnum; i <= pArea->uvnum; i++ ) { if ( ( pMob = get_mob_index( i ) ) ) save_mobile( fp, pMob ); } fprintf( fp, "#0\n\n\n\n" ); return; } /***************************************************************************** Name: save_object Purpose: Save one object to file. new ROM format saving -- Hugin Called by: save_objects (below). ****************************************************************************/ void save_object( FILE * fp, OBJ_INDEX_DATA * pObjIndex ) { char buf[MAX_STRING_LENGTH]; char letter; AFFECT_DATA *pAf; EXTRA_DESCR_DATA *pEd; fprintf( fp, "#%d\n", pObjIndex->vnum ); fprintf( fp, "%s~\n", pObjIndex->name ); fprintf( fp, "%s~\n", pObjIndex->short_descr ); fprintf( fp, "%s~\n", fix_string( pObjIndex->description ) ); fprintf( fp, "%s~\n", material_name( pObjIndex->material ) ); fprintf( fp, "%d ", pObjIndex->item_type ); fprintf( fp, "%s ", fwrite_flag( pObjIndex->extra_flags, buf ) ); fprintf( fp, "%s\n", fwrite_flag( pObjIndex->wear_flags, buf ) ); /* * Using fwrite_flag to write most values gives a strange * looking area file, consider making a case for each * item type later. */ switch ( pObjIndex->item_type ) { default: fprintf( fp, "%s ", fwrite_flag( pObjIndex->value[0], buf ) ); fprintf( fp, "%s ", fwrite_flag( pObjIndex->value[1], buf ) ); fprintf( fp, "%s ", fwrite_flag( pObjIndex->value[2], buf ) ); fprintf( fp, "%s ", fwrite_flag( pObjIndex->value[3], buf ) ); fprintf( fp, "%s\n", fwrite_flag( pObjIndex->value[4], buf ) ); break; case ITEM_LIGHT: fprintf( fp, "0 0 %d 0 0\n", pObjIndex->value[2] < 1 ? 999 /* infinite */ : pObjIndex->value[2] ); break; case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL: fprintf( fp, "%d %d %d %d %d\n", pObjIndex->value[0] > 0 ? /* no negative numbers */ pObjIndex->value[0] : 0, pObjIndex->value[1] != -1 ? skill_table[pObjIndex->value[1]].slot : 0, pObjIndex->value[2] != -1 ? skill_table[pObjIndex->value[2]].slot : 0, pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].slot : 0, 0 /* unused */ ); break; case ITEM_FURNITURE: fprintf( fp, "%d %d %s %d %d\n", pObjIndex->value[0], pObjIndex->value[1], fwrite_flag( pObjIndex->value[2], buf ), pObjIndex->value[3], pObjIndex->value[4] ); break; case ITEM_STAFF: case ITEM_WAND: fprintf( fp, "%s ", fwrite_flag( pObjIndex->value[0], buf ) ); fprintf( fp, "%s ", fwrite_flag( pObjIndex->value[1], buf ) ); fprintf( fp, "%s %d 0\n", fwrite_flag( pObjIndex->value[2], buf ), pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].slot : 0 ); break; } fprintf( fp, "%d ", pObjIndex->level ); fprintf( fp, "%d ", pObjIndex->weight ); fprintf( fp, "%d ", pObjIndex->cost ); if ( pObjIndex->condition > 90 ) letter = 'P'; else if ( pObjIndex->condition > 75 ) letter = 'G'; else if ( pObjIndex->condition > 50 ) letter = 'A'; else if ( pObjIndex->condition > 25 ) letter = 'W'; else if ( pObjIndex->condition > 10 ) letter = 'D'; else if ( pObjIndex->condition > 0 ) letter = 'B'; else letter = 'R'; fprintf( fp, "%c\n", letter ); if ( pObjIndex->clan > 0 ) fprintf( fp, "C %d\n", pObjIndex->clan ); for ( pAf = pObjIndex->affected; pAf; pAf = pAf->next ) { fprintf( fp, "A\n%d %d\n", pAf->location, pAf->modifier ); } for ( pEd = pObjIndex->extra_descr; pEd; pEd = pEd->next ) { fprintf( fp, "E\n%s~\n%s~\n", pEd->keyword, fix_string( pEd->description ) ); } return; } /***************************************************************************** Name: save_objects Purpose: Save #OBJECTS section of an area file. Called by: save_area(olc_save.c). Notes: Changed for ROM OLC. ****************************************************************************/ void save_objects( FILE * fp, AREA_DATA * pArea ) { int i; OBJ_INDEX_DATA *pObj; fprintf( fp, "#OBJECTS\n" ); for ( i = pArea->lvnum; i <= pArea->uvnum; i++ ) { if ( ( pObj = get_obj_index( i ) ) ) save_object( fp, pObj ); } fprintf( fp, "#0\n\n\n\n" ); return; } /***************************************************************************** Name: save_rooms Purpose: Save #ROOMS section of an area file. Called by: save_area(olc_save.c). ****************************************************************************/ void save_rooms( FILE * fp, AREA_DATA * pArea ) { ROOM_INDEX_DATA *pRoomIndex; EXTRA_DESCR_DATA *pEd; EXIT_DATA *pExit; int iHash; int door; fprintf( fp, "#ROOMS\n" ); for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) { for ( pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next ) { if ( pRoomIndex->area == pArea ) { fprintf( fp, "#%d\n", pRoomIndex->vnum ); fprintf( fp, "%s~\n", pRoomIndex->name ); fprintf( fp, "%s~\n", fix_string( pRoomIndex->description ) ); fprintf( fp, "0 " ); fprintf( fp, "%d ", pRoomIndex->room_flags ); fprintf( fp, "%d\n", pRoomIndex->sector_type ); for ( pEd = pRoomIndex->extra_descr; pEd; pEd = pEd->next ) { fprintf( fp, "E\n%s~\n%s~\n", pEd->keyword, fix_string( pEd->description ) ); } for ( door = 0; door < MAX_DIR; door++ ) /* I hate this! */ { if ( ( pExit = pRoomIndex->exit[door] ) && pExit->u1.to_room ) { int locks = 0; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) /* ROM OLC */ && ( !IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( !IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 1; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( !IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( !IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 2; /* Removed for ROM OLC *//*added back by Thexder */ if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 3; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 4; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( !IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 5; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( !IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 6; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( !IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 7; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( IS_SET( pExit->rs_flags, EX_HIDDEN ) ) && ( !IS_SET( pExit->rs_flags, EX_PASSPROOF ) ) ) locks = 8; /* ROM OLC */ fprintf( fp, "D%d\n", pExit->orig_door ); fprintf( fp, "%s~\n", fix_string( pExit->description ) ); fprintf( fp, "%s~\n", pExit->keyword ); fprintf( fp, "%d %d %d\n", locks, pExit->key, pExit->u1.to_room->vnum ); } } fprintf( fp, "S\n" ); } } } fprintf( fp, "#0\n\n\n\n" ); return; } /***************************************************************************** Name: save_mudprogs_area Purpose: Save #PROGS section of area file. -- By Zane Called by: save_area(olc_save.c). ****************************************************************************/ void save_mudprogs_area( FILE * fp, AREA_DATA * pArea ) { MOB_INDEX_DATA *pMobIndex; ROOM_INDEX_DATA *pRoom; OBJ_INDEX_DATA *pObj; MPROG_LIST *pList; MPROG_LIST *pInnerList; MPROG_GROUP_LIST *pGroupList; int vnum; int iFound; fprintf( fp, "#PROGS\n" ); for ( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ ) { /* Save each mob's progs */ if ( ( pMobIndex = get_mob_index( vnum ) ) ) { if ( pMobIndex->area == pArea && pMobIndex->progtypes ) /* prog */ { /* Write the Prog Groups */ for ( pGroupList = pMobIndex->mprog_groups; pGroupList; pGroupList = pGroupList->next ) fprintf( fp, "M %d %d %s Load to: %s\n", pMobIndex->vnum, pGroupList->mprog_group->vnum, pGroupList->mprog_group->name, pMobIndex->short_descr ); /* Write the vnum of all progs not in the groups listed above. Yes I know three nested loops are bad but considering most mobs will only have one or two progs or groups this doesn't concern me. - Zane */ for ( pList = pMobIndex->mudprogs; pList; pList = pList->next ) { iFound = 0; for ( pGroupList = pMobIndex->mprog_groups; pGroupList; pGroupList = pGroupList->next ) for ( pInnerList = pGroupList->mprog_group->mudprogs; pInnerList; pInnerList = pInnerList->next ) if ( pList->mudprog->vnum == pInnerList->mudprog->vnum ) iFound = 1; if ( !iFound ) fprintf( fp, "M %d %d %s Load to: %s\n", pMobIndex->vnum, pList->mudprog->vnum, pList->mudprog->name, pMobIndex->short_descr ); } } } /* Save each room's progs */ if ( ( pRoom = get_room_index( vnum ) ) ) { if ( pRoom->area == pArea && pRoom->progtypes ) /* prog */ { /* Write the Prog Groups */ for ( pGroupList = pRoom->mprog_groups; pGroupList; pGroupList = pGroupList->next ) fprintf( fp, "R %d %d %s Load to: %s\n", pRoom->vnum, pGroupList->mprog_group->vnum, pGroupList->mprog_group->name, pRoom->name ); /* Write the vnum of all progs not in the groups listed above. Yes I know three nested loops are bad but considering most rooms will only have one or two progs or groups this doesn't concern me. - Zane */ for ( pList = pRoom->mudprogs; pList; pList = pList->next ) { iFound = 0; for ( pGroupList = pRoom->mprog_groups; pGroupList; pGroupList = pGroupList->next ) for ( pInnerList = pGroupList->mprog_group->mudprogs; pInnerList; pInnerList = pInnerList->next ) if ( pList->mudprog->vnum == pInnerList->mudprog->vnum ) iFound = 1; if ( !iFound ) fprintf( fp, "R %d %d %s Load to: %s\n", pRoom->vnum, pList->mudprog->vnum, pList->mudprog->name, pRoom->name ); } } } /* Save each object's progs */ if ( ( pObj = get_obj_index( vnum ) ) ) { if ( pObj->area == pArea && pObj->progtypes ) /* prog */ { /* Write the Prog Groups */ for ( pGroupList = pObj->mprog_groups; pGroupList; pGroupList = pGroupList->next ) fprintf( fp, "O %d %d %s Load to: %s\n", pObj->vnum, pGroupList->mprog_group->vnum, pGroupList->mprog_group->name, pObj->short_descr ); /* Write the vnum of all progs not in the groups listed above. Yes I know three nested loops are bad but considering most objects will only have one or two progs or groups this doesn't concern me. - Zane */ for ( pList = pObj->mudprogs; pList; pList = pList->next ) { iFound = 0; for ( pGroupList = pObj->mprog_groups; pGroupList; pGroupList = pGroupList->next ) for ( pInnerList = pGroupList->mprog_group->mudprogs; pInnerList; pInnerList = pInnerList->next ) if ( pList->mudprog->vnum == pInnerList->mudprog->vnum ) iFound = 1; if ( !iFound ) fprintf( fp, "O %d %d %s Load to: %s\n", pObj->vnum, pList->mudprog->vnum, pList->mudprog->name, pObj->short_descr ); } } } } fprintf( fp, "S\n\n\n\n" ); return; } /* * This function is obsolete. It it not needed but has been left here * for historical reasons. It is used currently for the same reason. * * I don't think it's obsolete in ROM -- Hugin. */ void save_door_resets( FILE * fp, AREA_DATA * pArea ) { int iHash; ROOM_INDEX_DATA *pRoomIndex; EXIT_DATA *pExit; int door; int flags = 0; for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) { for ( pRoomIndex = room_index_hash[iHash]; pRoomIndex; pRoomIndex = pRoomIndex->next ) { if ( pRoomIndex->area == pArea ) { for ( door = 0; door < MAX_DIR; door++ ) { if ( ( pExit = pRoomIndex->exit[door] ) && pExit->u1.to_room && ( IS_SET( pExit->rs_flags, EX_CLOSED ) || IS_SET( pExit->rs_flags, EX_LOCKED ) ) ) { if IS_SET ( pExit->rs_flags, EX_CLOSED ) flags = 0; if IS_SET ( pExit->rs_flags, EX_LOCKED ) flags = 1; if IS_SET ( pExit->rs_flags, EX_PICKPROOF ) flags = 2; fprintf( fp, "D 0 %d %d %d\n", pRoomIndex->vnum, pExit->orig_door, flags ); } } } } } return; } /***************************************************************************** Name: save_resets Purpose: Saves the #RESETS section of an area file. Called by: save_area(olc_save.c) ****************************************************************************/ void save_resets( FILE * fp, AREA_DATA * pArea ) { RESET_DATA *pReset; MOB_INDEX_DATA *pLastMob = NULL; OBJ_INDEX_DATA *pLastObj; OBJ_INDEX_DATA *pObj; ROOM_INDEX_DATA *pRoom; int iHash; fprintf( fp, "#RESETS\n" ); save_door_resets( fp, pArea ); for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) { for ( pRoom = room_index_hash[iHash]; pRoom; pRoom = pRoom->next ) { if ( pRoom->area == pArea ) { for ( pReset = pRoom->reset_first; pReset; pReset = pReset->next ) { switch ( pReset->command ) { default: bug( "Save_resets: bad command %c.", pReset->command ); break; #if defined( VERBOSE ) case 'M': if ( pReset->vnum < 0 || pReset->arg3 < 0 ) /* Allow <= -1 for infinate values in arg2 */ { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pLastMob = get_mob_index( pReset->vnum ); fprintf( fp, "M 0 %d %d %d Load %s\n", pReset->vnum, ( pReset->arg2 == 1 ? 0 : pReset->arg2 ), /* 0 is easier for scanning the files manually and still pops 1 - Zane */ pReset->arg3, pLastMob ? pLastMob-> short_descr : "!NO_MOB!" ); if ( !pLastMob ) { bug( "Save_resets: !NO_MOB! in [%s]", pArea->filename ); } break; case 'O': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pLastObj = get_obj_index( pReset->vnum ); pRoom = get_room_index( pReset->arg3 ); fprintf( fp, "O 0 %d 0 %d %s loaded to %s\n", pReset->vnum, pReset->arg3, pLastObj ? capitalize( pLastObj->short_descr ) : "!NO_OBJ!", pRoom ? pRoom->name : "!NO_ROOM!" ); if ( !pLastObj ) { bug( "Save_resets: !NO_OBJ! in [%s]", pArea->filename ); } if ( !pRoom ) { bug( "Save_resets: !NO_ROOM! in [%s]", pArea->filename ); } break; case 'P': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pLastObj = get_obj_index( pReset->vnum ); fprintf( fp, "P 0 %d 0 %d %s put inside %s\n", pReset->vnum, pReset->arg3, capitalize( get_obj_index( pReset->vnum )-> short_descr ), pLastObj ? pLastObj-> short_descr : "!NULL OBJ!" ); if ( !pLastObj ) { bug( "Save_resets: !NO_OBJ! in [%s]", pArea->filename ); } break; case 'G': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pObj = get_obj_index( pReset->vnum ); if ( pObj == NULL ) { bug( "Save_resets: !NO_OBJ! in [%s] - non-existant obj vnum %d given to mob vnum %d", pArea->filename, pReset->vnum, pLastMob->vnum ); } else { fprintf( fp, "G 0 %d 0 %s is given to %s\n", pReset->vnum, capitalize( pObj->short_descr ), pLastMob ? pLastMob-> short_descr : "!NO_MOB!" ); if ( !pLastMob ) { bug( "Save_resets: !NO_MOB! in [%s]", pArea->filename ); } } break; case 'E': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } fprintf( fp, "E 0 %d 0 %d %s is loaded %s of %s\n", pReset->vnum, pReset->arg3, capitalize( get_obj_index( pReset->vnum )-> short_descr ), flag_string( wear_loc_strings, pReset->arg3 ), pLastMob ? pLastMob-> short_descr : "!NO_MOB!" ); if ( !pLastMob ) { bug( "Save_resets: !NO_MOB! in [%s]", pArea->filename ); } break; case 'D': break; case 'R': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < 0 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pRoom = get_room_index( pReset->vnum ); fprintf( fp, "R 0 %d %d Randomize %s\n", pReset->vnum, pReset->arg2, pRoom ? pRoom->name : "!NO_ROOM!" ); if ( !pRoom ) { bug( "Save_resets: !NO_ROOM! in [%s]", pArea->filename ); } break; } #endif #if !defined( VERBOSE ) case 'M': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < 0 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pLastMob = get_mob_index( pReset->vnum ); fprintf( fp, "M 0 %d %d %d\n", pReset->vnum, pReset->arg2, pReset->arg3 ); if ( !pLastMob ) { bug( "Save_resets: !NO_MOB! in [%s]", pArea->filename ); } break; case 'O': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pLastObj = get_obj_index( pReset->vnum ); pRoom = get_room_index( pReset->arg3 ); fprintf( fp, "O 0 %d 0 %d\n", pReset->vnum, pReset->arg3 ); if ( !pLastObj ) { bug( "Save_resets: !NO_Obj! in [%s]", pArea->filename ); } break; case 'P': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pLastObj = get_obj_index( pReset->vnum ); fprintf( fp, "P 0 %d 0 %d\n", pReset->vnum, pReset->arg3 ); if ( !pLastObj ) { bug( "Save_resets: !NO_Obj! in [%s]", pArea->filename ); } break; case 'G': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } fprintf( fp, "G 0 %d 0\n", pReset->vnum ); if ( !pLastMob ) { bug( "Save_resets: !NO_MOB! in [%s]", pArea->filename ); } break; case 'E': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < -1 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } fprintf( fp, "E 0 %d 0 %d\n", pReset->vnum, pReset->arg3 ); if ( !pLastMob ) { bug( "Save_resets: !NO_MOB! in [%s]", pArea->filename ); } break; case 'D': break; case 'R': if ( pReset->vnum < 0 || pReset->arg2 < 0 || pReset->arg3 < 0 ) { bug( "Save_resets: Bad Reset data: vnum(%d) arg2(%d) arg3(%d)", pReset->vnum, pReset->arg2, pReset->arg3 ); bug( "Save_resets: in file %s. Reset not saved", pArea->filename ); break; } pRoom = get_room_index( pReset->vnum ); fprintf( fp, "R 0 %d %d\n", pReset->vnum, pReset->arg2 ); if ( !pRoom ) { bug( "Save_resets: !NO_ROOM! in [%s]", pArea->filename ); } break; } #endif } } /* End if correct area */ } /* End for pRoom */ } /* End for iHash */ fprintf( fp, "S\n\n\n\n" ); return; } /***************************************************************************** Name: save_shops Purpose: Saves the #SHOPS section of an area file. Called by: save_area(olc_save.c) ****************************************************************************/ void save_shops( FILE * fp, AREA_DATA * pArea ) { SHOP_DATA *pShopIndex; MOB_INDEX_DATA *pMobIndex; int iTrade; int iHash; fprintf( fp, "#SHOPS\n" ); for ( iHash = 0; iHash < MAX_KEY_HASH; iHash++ ) { for ( pMobIndex = mob_index_hash[iHash]; pMobIndex; pMobIndex = pMobIndex->next ) { if ( pMobIndex && pMobIndex->area == pArea && pMobIndex->pShop ) { pShopIndex = pMobIndex->pShop; fprintf( fp, "%d ", pShopIndex->keeper ); for ( iTrade = 0; iTrade < MAX_TRADE; iTrade++ ) { if ( pShopIndex->buy_type[iTrade] != 0 ) { fprintf( fp, "%d ", pShopIndex->buy_type[iTrade] ); } else fprintf( fp, "0 " ); } fprintf( fp, "%d %d ", pShopIndex->profit_buy, pShopIndex->profit_sell ); fprintf( fp, "%d %d\n", pShopIndex->open_hour, pShopIndex->close_hour ); } } } fprintf( fp, "0\n\n\n\n" ); return; } /***************************************************************************** Name: save_area Purpose: Save an area, note that this format is new. Called by: do_asave(olc_save.c). ****************************************************************************/ void save_area( AREA_DATA * pArea ) { FILE *fp; char buf[MAX_STRING_LENGTH]; sprintf( buf, "%s/%s", sysconfig.area_dir, pArea->filename ); if ( !( fp = fopen( buf, "w" ) ) ) { bug( "Open_area: fopen" ); perror( pArea->filename ); return; } fprintf( fp, "#AREADATA\n" ); fprintf( fp, "Name %s~\n", pArea->name ); fprintf( fp, "Builders %s~\n", fix_string( pArea->builders ) ); fprintf( fp, "VNUMs %d %d\n", pArea->lvnum, pArea->uvnum ); fprintf( fp, "Security %d\n", pArea->security ); /* fprintf( fp, "Recall %d\n", pArea->recall ); ROM OLC */ fprintf( fp, "End\n\n\n\n" ); save_mobiles( fp, pArea ); save_objects( fp, pArea ); save_rooms( fp, pArea ); save_resets( fp, pArea ); save_mudprogs_area( fp, pArea ); save_shops( fp, pArea ); save_factionaffs( fp, pArea ); fprintf( fp, "#$\n" ); fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; } /***************************************************************************** Name: do_asave Purpose: Entry point for saving area data. Called by: interpreter(interp.c) ****************************************************************************/ void do_asave( CHAR_DATA * ch, char *argument ) { char arg[MAX_INPUT_LENGTH]; AREA_DATA *pArea; FILE *fp; int value; bool changed; if ( IS_NPC( ch ) ) { send_to_char( "Mobs dont need to be rebooting the mud.\n", ch ); return; } fp = NULL; if ( !ch ) /* Do an autosave */ { save_area_list( ); for ( pArea = area_first; pArea; pArea = pArea->next ) { save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); } return; } smash_tilde( argument ); strcpy( arg, argument ); if ( arg[0] == '\0' ) { printf_to_char( ch, "Syntax:\n\r" ); printf_to_char( ch, " asave <vnum> - saves a particular area\n\r" ); printf_to_char( ch, " asave world - saves the world! (db dump)\n\r" ); printf_to_char( ch, " asave changed - saves all changed zones\n\r" ); printf_to_char( ch, " asave list - saves the %s file\n\r", sysconfig.area_list ); printf_to_char( ch, " asave area - saves the area being edited\n\r" ); printf_to_char( ch, " asave help - saves the %s file\n\r", sysconfig.help_file ); printf_to_char( ch, " asave todo - saves the %s file\n\r", sysconfig.todo_file ); printf_to_char( ch, " asave mudprogs - saves the %s file\n\r", sysconfig.mudprogs_file ); printf_to_char( ch, " asave clans - saves the %s file\n\r", sysconfig.clans_file ); printf_to_char( ch, " asave factions - saves the %s file\n\r", sysconfig.factions_file ); printf_to_char( ch, " asave socials - saves the %s file\n\r", sysconfig.socials_file ); return; } /* Snarf the value (which need not be numeric). */ value = atoi( arg ); if ( !( pArea = get_area_data( value ) ) && is_number( arg ) ) { send_to_char( "That area does not exist.\n\r", ch ); return; } /* Save area of given vnum. */ /* ------------------------ */ if ( is_number( arg ) ) { if ( !IS_BUILDER( ch, pArea ) ) { send_to_char( "You are not a builder for this area.\n\r", ch ); return; } save_area_list( ); save_area( pArea ); return; } /* Save the factions file */ /* ---------------------- */ if ( !str_cmp( "factions", arg ) ) { save_factions( ); send_to_char( "Factions file saved!\n\r", ch );; return; } /* Save the socials file */ /* ---------------------- */ if ( !str_cmp( "socials", arg ) ) { save_socials( ); send_to_char( "Socials file saved!\n\r", ch );; return; } /* Save the clans file */ /*------------------- */ if ( !str_prefix( "clans", arg ) ) { save_clans( ); send_to_char( "Clans file saved!\n\r", ch ); return; } /* Save the help file */ /*------------------- */ if ( !str_prefix( "help", arg ) ) { save_helps( ); send_to_char( "Help file saved!\n\r", ch ); return; } /* Save the TODO file */ if ( !str_prefix( "todo", arg ) ) { save_todo( ); send_to_char( "TODO file saved!\n\r", ch ); return; } /* Save the mudprogs file */ /*------------------- */ if ( !str_cmp( "mudprogs", arg ) || !str_cmp( "progs", arg ) || !str_cmp( "mprogs", arg ) ) { save_mudprogs( ); send_to_char( "MudProgs file saved!\n\r", ch ); return; } /* Save the world, only authorized areas. */ /* -------------------------------------- */ if ( ( !str_cmp( "world", arg ) || !str_cmp( "all", arg ) ) && IS_IMMORTAL( ch ) ) { save_area_list( ); save_todo( ); save_mudprogs( ); save_clans( ); save_factions( ); save_socials( ); save_helps( ); for ( pArea = area_first; pArea; pArea = pArea->next ) { /* Builder must be assigned this area. */ if ( !IS_BUILDER( ch, pArea ) ) continue; save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); } send_to_char( "You saved the world.\n\r", ch ); return; } /* Save changed areas, only authorized areas. */ /* ------------------------------------------ */ if ( !str_cmp( "changed", arg ) ) { save_area_list( ); save_todo( ); save_mudprogs( ); save_clans( ); save_factions( ); save_socials( ); save_helps( ); changed = FALSE; send_to_char( "Saved zones:\n\r", ch ); for ( pArea = area_first; pArea; pArea = pArea->next ) { /* Builder must be assigned this area. */ if ( ( ch->Class != 4 ) && ( !IS_BUILDER( ch, pArea ) ) ) continue; /* Save changed areas. */ if ( IS_SET( pArea->area_flags, AREA_CHANGED ) ) { save_area( pArea ); if ( ch->Class != 4 ) printf_to_char( ch, "%24s - '%s'\n\r", pArea->name, pArea->filename ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); changed = TRUE; } } if ( ( !changed ) && ( ch->Class != 4 ) ) send_to_char( "None.\n\r", ch ); return; } /* Save the area.lst file. */ /* ----------------------- */ if ( !str_cmp( arg, "list" ) ) { save_area_list( ); return; } /* Save area being edited, if authorized. */ /* -------------------------------------- */ if ( !str_cmp( arg, "area" ) ) { /* Is character currently editing. */ if ( ch->desc->editor == 0 ) { send_to_char( "You are not editing an area, " "therefore an area vnum is required.\n\r", ch ); return; } /* Find the area to save. */ switch ( ch->desc->editor ) { case ED_AREA: pArea = ( AREA_DATA * ) ch->desc->pEdit; break; case ED_ROOM: pArea = ch->in_room->area; break; case ED_OBJECT: pArea = ( ( OBJ_INDEX_DATA * ) ch->desc->pEdit )->area; break; case ED_MOBILE: pArea = ( ( MOB_INDEX_DATA * ) ch->desc->pEdit )->area; break; default: pArea = ch->in_room->area; break; } if ( !IS_BUILDER( ch, pArea ) ) { send_to_char( "You are not a builder for this area.\n\r", ch ); return; } save_area_list( ); save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); send_to_char( "Area saved.\n\r", ch ); return; } /* Show correct syntax. */ /* -------------------- */ do_asave( ch, "" ); return; } void save_helps( ) { char buf[MAX_STRING_LENGTH]; HELP_DATA *pHelp; FILE *fp; fclose( fpReserve ); sprintf( buf, "%s/%s", sysconfig.area_dir, sysconfig.help_file ); if ( !( fp = fopen( buf, "w" ) ) ) { bug( "help.are: fopen" ); perror( buf ); return; } fprintf( fp, "#HELPS\n\n" ); for ( pHelp = help_first; pHelp != NULL; pHelp = pHelp->next ) { fprintf( fp, "%d", pHelp->level ); fprintf( fp, " %s", pHelp->keyword ); fprintf( fp, "~\n" ); fprintf( fp, "%s~", fix_string( pHelp->text ) ); fprintf( fp, "\n" ); } fprintf( fp, "\n\n0 $~" ); fprintf( fp, "\n\n#$\n" ); fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; } void save_todo( ) { char buf[MAX_STRING_LENGTH]; TODO_DATA *pTodo; FILE *fp; fclose( fpReserve ); sprintf( buf, "%s/%s", sysconfig.area_dir, sysconfig.todo_file ); if ( !( fp = fopen( buf, "w" ) ) ) { bug( "todo.txt: fopen" ); perror( buf ); return; } fprintf( fp, "#TODO\n\n" ); for ( pTodo = todo_first; pTodo != NULL; pTodo = pTodo->next ) { fprintf( fp, "%d", pTodo->level ); fprintf( fp, " %s", pTodo->keyword ); fprintf( fp, "~\n" ); fprintf( fp, "%s~", fix_string( pTodo->text ) ); fprintf( fp, "\n" ); } fprintf( fp, "\n\n0 $~" ); fprintf( fp, "\n\n#$\n" ); fclose( fp ); fpReserve = fopen( NULL_FILE, "r" ); return; } void save_mudprogs( void ) { char buf[MAX_STRING_LENGTH]; FILE *fp; MPROG_DATA *pMudProg; MPROG_GROUP *pMprogGroup; MPROG_LIST *pList; sprintf( buf, "%s/%s", sysconfig.area_dir, sysconfig.mudprogs_file ); if ( !( fp = fopen( buf, "w" ) ) ) { sprintf( buf, "write_mudprogs: unable to open file %s/%s", sysconfig.area_dir, sysconfig.mudprogs_file ); bug( buf ); perror( sysconfig.mudprogs_file ); return; } *buf = '\0'; fprintf( fp, "#MOBPROGS\n" ); for ( pMudProg = mudprog_first; pMudProg; pMudProg = pMudProg->next ) { if ( pMudProg->prog_type != MOB_PROG ) continue; fprintf( fp, "#%d\n%s~\n%s~\n%s %s~\n%s~\n", pMudProg->vnum, pMudProg->name, pMudProg->description, mprog_type_to_name( pMudProg->trigger_type ), pMudProg->arglist, pMudProg->comlist ); } fprintf( fp, "#0\n\n\n\n" ); fprintf( fp, "#OBJPROGS\n" ); for ( pMudProg = mudprog_first; pMudProg; pMudProg = pMudProg->next ) { if ( pMudProg->prog_type != OBJ_PROG ) continue; fprintf( fp, "#%d\n%s~\n%s~\n%s %s~\n%s~\n", pMudProg->vnum, pMudProg->name, pMudProg->description, mprog_type_to_name( pMudProg->trigger_type ), pMudProg->arglist, pMudProg->comlist ); } fprintf( fp, "#0\n\n\n\n" ); fprintf( fp, "#ROOMPROGS\n" ); for ( pMudProg = mudprog_first; pMudProg; pMudProg = pMudProg->next ) { if ( pMudProg->prog_type != ROOM_PROG ) continue; fprintf( fp, "#%d\n%s~\n%s~\n%s %s~\n%s~\n", pMudProg->vnum, pMudProg->name, pMudProg->description, mprog_type_to_name( pMudProg->trigger_type ), pMudProg->arglist, pMudProg->comlist ); } fprintf( fp, "#0\n\n\n\n" ); fprintf( fp, "#PROGGROUPS\n" ); for ( pMprogGroup = mprog_group_first; pMprogGroup; pMprogGroup = pMprogGroup->next ) { fprintf( fp, "#%d\n%s~\n%s~\n", pMprogGroup->vnum, pMprogGroup->name, pMprogGroup->description ); switch ( pMprogGroup->prog_type ) { case MOB_PROG: for ( pList = pMprogGroup->mudprogs; pList; pList = pList->next ) fprintf( fp, "M %d\n", pList->mudprog->vnum ); break; case OBJ_PROG: for ( pList = pMprogGroup->mudprogs; pList; pList = pList->next ) fprintf( fp, "O %d\n", pList->mudprog->vnum ); break; case ROOM_PROG: for ( pList = pMprogGroup->mudprogs; pList; pList = pList->next ) fprintf( fp, "R %d\n", pList->mudprog->vnum ); break; default: bug( "Save_Mudprogs: Invalid mudprog group type." ); perror( sysconfig.mudprogs_file ); return; } fprintf( fp, "~\n" ); } fprintf( fp, "#0\n\n\n\n#$\n" ); fclose( fp ); return; }