/***************************************************************************
* Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. *
* *
* Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* In order to use any part of this Merc Diku Mud, you must comply with *
* both the original Diku license in 'license.doc' as well the Merc *
* license in 'license.txt'. In particular, you may not remove either of *
* these copyright notices. *
* *
* Thanks to abaddon for proof-reading our comm.c and pointing out bugs. *
* Any remaining bugs are, of course, our work, not his. :) *
* *
* 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. *
***************************************************************************/
/***************************************************************************
* ROM 2.4 is copyright 1993-1996 Russ Taylor *
* ROM has been brought to you by the ROM consortium *
* Russ Taylor (rtaylor@pacinfo.com) *
* Gabrielle Taylor (gtaylor@pacinfo.com) *
* Brian Moore (rom@rom.efn.org) *
* By using this code, you have agreed to follow the terms of the *
* ROM license, in the file Tartarus/doc/rom.license *
***************************************************************************/
/***************************************************************************
* Tartarus code is copyright (C) 1997-1998 by Daniel Graham *
* In using this code you agree to comply with the Tartarus license *
* found in the file /Tartarus/doc/tartarus.doc *
***************************************************************************/
/**************************************************************************
* 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 "include.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];
int i;
int o;
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;
AREA_DATA *pArea;
extern HELP_AREA *had_list;
HELP_AREA *ha;
if ( ( fp = fopen( "area.lst", "w" ) ) == NULL )
{
bug( "Save_area_list: fopen", 0 );
perror( "area.lst" );
}
else
{
fprintf (fp, "social.are\n"); /* Add our socials to the list */
/*
* Add any help files that need to be loaded at
* startup to this section.
*/
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( 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 )
{
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->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 )
{
AFFECT_DATA *pAf;
EXTRA_DESCR_DATA *pEd;
char buf[MAX_STRING_LENGTH];
fprintf( fp, "#%ld\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->name );
fprintf( fp, "%s ", item_name(pObjIndex->item_type));
save_bitmask(&pObjIndex->extra_flags, fp);
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 %ld 0 0\n",
pObjIndex->value[2] < 1 ? 999 /* infinite */
: pObjIndex->value[2] );
break;
case ITEM_MONEY:
fprintf( fp, "%ld 0 0 0 0\n",
pObjIndex->value[0] );
break;
case ITEM_DRINK_CON:
fprintf( fp, "%ld %ld '%s' %ld 0\n",
pObjIndex->value[0],
pObjIndex->value[1],
liq_table[pObjIndex->value[2]].liq_name,
/* fwrite_flag( pObjIndex->value[3], buf ) ); */
pObjIndex->value[3]);
break;
case ITEM_FOUNTAIN:
fprintf( fp, "%ld %ld '%s' 0 0\n",
pObjIndex->value[0],
pObjIndex->value[1],
liq_table[pObjIndex->value[2]].liq_name);
break;
case ITEM_CONTAINER:
fprintf( fp, "%ld %s %ld %ld %ld\n",
pObjIndex->value[0],
fwrite_flag( pObjIndex->value[1], buf ),
pObjIndex->value[2],
pObjIndex->value[3],
pObjIndex->value[4]);
break;
case ITEM_FOOD:
fprintf( fp, "%ld %ld 0 %s 0\n",
pObjIndex->value[0],
pObjIndex->value[1],
fwrite_flag( pObjIndex->value[3], buf ) );
break;
case ITEM_PORTAL:
fprintf( fp, "%ld %s %s %ld 0\n",
pObjIndex->value[0],
fwrite_flag( pObjIndex->value[1], buf ),
fwrite_flag( pObjIndex->value[2], buf ),
pObjIndex->value[3]);
break;
case ITEM_FURNITURE:
fprintf( fp, "%ld %ld %s %ld %ld\n",
pObjIndex->value[0],
pObjIndex->value[1],
fwrite_flag( pObjIndex->value[2], buf),
pObjIndex->value[3],
pObjIndex->value[4]);
break;
case ITEM_WEAPON:
fprintf( fp, "%s %ld %ld %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_ARMOR:
fprintf( fp, "%ld %ld %ld %ld %ld\n",
pObjIndex->value[0],
pObjIndex->value[1],
pObjIndex->value[2],
pObjIndex->value[3],
pObjIndex->value[4]);
break;
case ITEM_PILL:
case ITEM_POTION:
case ITEM_SCROLL:
fprintf( fp, "%ld '%s' '%s' '%s' '%s'\n",
pObjIndex->value[0] > 0 ? /* no negative numbers */
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, "%ld ", pObjIndex->value[0] );
fprintf( fp, "%ld ", pObjIndex->value[1] );
fprintf( fp, "%ld '%s' 0\n",
pObjIndex->value[2],
pObjIndex->value[3] != -1 ?
skill_table[pObjIndex->value[3]].name
: 0 );
break;
}
fprintf( fp, "%d ", pObjIndex->level );
fprintf( fp, "%d ", pObjIndex->weight );
fprintf( fp, "%d ", pObjIndex->cost );
fprintf( fp, "%c\n", 'p' );
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:
bug( "olc_save: Invalid Affect->where", 0);
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 ) );
}
if ( pObjIndex->cabal )
{
fprintf( fp, "C\n%d\n", pObjIndex->cabal );
}
if ( pObjIndex->limtotal )
{
fprintf( fp, "L\n%d\n", pObjIndex->limtotal );
}
if ( pObjIndex->restrict_flags )
{
fprintf( fp, "R\n%s\n", fwrite_flag( pObjIndex->restrict_flags, buf ) );
}
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->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;
EXTRA_DESCR_DATA *pEd;
EXIT_DATA *pExit;
int iHash;
int door;
char buf[MAX_STRING_LENGTH];
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, "#%ld\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++ )
{
if ((pExit = pRoomIndex->exit[door]) && (pExit->u1.to_room ))
{
fprintf( fp, "D%ld\n", pExit->orig_door );
fprintf( fp, "%s~\n", fix_string( pExit->description));
fprintf( fp, "%s~\n", pExit->keyword );
fprintf( fp, "%s %ld %ld\n", fwrite_flag(pExit->rs_flags, buf),
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->owner && str_cmp(pRoomIndex->owner,""))
fprintf ( fp, "O %s~\n" , pRoomIndex->owner );
if (pRoomIndex->cabal)
fprintf( fp, "C\n%s~\n", cabal_table[pRoomIndex->cabal].name);
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;
MOB_INDEX_DATA *pMobIndex;
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 %ld %s Load to: %s\n", pMobIndex->vnum,
spec_name( pMobIndex->spec_fun ),
pMobIndex->short_descr );
#else
fprintf( fp, "M %ld %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;
ROOM_INDEX_DATA *pRoomIndex;
EXIT_DATA *pExit;
int door;
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 ) ) )
{
fprintf( fp, "D 0 %ld %ld %d\n",
pRoomIndex->vnum,
pExit->orig_door,
IS_SET( pExit->rs_flags, EX_LOCKED) ? 2 : 1 );
}
}
}
}
}
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;
char buf[MAX_STRING_LENGTH];
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':
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 %ld 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 )
{
sprintf( buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name );
bug( buf, 0 );
}
break;
case 'E':
fprintf( fp, "E 0 %ld 0 %ld %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 )
{
sprintf( buf, "Save_resets: !NO_MOB! in [%s]", pArea->file_name );
bug( buf, 0 );
}
break;
case 'D':
break;
case 'R':
pRoom = get_room_index( pReset->arg1 );
fprintf( fp, "R 0 %ld %ld Randomize %s\n",
pReset->arg1,
pReset->arg2,
pRoom->name );
break;
}
#endif
#if !defined( VERBOSE )
case 'M':
pLastMob = get_mob_index( pReset->arg1 );
fprintf( fp, "M 0 %ld %ld %ld %ld\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 %ld 0 %ld\n",
pReset->arg1,
pReset->arg3 );
break;
case 'P':
pLastObj = get_obj_index( pReset->arg1 );
fprintf( fp, "P 0 %ld %ld %ld %ld\n",
pReset->arg1,
pReset->arg2,
pReset->arg3,
pReset->arg4 );
break;
case 'G':
fprintf( fp, "G 0 %ld 0\n", pReset->arg1 );
if ( !pLastMob )
{
sprintf( buf,
"Save_resets: !NO_MOB! in [%s]", pArea->file_name );
bug( buf, 0 );
}
break;
case 'E':
fprintf( fp, "E 0 %ld 0 %ld\n",
pReset->arg1,
pReset->arg3 );
if ( !pLastMob )
{
sprintf( buf,
"Save_resets: !NO_MOB! in [%s]", pArea->file_name );
bug( buf, 0 );
}
break;
case 'D':
break;
case 'R':
pRoom = get_room_index( pReset->arg1 );
fprintf( fp, "R 0 %ld %ld\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;
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;
}
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);
fprintf (fp, "%s~\n\n", fix_string (help->text));
}
fprintf (fp, "-1 $~\n\n");
ha->changed = FALSE;
return;
}
void save_other_helps (CHAR_DATA * ch)
{
extern HELP_AREA *had_list;
HELP_AREA *ha;
FILE *fp;
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)
printf_to_char (ch, "%s\n\r", ha->filename);
fprintf (fp, "#$\n");
fclose (fp);
}
return;
}
void write_iprog( FILE *fp, OBJ_INDEX_DATA *pObj )
{
if(IS_SET(pObj->progtypes, IPROG_WEAR))
fprintf(fp,"I %ld wear_prog %s\n", pObj->vnum, pObj->iprogs->wear_name);
if(IS_SET(pObj->progtypes, IPROG_REMOVE))
fprintf(fp,"I %ld remove_prog %s\n", pObj->vnum, pObj->iprogs->remove_name);
if(IS_SET(pObj->progtypes, IPROG_DROP))
fprintf(fp,"I %ld drop_prog %s\n", pObj->vnum, pObj->iprogs->drop_name);
if(IS_SET(pObj->progtypes, IPROG_SAC))
fprintf(fp,"I %ld sac_prog %s\n", pObj->vnum, pObj->iprogs->sac_name);
if(IS_SET(pObj->progtypes, IPROG_GIVE))
fprintf(fp,"I %ld give_prog %s\n", pObj->vnum, pObj->iprogs->give_name);
if(IS_SET(pObj->progtypes, IPROG_GREET))
fprintf(fp,"I %ld greet_prog %s\n", pObj->vnum, pObj->iprogs->greet_name);
if(IS_SET(pObj->progtypes, IPROG_FIGHT))
fprintf(fp,"I %ld fight_prog %s\n", pObj->vnum, pObj->iprogs->fight_name);
if(IS_SET(pObj->progtypes, IPROG_DEATH))
fprintf(fp,"I %ld death_prog %s\n", pObj->vnum, pObj->iprogs->death_name);
if(IS_SET(pObj->progtypes, IPROG_SPEECH))
fprintf(fp,"I %ld speech_prog %s\n", pObj->vnum, pObj->iprogs->speech_name);
if(IS_SET(pObj->progtypes, IPROG_ENTRY))
fprintf(fp,"I %ld entry_prog %s\n", pObj->vnum, pObj->iprogs->entry_name);
if(IS_SET(pObj->progtypes, IPROG_GET))
fprintf(fp,"I %ld get_prog %s\n", pObj->vnum, pObj->iprogs->get_name);
if(IS_SET(pObj->progtypes, IPROG_PULSE))
fprintf(fp,"I %ld pulse_prog %s\n", pObj->vnum, pObj->iprogs->pulse_name);
if(IS_SET(pObj->progtypes, IPROG_INVOKE))
fprintf(fp,"I %ld invoke_prog %s\n", pObj->vnum, pObj->iprogs->invoke_name);
}
void write_mprog( FILE *fp, MOB_INDEX_DATA *pMob )
{
if(IS_SET(pMob->progtypes, MPROG_BRIBE))
fprintf(fp,"M %ld bribe_prog %s\n", pMob->vnum, pMob->mprogs->bribe_name);
if(IS_SET(pMob->progtypes, MPROG_ENTRY))
fprintf(fp,"M %ld entry_prog %s\n", pMob->vnum, pMob->mprogs->entry_name);
if(IS_SET(pMob->progtypes, MPROG_GREET))
fprintf(fp,"M %ld greet_prog %s\n", pMob->vnum, pMob->mprogs->greet_name);
if(IS_SET(pMob->progtypes, MPROG_GIVE))
fprintf(fp,"M %ld give_prog %s\n", pMob->vnum, pMob->mprogs->give_name);
if(IS_SET(pMob->progtypes, MPROG_FIGHT))
fprintf(fp,"M %ld fight_prog %s\n", pMob->vnum, pMob->mprogs->fight_name);
if(IS_SET(pMob->progtypes, MPROG_DEATH))
fprintf(fp,"M %ld death_prog %s\n", pMob->vnum, pMob->mprogs->death_name);
if(IS_SET(pMob->progtypes, MPROG_PULSE))
fprintf(fp,"M %ld pulse_prog %s\n", pMob->vnum, pMob->mprogs->pulse_name);
if(IS_SET(pMob->progtypes, MPROG_SPEECH))
fprintf(fp,"M %ld speech_prog %s\n", pMob->vnum, pMob->mprogs->speech_name);
if(IS_SET(pMob->progtypes, MPROG_ATTACK))
fprintf(fp,"M %ld attack_prog %s\n", pMob->vnum, pMob->mprogs->attack_name);
if(IS_SET(pMob->progtypes, MPROG_MOVE))
fprintf(fp,"M %ld move_prog %s\n", pMob->vnum, pMob->mprogs->move_name);
if(IS_SET(pMob->progtypes, MPROG_REQUEST))
fprintf(fp,"M %ld request_prog %s\n", pMob->vnum, pMob->mprogs->request_name);
}
void write_rprog( FILE *fp, ROOM_INDEX_DATA *pRoom )
{
if(IS_SET(pRoom->progtypes, RPROG_SPEECH))
fprintf(fp,"R %ld speech_prog %s\n", pRoom->vnum, pRoom->rprogs->speech_name);
if(IS_SET(pRoom->progtypes, RPROG_ENTRY))
fprintf(fp,"R %ld entry_prog %s\n", pRoom->vnum, pRoom->rprogs->entry_name);
}
void save_improgs( FILE *fp, AREA_DATA *pArea )
{
int i;
OBJ_INDEX_DATA *pObj;
MOB_INDEX_DATA *pMob;
ROOM_INDEX_DATA *pRoom;
fprintf(fp, "#IMPROGS\n");
for ( i = pArea->min_vnum ; i <= pArea->max_vnum ; i++)
{
if ( (pObj = get_obj_index( i )))
write_iprog(fp, pObj);
}
for ( i = pArea->min_vnum ; i <= pArea->max_vnum ; i++)
{
if ( (pMob = get_mob_index( i )))
write_mprog(fp, pMob);
}
for ( i = pArea->min_vnum ; i <= pArea->max_vnum ; i++)
{
if ( (pRoom = get_room_index( i )))
write_rprog(fp, pRoom);
}
fprintf(fp, "E\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;
fclose( fpReserve );
if ( !( fp = fopen( pArea->file_name, "w" ) ) )
{
bug( "Open_area: fopen", 0 );
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 %ld %ld\n", pArea->min_vnum, pArea->max_vnum );
fprintf( fp, "Credits %s~\n", pArea->credits );
fprintf( fp, "Security %d\n", pArea->security );
fprintf( fp, "Xplore %d\n", pArea->explore);
fprintf( fp, "End\n\n\n\n" );
save_mobiles_new( fp, pArea );
save_objects_new( fp, pArea );
save_rooms_new( fp, pArea );
save_specials( fp, pArea );
save_resets( fp, pArea );
save_shops( fp, pArea );
save_improgs( fp, pArea );
if (pArea->helps && pArea->helps->first)
save_helps (fp, pArea->helps);
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 arg1 [MAX_INPUT_LENGTH];
AREA_DATA *pArea;
FILE *fp;
int value;
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( arg1, argument );
if ( arg1[0] == '\0' )
{
send_to_char( "Syntax:\n\r", ch );
send_to_char( " asave <vnum> - saves a particular area\n\r", ch );
send_to_char( " asave list - saves the area.lst file\n\r", ch );
send_to_char( " asave area - saves the area being edited\n\r", ch );
send_to_char( " asave changed - saves all changed zones\n\r", ch );
send_to_char( " asave world - saves the world! (db dump)\n\r", ch );
send_to_char( "\n\r", ch );
return;
}
/* Snarf the value (which need not be numeric). */
value = atoi( arg1 );
if ( !( pArea = get_area_data( value ) ) && is_number( arg1 ) )
{
send_to_char( "That area does not exist.\n\r", ch );
return;
}
/* Save area of given vnum. */
/* ------------------------ */
if ( is_number( arg1 ) )
{
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 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 ( !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 );
save_other_helps (NULL);
return;
}
/* Save changed areas, only authorized areas. */
/* ------------------------------------------ */
if ( !str_cmp( "changed", arg1 ) )
{
char buf[MAX_INPUT_LENGTH];
save_area_list();
send_to_char( "Saved zones:\n\r", ch );
sprintf( buf, "None.\n\r" );
for( pArea = area_first; pArea; pArea = pArea->next )
{
/* Builder must be assigned this area. */
if ( !IS_BUILDER( ch, pArea ) )
continue;
/* Save changed areas. */
if ( IS_SET(pArea->area_flags, AREA_CHANGED) )
{
save_area( pArea );
sprintf( buf, "%24s - '%s'\n\r", pArea->name, pArea->file_name );
send_to_char( buf, ch );
REMOVE_BIT( pArea->area_flags, AREA_CHANGED );
}
}
save_other_helps (ch);
if ( !str_cmp( buf, "None.\n\r" ) )
send_to_char( buf, ch );
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" ) )
{
/* 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. */
/* -------------------- */
if (ch)
do_asave( ch, "" );
return;
}
void fwrite_area( AREA_DATA *pArea )
{
FILE *fp;
fclose( fpReserve );
if ( !( fp = fopen( pArea->file_name, "w" ) ) )
{
bug( "Open_area: fopen", 0 );
perror( pArea->file_name );
}
fprintf( fp, "#NEWAREA\n" );
fprintf( fp, "NAME %s~\n", pArea->name );
fprintf( fp, "BUILDR %s~\n", fix_string( pArea->builders ) );
fprintf( fp, "VNUMS %ld %ld\n", pArea->min_vnum, pArea->max_vnum );
fprintf( fp, "CREDIT %s~\n", pArea->credits );
fprintf( fp, "SEC %d\n", pArea->security );
fprintf( fp, "XPLORE %d\n", pArea->explore);
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_improgs( fp, pArea );
if (pArea->helps && pArea->helps->first)
save_helps (fp, pArea->helps);
fprintf( fp, "#$\n" );
fclose( fp );
fpReserve = fopen( NULL_FILE, "r" );
return;
}
void fwrite_mob( FILE *fp, MOB_INDEX_DATA *pMobIndex )
{
sh_int race = pMobIndex->race;
char buf[MSL];
fprintf( fp, "#%ld\n", pMobIndex->vnum );
fprintf( fp, "NAME %s~\n", pMobIndex->player_name );
fprintf( fp, "SHORT %s~\n", pMobIndex->short_descr );
fprintf( fp, "LONG %s~\n", fix_string( pMobIndex->long_descr ) );
fprintf( fp, "DESCR\n%s~\n", fix_string( pMobIndex->description) );
fprintf( fp, "RACE %s~\n", race_table[race].name );
fprintf( fp, "ACT %s\n", fwrite_flag( pMobIndex->act, buf ) );
fprintf( fp, "AFF %s\n", fwrite_flag( pMobIndex->affected_by, buf ) );
fprintf( fp, "OFF %s\n", fwrite_flag( pMobIndex->off_flags, buf ) );
fprintf( fp, "IMM %s\n", fwrite_flag( pMobIndex->imm_flags, buf ) );
fprintf( fp, "RES %s\n", fwrite_flag( pMobIndex->res_flags, buf ) );
fprintf( fp, "VULN %s\n", fwrite_flag( pMobIndex->vuln_flags, buf ) );
fprintf( fp, "WSPEC %s\n", fwrite_flag( pMobIndex->extended_flags, buf ) );
fprintf( fp, "ALIGN %d\n", pMobIndex->alignment);
fprintf( fp, "GROUP %d\n", pMobIndex->group);
fprintf( fp, "LEVEL %d\n", pMobIndex->level );
fprintf( fp, "HROLL %d\n", pMobIndex->hitroll );
fprintf( fp, "ENHA %.2f%%\n", pMobIndex->enhancedDamMod );
fprintf( fp, "MATER %s~\n", pMobIndex->material ? pMobIndex->material : "none" );
fprintf( fp, "HDICE %dd%d+%d\n", pMobIndex->hit[DICE_NUMBER], pMobIndex->hit[DICE_TYPE], pMobIndex->hit[DICE_BONUS] );
fprintf( fp, "MDICE %dd%d+%d\n", pMobIndex->mana[DICE_NUMBER], pMobIndex->mana[DICE_TYPE], pMobIndex->mana[DICE_BONUS] );
fprintf( fp, "DDICE %dd%d+%d\n", pMobIndex->damage[DICE_NUMBER], pMobIndex->damage[DICE_TYPE], pMobIndex->damage[DICE_BONUS] );
fprintf( fp, "REGEN %d\n", pMobIndex->regen_rate );
fprintf( fp, "DTYPE %s\n", attack_table[pMobIndex->dam_type].name );
fprintf( fp, "AC %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, "POS %s %s\n", position_table[pMobIndex->start_pos].short_name, position_table[pMobIndex->default_pos].short_name );
fprintf( fp, "SEX %s\n", sex_table[pMobIndex->sex].name );
fprintf( fp, "GOLD %ld\n", pMobIndex->wealth );
fprintf( fp, "FORM %s\n", fwrite_flag( pMobIndex->form, buf ) );
fprintf( fp, "PARTS %s\n", fwrite_flag( pMobIndex->parts, buf ) );
fprintf( fp, "SIZE %s\n", size_table[pMobIndex->size].name );
fprintf( fp, "DMOD %d\n", pMobIndex->dam_mod);
fprintf( fp, "AMOD %d\n", pMobIndex->numAttacks);
fprintf( fp, "QUEST %ld\n", pMobIndex->quest_credit_reward);
if ( pMobIndex->cabal )
fprintf( fp, "CABAL %s\n", cabal_table[pMobIndex->cabal].name);
fprintf( fp, "End\n\n" );
return;
}
void fwrite_object( FILE *fp, OBJ_INDEX_DATA *pObjIndex )
{
AFFECT_DATA *pAf;
EXTRA_DESCR_DATA *pEd;
char buf[MSL];
fprintf( fp, "#%ld\n", pObjIndex->vnum );
fprintf( fp, "NAME %s~\n", pObjIndex->name );
fprintf( fp, "SHORT %s~\n", pObjIndex->short_descr );
fprintf( fp, "DESCR \n%s~\n", fix_string( pObjIndex->description ) );
fprintf( fp, "MAT %s~\n", pObjIndex->material->name );
fprintf( fp, "TYPE %s ", item_name(pObjIndex->item_type));
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, "%ld %ld '%s' %ld %ld\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, "%ld %s %ld %ld %ld\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 %ld %ld %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, "%ld '%s' '%s' '%s' '%s'\n",
pObjIndex->value[0] > 0 ? /* no negative numbers */ 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, "%ld %ld %ld '%s' %ld\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, "EXTRA ");
save_bitmask(&pObjIndex->extra_flags, fp);
fprintf( fp, "WEAR %s\n", fwrite_flag( pObjIndex->wear_flags, buf ) );
fprintf( fp, "LEVEL %d\n", pObjIndex->level );
fprintf( fp, "WEIGHT %d\n", pObjIndex->weight );
fprintf( fp, "COST %d\n", pObjIndex->cost );
fprintf( fp, "COND %d\n", pObjIndex->condition );
for( pAf = pObjIndex->affected; pAf; pAf = pAf->next )
{
fprintf( fp, "Affect " );
if (pAf->where == TO_OBJECT || pAf->bitvector == 0)
fprintf( fp, "O %d %d 0\n", pAf->location, pAf->modifier );
else
{
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: bug( "olc_save: Invalid Affect->where", 0); 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, "EDESC %s~\n%s~\n", pEd->keyword,fix_string( pEd->description ) );
}
if ( pObjIndex->cabal )
fprintf( fp, "CABAL %d\n", pObjIndex->cabal );
if ( pObjIndex->limtotal )
fprintf( fp, "LIMIT %d\n", pObjIndex->limtotal );
if ( pObjIndex->restrict_flags )
fprintf( fp, "RESTR %s\n", fwrite_flag( pObjIndex->restrict_flags, buf ) );
fprintf( fp, "End\n\n" );
return;
}
void fwrite_room( FILE *fp, ROOM_INDEX_DATA *pRoomIndex )
{
EXTRA_DESCR_DATA *pEd;
EXIT_DATA *pExit;
int door;
char buf[MAX_STRING_LENGTH];
fprintf( fp, "#%ld\n", pRoomIndex->vnum );
fprintf( fp, "NAME %s~\n", pRoomIndex->name );
fprintf( fp, "DESCR\n%s~\n", fix_string( pRoomIndex->description ) );
fprintf( fp, "FLAGS %d\n", pRoomIndex->room_flags );
fprintf( fp, "Sect %d\n", pRoomIndex->sector_type );
for ( pEd = pRoomIndex->extra_descr; pEd; pEd = pEd->next )
fprintf( fp, "EDESC %s~\n%s~\n", pEd->keyword, fix_string( pEd->description ) );
for ( door = 0; door <MAX_DIR; door++ )
{
if ((pExit = pRoomIndex->exit[door]) && (pExit->u1.to_room ))
{
// OLC is making some doors not doors anymore, but leaving them closed. Quick hack until the problem is identified. - Tracerah (4/17/09)
if (IS_SET(pExit->rs_flags, EX_CLOSED) && !IS_SET(pExit->rs_flags, EX_ISDOOR)) {
SET_BIT(pExit->rs_flags, EX_ISDOOR);
}
fprintf( fp, "DOOR %ld\n", pExit->orig_door );
fprintf( fp, "%s~\n", fix_string( pExit->description));
fprintf( fp, "%s~\n", pExit->keyword );
fprintf( fp, "%s %ld %ld\n", fwrite_flag(pExit->rs_flags, buf), pExit->key, pExit->u1.to_room->vnum );
}
}
if (pRoomIndex->mana_rate != 100 || pRoomIndex->heal_rate != 100)
fprintf ( fp, "MHRATE %d %d\n", pRoomIndex->mana_rate, pRoomIndex->heal_rate);
if (pRoomIndex->cabal)
fprintf( fp, "CABAL %s~\n", cabal_table[pRoomIndex->cabal].name);
fprintf( fp, "End\n\n" );
return;
}
void save_rooms_new( FILE *fp, AREA_DATA *pArea )
{
int i;
ROOM_INDEX_DATA *pRoom;
fprintf( fp, "#ROOMDATA\n" );
for( i = pArea->min_vnum; i <= pArea->max_vnum; i++ )
{
if ( (pRoom = get_room_index( i )) )
fwrite_room( fp, pRoom );
}
fprintf( fp, "#0\n\n\n\n" );
return;
}
void save_objects_new( FILE *fp, AREA_DATA *pArea )
{
int i;
OBJ_INDEX_DATA *pObj;
fprintf( fp, "#OBJDATA\n" );
for( i = pArea->min_vnum; i <= pArea->max_vnum; i++ )
{
if ( (pObj = get_obj_index( i )) )
fwrite_object( fp, pObj );
}
fprintf( fp, "#0\n\n\n\n" );
return;
}
void save_mobiles_new( FILE *fp, AREA_DATA *pArea )
{
int i;
MOB_INDEX_DATA *pMob;
fprintf( fp, "#MOBDATA\n" );
for( i = pArea->min_vnum; i <= pArea->max_vnum; i++ )
{
if ( (pMob = get_mob_index( i )) )
fwrite_mob( fp, pMob );
}
fprintf( fp, "#0\n\n\n\n" );
return;
}