/**************************************************************************
* 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"
/*
* 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, "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 ", 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, "%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_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, "M %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, "M %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, "M %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, "M %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;
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;
}
fprintf( fp, "G 0 %d 0 %s is given to %s\n",
pReset->vnum,
capitalize(get_obj_index( pReset->vnum )->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 );
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_IMMORTAL(ch) )
{
send_to_char("Huh?\n\r", 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 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 );
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 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 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_helps();
save_mudprogs();
save_clans();
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_helps();
save_mudprogs();
save_clans();
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_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_list; 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_list; 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_list; 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_list; 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;
}