/* * RAM $Id: olc_save.c 81 2009-01-14 06:16:31Z ghasatta $ */ /************************************************************************** * 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. */ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "tables.h" #include "db.h" #include "interp.h" #include "special.h" #include "strings.h" #include "act.h" #include "olc.h" #define DIF(a,b) (~((~a)|(b))) /* * 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 /***************************************************************************** Name: fix_string Purpose: Returns a string without \r and ~. ****************************************************************************/ char *fix_string( const char *str ) { static char strfix[MAX_STRING_LENGTH * 2] = "\0\0\0\0\0\0\0"; int i = 0; int o = 0; if ( str == NULL ) return '\0'; for ( o = i = 0; str[i + o] != '\0'; 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 = NULL; AREA_DATA *pArea = NULL; HELP_AREA *ha = NULL; if ( ( fp = fopen( "area.lst", "w" ) ) == NULL ) { log_error( "Save_area_list: fopen" ); perror( "area.lst" ); } else { /* * Add any help files that need to be loaded at * startup to this section. */ fprintf( fp, "social.are\n" ); /* ROM OLC */ for ( ha = had_list; ha; ha = ha->next ) if ( ha->area == NULL ) fprintf( fp, "%s\n", ha->filename ); for ( pArea = area_first; pArea; pArea = pArea->next ) { fprintf( fp, "%s\n", pArea->file_name ); } 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( int flags, char buf[] ) { char offset = '\0'; char *cp = NULL; buf[0] = '\0'; if ( flags == 0 ) { strcpy( buf, "0" ); return buf; } /* * 32 -- number of bits in an int */ for ( offset = 0, cp = buf; offset < 32; offset++ ) if ( flags & ( ( int ) 1 << offset ) ) { if ( offset <= 'Z' - 'A' ) *( cp++ ) = 'A' + offset; else *( cp++ ) = 'a' + offset - ( 'Z' - 'A' + 1 ); } *cp = '\0'; return buf; } void save_mobprogs( FILE * fp, AREA_DATA *pArea ) { MPROG_CODE *pMprog = NULL; int i = 0; fprintf( fp, "#MOBPROGS\n" ); for ( i = pArea->min_vnum; i <= pArea->max_vnum; i++ ) { if ( ( pMprog = get_mprog_index( i ) ) != NULL ) { fprintf( fp, "#%d\n", i ); fprintf( fp, "%s~\n", fix_string( pMprog->code ) ); } } fprintf( fp, "#0\n\n" ); return; } /***************************************************************************** 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 ) { int race = pMobIndex->race; MPROG_LIST *pMprog = NULL; char buf[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; int temp = 0; 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 %d\n", pMobIndex->alignment, pMobIndex->group ); fprintf( fp, "%d ", pMobIndex->level ); fprintf( fp, "%d ", pMobIndex->hitroll ); 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, "%s\n", attack_table[pMobIndex->dam_type].name ); 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, "%s %s %s %d\n", position_table[pMobIndex->start_pos].short_name, position_table[pMobIndex->default_pos].short_name, sex_table[pMobIndex->sex].name, pMobIndex->wealth ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->form, buf ) ); fprintf( fp, "%s ", fwrite_flag( pMobIndex->parts, buf ) ); fprintf( fp, "%s ", size_table[pMobIndex->size].name ); fprintf( fp, "%s\n", IS_NULLSTR( pMobIndex->material ) ? pMobIndex->material : "unknown" ); if ( ( temp = DIF( race_table[race].act, pMobIndex->act ) ) ) fprintf( fp, "F act %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].aff, pMobIndex->affected_by ) ) ) fprintf( fp, "F aff %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].off, pMobIndex->off_flags ) ) ) fprintf( fp, "F off %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].imm, pMobIndex->imm_flags ) ) ) fprintf( fp, "F imm %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].res, pMobIndex->res_flags ) ) ) fprintf( fp, "F res %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].vuln, pMobIndex->vuln_flags ) ) ) fprintf( fp, "F vul %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].form, pMobIndex->form ) ) ) fprintf( fp, "F for %s\n", fwrite_flag( temp, buf ) ); if ( ( temp = DIF( race_table[race].parts, pMobIndex->parts ) ) ) fprintf( fp, "F par %s\n", fwrite_flag( temp, buf ) ); for ( pMprog = pMobIndex->mprogs; pMprog; pMprog = pMprog->next ) { fprintf( fp, "M %s %d %s~\n", mprog_type_to_name( pMprog->trig_type ), pMprog->vnum, pMprog->trig_phrase ); } 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 = 0; MOB_INDEX_DATA *pMob = NULL; fprintf( fp, "#MOBILES\n" ); for ( i = pArea->min_vnum; i <= pArea->max_vnum; 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 letter = '\0'; AFFECT_DATA *pAf = NULL; EXTRA_DESCR_DATA *pEd = NULL; char buf[MAX_STRING_LENGTH] = "\0\0\0\0\0\0\0"; 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", pObjIndex->material ); fprintf( fp, "%s ", item_name( 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_DRINK_CON: case ITEM_FOUNTAIN: fprintf( fp, "%d %d '%s' %d %d\n", pObjIndex->value[0], pObjIndex->value[1], liq_table[pObjIndex->value[2]].liq_name, pObjIndex->value[3], pObjIndex->value[4] ); break; case ITEM_CONTAINER: fprintf( fp, "%d %s %d %d %d\n", pObjIndex->value[0], fwrite_flag( pObjIndex->value[1], buf ), pObjIndex->value[2], pObjIndex->value[3], pObjIndex->value[4] ); break; case ITEM_WEAPON: fprintf( fp, "%s %d %d %s %s\n", weapon_name( pObjIndex->value[0] ), pObjIndex->value[1], pObjIndex->value[2], attack_table[pObjIndex->value[3]].name, fwrite_flag( pObjIndex->value[4], buf ) ); break; case ITEM_PILL: case ITEM_POTION: case ITEM_SCROLL: fprintf( fp, "%d '%s' '%s' '%s' '%s'\n", pObjIndex->value[0] > 0 ? pObjIndex->value[0] : 0, pObjIndex->value[1] != -1 ? skill_table[pObjIndex->value[1]].name : "", pObjIndex->value[2] != -1 ? skill_table[pObjIndex->value[2]].name : "", pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].name : "", pObjIndex->value[4] != -1 ? skill_table[pObjIndex->value[4]].name : "" ); break; case ITEM_STAFF: case ITEM_WAND: fprintf( fp, "%d %d %d '%s' %d\n", pObjIndex->value[0], pObjIndex->value[1], pObjIndex->value[2], pObjIndex->value[3] != -1 ? skill_table[pObjIndex->value[3]].name : "", pObjIndex->value[4] ); 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 ); for ( pAf = pObjIndex->affected; pAf; pAf = pAf->next ) { if ( pAf->where == TO_OBJECT || pAf->bitvector == 0 ) fprintf( fp, "A\n%d %d\n", pAf->location, pAf->modifier ); else { fprintf( fp, "F\n" ); switch ( pAf->where ) { case TO_AFFECTS: fprintf( fp, "A " ); break; case TO_IMMUNE: fprintf( fp, "I " ); break; case TO_RESIST: fprintf( fp, "R " ); break; case TO_VULN: fprintf( fp, "V " ); break; default: log_error( "olc_save: Invalid Affect->where" ); break; } fprintf( fp, "%d %d %s\n", pAf->location, pAf->modifier, fwrite_flag( pAf->bitvector, buf ) ); } } 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 = 0; OBJ_INDEX_DATA *pObj = NULL; fprintf( fp, "#OBJECTS\n" ); for ( i = pArea->min_vnum; i <= pArea->max_vnum; 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 = NULL; EXTRA_DESCR_DATA *pEd = NULL; EXIT_DATA *pExit = NULL; int iHash = 0; int door = 0; 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; /* * HACK : TO PREVENT EX_LOCKED etc without EX_ISDOOR to stop * booting the mud */ if ( IS_SET( pExit->rs_flags, EX_CLOSED ) || IS_SET( pExit->rs_flags, EX_LOCKED ) || IS_SET( pExit->rs_flags, EX_PICKPROOF ) || IS_SET( pExit->rs_flags, EX_NOPASS ) || IS_SET( pExit->rs_flags, EX_EASY ) || IS_SET( pExit->rs_flags, EX_HARD ) || IS_SET( pExit->rs_flags, EX_INFURIATING ) || IS_SET( pExit->rs_flags, EX_NOCLOSE ) || IS_SET( pExit->rs_flags, EX_NOLOCK ) ) SET_BIT( pExit->rs_flags, EX_ISDOOR ); else REMOVE_BIT( pExit->rs_flags, EX_ISDOOR ); /* * THIS SUCKS but it's backwards compatible */ /* * NOTE THAT EX_NOCLOSE NOLOCK etc aren't being saved */ if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( !IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) locks = 1; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( !IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) locks = 2; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( !IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) locks = 3; if ( IS_SET( pExit->rs_flags, EX_ISDOOR ) && ( IS_SET( pExit->rs_flags, EX_PICKPROOF ) ) && ( IS_SET( pExit->rs_flags, EX_NOPASS ) ) ) locks = 4; 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 ); } } if ( pRoomIndex->mana_rate != 100 || pRoomIndex->heal_rate != 100 ) fprintf( fp, "M %d H %d\n", pRoomIndex->mana_rate, pRoomIndex->heal_rate ); if ( pRoomIndex->clan > 0 ) fprintf( fp, "C %s~\n", clan_table[pRoomIndex->clan].name ); if ( !IS_NULLSTR( pRoomIndex->owner ) ) fprintf( fp, "O %s~\n", pRoomIndex->owner ); fprintf( fp, "S\n" ); } } } fprintf( fp, "#0\n\n\n\n" ); return; } /***************************************************************************** Name: save_specials Purpose: Save #SPECIALS section of area file. Called by: save_area(olc_save.c). ****************************************************************************/ void save_specials( FILE * fp, AREA_DATA *pArea ) { int iHash = 0; MOB_INDEX_DATA *pMobIndex = NULL; fprintf( fp, "#SPECIALS\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->spec_fun ) { #if defined( VERBOSE ) fprintf( fp, "M %d %s Load to: %s\n", pMobIndex->vnum, spec_name( pMobIndex->spec_fun ), pMobIndex->short_descr ); #else fprintf( fp, "M %d %s\n", pMobIndex->vnum, spec_name( pMobIndex->spec_fun ) ); #endif } } } 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 = 0; ROOM_INDEX_DATA *pRoomIndex = NULL; EXIT_DATA *pExit = NULL; int door = 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 defined( VERBOSE ) fprintf( fp, "D 0 %d %d %d The %s door of %s is %s\n", pRoomIndex->vnum, pExit->orig_door, IS_SET( pExit->rs_flags, EX_LOCKED ) ? 2 : 1, dir_name[pExit->orig_door], pRoomIndex->name, IS_SET( pExit->rs_flags, EX_LOCKED ) ? "closed and locked" : "closed" ); #endif #if !defined( VERBOSE ) fprintf( fp, "D 0 %d %d %d\n", pRoomIndex->vnum, pExit->orig_door, IS_SET( pExit->rs_flags, EX_LOCKED ) ? 2 : 1 ); #endif } } } } 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 = NULL; MOB_INDEX_DATA *pLastMob = NULL; OBJ_INDEX_DATA *pLastObj = NULL; ROOM_INDEX_DATA *pRoom = NULL; int iHash = 0; 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: log_error( "Save_resets: bad command %c.", pReset->command ); break; #if defined( VERBOSE ) case 'M': pLastMob = get_mob_index( pReset->arg1 ); fprintf( fp, "M 0 %d %d %d %d Load %s\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4, pLastMob->short_descr ); break; case 'O': pLastObj = get_obj_index( pReset->arg1 ); pRoom = get_room_index( pReset->arg3 ); fprintf( fp, "O 0 %d 0 %d %s loaded to %s\n", pReset->arg1, pReset->arg3, capitalize( pLastObj->short_descr ), pRoom->name ); break; case 'P': pLastObj = get_obj_index( pReset->arg1 ); fprintf( fp, "P 0 %d %d %d %d %s put inside %s\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4, capitalize( get_obj_index( pReset->arg1 )-> short_descr ), pLastObj->short_descr ); break; case 'G': fprintf( fp, "G 0 %d 0 %s is given to %s\n", pReset->arg1, capitalize( get_obj_index( pReset->arg1 )-> short_descr ), pLastMob ? pLastMob->short_descr : "!NO_MOB!" ); if ( !pLastMob ) { log_error( "Save_resets: !NO_MOB! in [%s]", pArea->file_name ); } break; case 'E': fprintf( fp, "E 0 %d 0 %d %s is loaded %s of %s\n", pReset->arg1, pReset->arg3, capitalize( get_obj_index( pReset->arg1 )-> short_descr ), flag_string( wear_loc_strings, pReset->arg3 ), pLastMob ? pLastMob->short_descr : "!NO_MOB!" ); if ( !pLastMob ) { log_error( "Save_resets: !NO_MOB! in [%s]", pArea->file_name ); } break; case 'D': break; case 'R': pRoom = get_room_index( pReset->arg1 ); fprintf( fp, "R 0 %d %d Randomize %s\n", pReset->arg1, pReset->arg2, pRoom->name ); break; #else case 'M': pLastMob = get_mob_index( pReset->arg1 ); fprintf( fp, "M 0 %d %d %d %d\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4 ); break; case 'O': pLastObj = get_obj_index( pReset->arg1 ); pRoom = get_room_index( pReset->arg3 ); fprintf( fp, "O 0 %d 0 %d\n", pReset->arg1, pReset->arg3 ); break; case 'P': pLastObj = get_obj_index( pReset->arg1 ); fprintf( fp, "P 0 %d %d %d %d\n", pReset->arg1, pReset->arg2, pReset->arg3, pReset->arg4 ); break; case 'G': fprintf( fp, "G 0 %d 0\n", pReset->arg1 ); if ( !pLastMob ) { log_error( "Save_resets: !NO_MOB! in [%s]", pArea->file_name ); } break; case 'E': fprintf( fp, "E 0 %d 0 %d\n", pReset->arg1, pReset->arg3 ); if ( !pLastMob ) { log_error( "Save_resets: !NO_MOB! in [%s]", pArea->file_name ); } break; case 'D': break; case 'R': pRoom = get_room_index( pReset->arg1 ); fprintf( fp, "R 0 %d %d\n", pReset->arg1, pReset->arg2 ); 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 = NULL; MOB_INDEX_DATA *pMobIndex = NULL; int iTrade = 0; int iHash = 0; 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; } void save_helps( FILE * fp, HELP_AREA *ha ) { HELP_DATA *help = ha->first; fprintf( fp, "#HELPS\n" ); for ( ; help; help = help->next_area ) { fprintf( fp, "%d %s~\n", help->level, help->keyword.c_str()); fprintf( fp, "%s~\n\n", fix_string( help->text.c_str() ) ); } fprintf( fp, "-1 $~\n\n" ); ha->changed = false; return; } void save_other_helps( CHAR_DATA *ch ) { HELP_AREA *ha = NULL; FILE *fp = NULL; for ( ha = had_list; ha; ha = ha->next ) if ( ha->changed == true ) { fp = fopen( ha->filename, "w" ); if ( !fp ) { perror( ha->filename ); return; } save_helps( fp, ha ); if ( ch ) ch_printf( ch, "%s\r\n", ha->filename ); fprintf( fp, "#$\n" ); fclose( fp ); } 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 = NULL; if ( !( fp = fopen( pArea->file_name, "w" ) ) ) { log_error( "Open_area: fopen" ); perror( pArea->file_name ); } 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->min_vnum, pArea->max_vnum ); fprintf( fp, "Credits %s~\n", pArea->credits ); fprintf( fp, "Security %d\n", pArea->security ); fprintf( fp, "End\n\n\n\n" ); save_mobiles( fp, pArea ); save_objects( fp, pArea ); save_rooms( fp, pArea ); save_specials( fp, pArea ); save_resets( fp, pArea ); save_shops( fp, pArea ); save_mobprogs( fp, pArea ); if ( pArea->helps && pArea->helps->first ) save_helps( fp, pArea->helps ); fprintf( fp, "#$\n" ); fclose( fp ); return; } /***************************************************************************** Name: do_asave Purpose: Entry point for saving area data. Called by: interpreter(interp.c) ****************************************************************************/ void do_asave( CHAR_DATA *ch, const char *argument ) { char arg1[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0"; char local_argument[MAX_INPUT_LENGTH] = "\0\0\0\0\0\0\0"; AREA_DATA *pArea = NULL; int value = 0; int sec = 0; if ( !ch ) /* Do an autosave */ sec = 9; else if ( !IS_NPC( ch ) ) sec = ch->pcdata->security; else sec = 0; #if 0 { save_area_list( ); for ( pArea = area_first; pArea; pArea = pArea->next ) { save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); } return; } #endif strcpy( local_argument, argument ); smash_tilde( local_argument ); strcpy( arg1, local_argument ); if ( arg1[0] == '\0' ) { if ( ch ) { ch_printf( ch, "Syntax:\r\n" ); ch_printf( ch, " asave <vnum> - saves a particular area\r\n" ); ch_printf( ch, " asave list - saves the area.lst file\r\n" ); ch_printf( ch, " asave area - saves the area being edited\r\n" ); ch_printf( ch, " asave changed - saves all changed zones\r\n" ); ch_printf( ch, " asave world - saves the world! (db dump)\r\n" ); ch_printf( ch, "\r\n" ); } return; } /* * Snarf the value (which need not be numeric). */ value = atoi( arg1 ); if ( !( pArea = get_area_data( value ) ) && is_number( arg1 ) ) { if ( ch ) ch_printf( ch, "That area does not exist.\r\n" ); return; } /* * Save area of given vnum. */ if ( is_number( arg1 ) ) { if ( ch && !IS_BUILDER( ch, pArea ) ) { ch_printf( ch, "You are not a builder for this area.\r\n" ); return; } save_area_list( ); save_area( pArea ); return; } /* * Save the world, only authorized areas. */ if ( !str_cmp( "world", arg1 ) ) { save_area_list( ); for ( pArea = area_first; pArea; pArea = pArea->next ) { /* * Builder must be assigned this area. */ if ( ch && !IS_BUILDER( ch, pArea ) ) continue; save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); } if ( ch ) ch_printf( ch, "You saved the world.\r\n" ); save_other_helps( NULL ); return; } /* * Save changed areas, only authorized areas. */ if ( !str_cmp( "changed", arg1 ) ) { char buf[MAX_INPUT_LENGTH]; save_area_list( ); if ( ch ) ch_printf( ch, "Saved zones:\r\n" ); else log_string( "Saved zones:" ); sprintf( buf, "None.\r\n" ); for ( pArea = area_first; pArea; pArea = pArea->next ) { /* * Builder must be assigned this area. */ if ( ch && !IS_BUILDER( ch, pArea ) ) continue; /* * Save changed areas. */ if ( IS_SET( pArea->area_flags, AREA_CHANGED ) ) { save_area( pArea ); sprintf( buf, "%24s - '%s'", pArea->name, pArea->file_name ); if ( ch ) { send_to_char( buf, ch ); send_to_char( "\r\n", ch ); } else log_string( buf ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); } } save_other_helps( ch ); if ( !str_cmp( buf, "None.\r\n" ) ) { if ( ch ) ch_printf( ch, "%s", buf ); else log_string( "None." ); } return; } /* * Save the area.lst file. */ if ( !str_cmp( arg1, "list" ) ) { save_area_list( ); return; } /* * Save area being edited, if authorized. */ if ( !str_cmp( arg1, "area" ) ) { if ( !ch || !ch->desc ) return; /* * Is character currently editing. */ if ( ch->desc->editor == ED_NONE ) { ch_printf( ch, "You are not editing an area, " "therefore an area vnum is required.\r\n" ); 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; case ED_HELP: ch_printf( ch, "Recording area : " ); save_other_helps( ch ); return; default: pArea = ch->in_room->area; break; } if ( !IS_BUILDER( ch, pArea ) ) { ch_printf( ch, "You are not a builder for this area.\r\n" ); return; } save_area_list( ); save_area( pArea ); REMOVE_BIT( pArea->area_flags, AREA_CHANGED ); ch_printf( ch, "Area saved.\r\n" ); return; } /* * Show correct syntax. */ if ( ch ) do_asave( ch, "" ); return; }