daleken/
daleken/data/notes/
daleken/data/player/
daleken/data/system/poses/
daleken/doc/Homepage/images/
daleken/log/
/*___________________________________________________________________________*
   )()(			  DalekenMUD 1.12 (C) 2000			)()(
   `]['		       by Martin Thomson, Lee Brooks,			`]['
    ||		       Ken Herbert and David Jacques			 ||
    || ----------------------------------------------------------------- ||
    || Envy Diku Mud improvements copyright (C) 1994 by Michael Quan,	 ||
    || David Love, Guilherme 'Willie' Arnold, and Mitchell Tse.		 ||
    || Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael	 ||
    || Chastain, Michael Quan, and Mitchell Tse.			 ||
    || Original Diku Mud copyright (C) 1990, 1991			 ||
    || by Sebastian Hammer, Michael Seifert, Hans Henrik St{rfeldt,	 ||
    || Tom Madsen, and Katja Nyboe.					 ||
    || ----------------------------------------------------------------- ||
    || Any use of this software must follow the licenses of the		 ||
    || creators.  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.					 ||
    || ----------------------------------------------------------------- ||
    ||				  scriptsave.c				 ||
    || Methods for saving a file for olc input.				 ||
 *_/<>\_________________________________________________________________/<>\_*/


/*
 * This file was created to demonstrate the flexibility of the OLC system.
 * Using this file, you can create a file which contains a list of commands
 * that will successfully create a single area on a MUD that has similar OLC
 * syntax to that of Daleken.  This script saver has been tested on both
 * Daleken and another Envy based MUD called Asgaard and it has been 99%
 * successful on both.
 *
 * Warning: this file may not work as it is not regularly tested.
 */

/*
 * If you want to save an area as an OLC script you will have to include this
 * file in your Makefile as well as adding the following line to interp.c:
     { "scriptsave",	do_scriptsave,	POS_DEAD,	L_MAS,	LOG_ALWAYS },
 */


#include "mud.h"
#include "olc.h"


/*
 * Scriptsave, saves an area as an OLC script.
 * A cheat for those who would only build on one mud but have the
 * area in many places, without the work.
 */
#define SCRIPTSAVE_DALEKEN 1
#define SCRIPTSAVE_ASGAARD 2
void scriptsave_area	args( ( FILE * fp, AREA_DATA * pArea, int shift, int type ) );
void scriptsave_objects	args( ( FILE * fp, AREA_DATA * pArea, int shift, int type ) );
void scriptsave_mobiles	args( ( FILE * fp, AREA_DATA * pArea, int shift, int type ) );
void scriptsave_rooms	args( ( FILE * fp, AREA_DATA * pArea, int shift, int type ) );
void scriptsave_exits	args( ( FILE * fp, AREA_DATA * pArea, int shift, int type ) );
void scriptsave_resets	args( ( FILE *fp, RESET_DATA * pReset, int shift, int type ) );


/*
 * Scriptsave.
 *
 * Written by Symposium to allow builders who play multiple muds to
 * utilise the similarities with OLC by saving areas as an OLC script.
 * This means you can move areas to other mud which have strange area
 * formats.
 * New types can easily be added to suit your favourite mud(s).
 */
void do_scriptsave( CHAR_DATA *ch, const char *argument )
{
    CHAR_DATA *rch;
    FILE *fp;
    AREA_DATA *pArea;
    char comm[MAX_INPUT_LENGTH];
    char filename[MAX_INPUT_LENGTH];
    int vnum_shift = 0, type;

    rch = get_char( ch );
    if( !authorized( rch, "scriptsave" ) )
	return;

    argument = one_argument( argument, comm );
    if( !str_cmp( comm, "daleken" ) )
    {
	type = SCRIPTSAVE_DALEKEN;
    }
    else if( !str_cmp( comm, "asgaard" ) )
    {
	type = SCRIPTSAVE_ASGAARD;
    }
    else
    {
	do_help( ch, "Scriptsave" );
	return;
    }

    argument = one_argument( argument, comm );
    if( !str_cmp( comm, "area" ) )
    {
	pArea = get_editing_area( ch );
    }
    else if( is_number( comm ) )
    {
	pArea = get_area_data( atoi( comm ) );
    }
    else
    {
	do_help( ch, "scriptsave" );
	return;
    }

    if( !pArea )
    {
	send_to_char( "Non-existant area.\n\r", ch );
	return;
    }
    if( !IS_BUILDER( ch, pArea ) )
    {
	send_to_char( "You are not a builder for this area.\n\r", ch );
	return;
    }

    argument = one_argument( argument, comm );
    if( !str_cmp( comm, "shift" ) )
    {
	vnum_shift = atoi( argument );
	if( vnum_shift % 100 != 0 )
	{
	    send_to_char( "Make the vnum shift a multiple of 100 please.\n\r",
			  ch );
	    return;
	}
    }

    strcpy( filename, pArea->filename );
    strcat( filename, ".olc" );

    fp = open_file( filename, "w", FALSE );
    if( !fp )
    {
	bug( "Cannot open area file {%d}.", pArea->vnum );
	return;
    }

    scriptsave_area( fp, pArea, vnum_shift, type );
    scriptsave_objects( fp, pArea, vnum_shift, type );
    scriptsave_mobiles( fp, pArea, vnum_shift, type );
    scriptsave_rooms( fp, pArea, vnum_shift, type );

    close_file( fp );
    send_to_char( "Area saved.\n\r", ch );
    return;
}


void scriptsave_area( FILE *fp, AREA_DATA * pArea, int shift, int type )
{
    char tmp[MAX_STRING_LENGTH];

    fprintf( fp, "aedit\n" );
    fprintf( fp, "name %s\n", pArea->name );
    fprintf( fp, "vnum %d %d\n", pArea->lvnum + shift , pArea->uvnum + shift );
    if( pArea->recall != ROOM_VNUM_TEMPLE )
	fprintf( fp, "recall %d\n", pArea->recall );

    switch( type )
    {
    case SCRIPTSAVE_DALEKEN:
	fprintf( fp, "plane %s\n", pArea->plane );
	if( pArea->repop && pArea->repop[0] )
	    fprintf( fp, "repop %s\n", fix_string( tmp, pArea->repop ) );
	fprintf( fp, "temp %d\n", pArea->ave_temp );
	if( ( pArea->area_flags & AREA_SAVE ) )
	{
	    int i = pArea->area_flags & AREA_SAVE;
	    fprintf( fp, "%s\n", flag_string( area_flags, &i ) );
	}
	break;
    case SCRIPTSAVE_ASGAARD:
	fprintf( fp, "plane %s\n", pArea->plane );
	break;
    }
    fprintf( fp, "done\n\n" );
    return;
}


void scriptsave_objects( FILE * fp, AREA_DATA * pArea, int shift, int type )
{
    int vnum;
    OBJ_INDEX_DATA *pObj;
    AFFECT_DATA *pAf;
    EXTRA_DESCR_DATA *pEd;
    char tmp[MAX_STRING_LENGTH];

    fprintf( fp, "oedit\n" );
    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pObj = get_obj_index( vnum ) )
	    && pObj->area == pArea )
	{
	    fprintf( fp, "create %d\n", pObj->vnum + shift );
	    fprintf( fp, "name %s\n", pObj->name );
	    fprintf( fp, "short %s\n", pObj->short_descr );
	    fprintf( fp, "long %s\n",  fix_string( tmp, pObj->description ) );
	    fprintf( fp, "level %d\n", pObj->level );
	    if( pObj->cost > 0 )
		fprintf( fp, "cost %d\n", pObj->cost );
	    fprintf( fp, "weight %d\n", pObj->weight );
	    if( pObj->reset_chance < 1000 )
		fprintf( fp, "repop %d\n", pObj->reset_chance );
	    fprintf( fp, "'%s\n", flag_string( type_flags, &pObj->item_type ) );
	    fprintf( fp, "%s\n", flag_string( wear_flags, &pObj->wear_flags ) );
	    fprintf( fp, "%s\n", flag_string( extra_flags, &pObj->extra_flags ) );
	    fprintf( fp, "%s\n", flag_string( material_flags, &pObj->material ) );
	    switch( type )
	    {
	    case SCRIPTSAVE_DALEKEN:
		if( pObj->action && pObj->action[0] )
		    fprintf( fp, "action %s", fix_string( tmp, pObj->action ) );
		if( pObj->required_skill > 0 )
		    fprintf( fp, "Required %s\n",
			     skill_table[pObj->required_skill].name );
		break;
	    case SCRIPTSAVE_ASGAARD:
		break;
	    }
	    switch( pObj->item_type )
	    {
	    default:
	    case ITEM_FURNITURE:
	    case ITEM_TRASH:
	    case ITEM_KEY:
	    case ITEM_BOAT:
		break;

	    case ITEM_PORTAL:
		fprintf( fp, "v0 %d\n", pObj->value[0] + shift );
		break;

	    case ITEM_EXPLOSIVE:
	    case ITEM_MONEY:
	    case ITEM_TREASURE:
		fprintf( fp, "v0 %d\n", pObj->value[0] );
		break;

	    case ITEM_ARMOUR:
		fprintf( fp, "v1 %d\n", pObj->value[1] );
		break;

	    case ITEM_LIGHT:
		fprintf( fp, "v2 %d\n", pObj->value[2] );
		break;

	    case ITEM_STAFF:
	    case ITEM_WAND:
		fprintf( fp, "v0 %d\nv1 %d\nv2 %d\nv3 %s\n",
			 pObj->value[0], pObj->value[1], pObj->value[2],
			 pObj->value > 0 ?
			 skill_table[pObj->value[3]].name : "none" );
		break;

	    case ITEM_PLANT:
		if( type == SCRIPTSAVE_ASGAARD )
		    fprintf( fp, "say I created a plant\n" );
	    case ITEM_PILL:
	    case ITEM_POTION:
	    case ITEM_SCROLL:
		fprintf( fp, "v0 %d\nv1 %s\nv2 %s\nv3 %s\n",
			 pObj->value[0],
			 pObj->value[1] > 0 ?
			 skill_table[pObj->value[1]].name : "none",
			 pObj->value[2] > 0 ?
			 skill_table[pObj->value[2]].name : "none",
			 pObj->value[3] > 0 ?
			 skill_table[pObj->value[3]].name : "none" );
		break;

	    case ITEM_WEAPON:
		fprintf( fp, "v0 %s\nv3 %s\n",
			 pObj->value[0] > 0 ?
			 skill_table[pObj->value[0]].name : "none",
			 flag_string( weapon_flags, &pObj->value[3] ) );
		break;

	    case ITEM_CORPSE_PC:
	    case ITEM_CORPSE_NPC:
		if( type == SCRIPTSAVE_DALEKEN )
		    fprintf( fp, "v0 %s\n", race_table[pObj->value[0]].name );
		break;

	    case ITEM_CONTAINER:
		fprintf( fp, "v0 %d\nv1 %s\nv2 %d\n",
			 pObj->value[0],
			 flag_string( container_flags, &pObj->value[1] ),
			 pObj->value[2] + shift );
		break;

	    case ITEM_DRINK_CON:
		fprintf( fp, "v0 %d\nv1 %d\n v2 %s\nv3 %d\n",
			 pObj->value[0], pObj->value[1],
			 flag_string( liquid_flags, &pObj->value[2] ),
			 pObj->value[3] );
		break;

	    case ITEM_FOUNTAIN:
		fprintf( fp, "v2 %s\n", flag_string( liquid_flags, &pObj->value[2] ) );
		break;

	    case ITEM_FOOD:
		fprintf( fp, "v0 %d\nv3 %d\n", pObj->value[0], pObj->value[3] );
		break;

	    case ITEM_LIMB:
		if( type == SCRIPTSAVE_DALEKEN )
		    fprintf( fp, "v0 %s\n", flag_string( body_part_flags, &pObj->value[0] ) );
		break;
	    }

	    for( pAf = pObj->affected; pAf; pAf = pAf->next )
	    {
		char temp[MAX_STRING_LENGTH];

		strcpy( temp, flag_string( apply_flags, &pAf->location ) );
		if( pAf->type == gsn_perm_spell )
		    fprintf( fp, "addperm %s\n",
			     skill_table[pAf->location].name );
		else if( type == SCRIPTSAVE_DALEKEN
			 && ( !vnull( pAf->bitvector ) || pAf->type > 0 ) )
		    fprintf( fp, "addspell '%s' %s %d %s\n",
			     skill_table[pAf->type].name,
			     temp, pAf->modifier,
			     flag_string( affect_flags, pAf->bitvector ) );
		else
		    fprintf( fp, "addaffect %s %d\n",
			     temp, pAf->modifier );
	    }

	    for( pEd = pObj->extra_descr; pEd; pEd = pEd->next )
	    {
		if( type == SCRIPTSAVE_DALEKEN )
		    fprintf( fp, "ed add %s\n", fix_string( tmp, pEd->keyword ) );
		else
		    fprintf( fp, "ed add '%s\n", fix_string( tmp, pEd->keyword ) );
		fprintf( fp, "%s@\n",
			 fix_string( tmp, pEd->description ) );
	    }
	}
    }

    fprintf( fp, "done\n\n" );

    return;
}


void scriptsave_mobiles( FILE * fp, AREA_DATA * pArea, int shift, int type )
{
    int vnum;
    MOB_INDEX_DATA *pMob;
    char tmp[MAX_STRING_LENGTH];

    fprintf( fp, "medit\n" );
    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pMob = get_mob_index( vnum ) )
	    && pMob->area == pArea )
	{
	    fprintf( fp, "create %d\n", pMob->vnum + shift );
	    fprintf( fp, "name %s\n", pMob->name );
	    fprintf( fp, "short %s\n", pMob->short_descr );
	    fprintf( fp, "long %s", fix_string( tmp, pMob->long_descr ) );
	    fprintf( fp, "desc\n%s@\n", fix_string( tmp, pMob->description ) );
	    fprintf( fp, "level %d\n", pMob->level );
	    fprintf( fp, "align %d\n", pMob->alignment );
	    if( pMob->reset_chance < 1000 )
		fprintf( fp, "repop %d\n", pMob->reset_chance );
	    fprintf( fp, "%s\n",
		     flag_string( act_flags, pMob->act ) );
	    fprintf( fp, "%s\n",
		     flag_string( affect_flags, pMob->affected_by ) );
	    fprintf( fp, "%s\n",
		     flag_string( sex_flags, &pMob->sex ) );
	    fprintf( fp, "%s\n", race_table[pMob->race].name );
	    if( pMob->spec_fun )
		fprintf( fp, "specfun %s\n",
			 spec_table[pMob->spec_fun].spec_name );
	    switch( type )
	    {
	    case SCRIPTSAVE_DALEKEN:
		if( pMob->class != CLASS_NONE )
		    fprintf( fp, "class %s\n",
			     flag_string( class_flags, &pMob->class ) );
		if( pMob->body_parts != race_table[pMob->race].body_parts )
		{
		    int i = pMob->body_parts ^ race_table[pMob->race].body_parts;
		    fprintf( fp, "%s\n", flag_string( body_part_flags, &i ) );
		}
		break;
	    case SCRIPTSAVE_ASGAARD:
		if( pMob->class != CLASS_NONE )
		    fprintf( fp, "%s\n", flag_string( class_flags, &pMob->class ) );
		break;
	    }

	    if( pMob->pShop )
	    {
		int i;

		for( i = 0; i < MAX_TRADE; i++ )
		    if( pMob->pShop->buy_type[i] > 0 )
			fprintf( fp, "shop type %d %s\n", i,
				 flag_string( type_flags,
					      &pMob->pShop->buy_type[i] ) );
		fprintf( fp, "shop profit %d %d\n",
			 pMob->pShop->profit_buy, pMob->pShop->profit_sell );
		fprintf( fp, "shop hours %d %d\n",
			 pMob->pShop->open_hour, pMob->pShop->close_hour );
	    }
	}
    }

    fprintf( fp, "done\n\n" );

    return;
}


void scriptsave_rooms( FILE * fp, AREA_DATA * pArea, int shift, int type )
{
    ROOM_INDEX_DATA *pRoom;
    EXTRA_DESCR_DATA *pEd;
    int vnum;
    char tmp[MAX_STRING_LENGTH];

    fprintf( fp, "redit\n" );
    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pRoom = get_room_index( vnum ) )
	    && pRoom->area == pArea )
	{
	    fprintf( fp, "create %d\n", pRoom->vnum + shift );
	    fprintf( fp, "goto %d\n", pRoom->vnum + shift );
	    fprintf( fp, "name %s\n", pRoom->name );
	    fprintf( fp, "desc\n%s@\n", fix_string( tmp, pRoom->description ) );
	    fprintf( fp, "%s\n", flag_string( room_flags, &pRoom->room_flags ) );
	    fprintf( fp, "%s\n", flag_string( sector_flags, &pRoom->sector_type ) );

	    for( pEd = pRoom->extra_descr; pEd; pEd = pEd->next )
	    {
		if( type == SCRIPTSAVE_DALEKEN )
		    fprintf( fp, "ed add %s\n", pEd->keyword );
		else
		    fprintf( fp, "ed add '%s\n", pEd->keyword );
		fprintf( fp, "%s@\n",
			 fix_string( tmp, pEd->description ) );
	    }

	    scriptsave_resets( fp, pRoom->reset_first, shift, type );
	}
    }
    scriptsave_exits( fp, pArea, shift, type );

    fprintf( fp, "done\n\n" );

    return;
}


void scriptsave_exits( FILE * fp, AREA_DATA * pArea, int shift, int type )
{
    ROOM_INDEX_DATA *pRoom;
    EXIT_DATA *pExit;
    int vnum;
    int door;
    char tmp[MAX_STRING_LENGTH];

    for( vnum = pArea->lvnum; vnum <= pArea->uvnum; vnum++ )
    {
	if( ( pRoom = get_room_index( vnum ) )
	    && pRoom->area == pArea )
	{
	    fprintf( fp, "goto %d\n", pRoom->vnum + shift );
	    for( door = 0; door < MAX_DIR; door++ )
	    {
		if( ( pExit = pRoom->exit[door] )
		    && pExit->to_room )
		{
		    fprintf( fp, "%s room %d\n", dir_name[door],
			     pExit->to_room->vnum + shift );
		    if( pExit->keyword && pExit->keyword[0] )
			fprintf( fp, "%s name %s\n", dir_name[door],
				 pExit->keyword );
		    if( pExit->description && pExit->description[0] )
			fprintf( fp, "%s desc\n%s@\n", dir_name[door],
				 fix_string( tmp, pExit->description ) );
		    if( pExit->key > 0 )
			fprintf( fp, "%s key %d\n",
				 dir_name[door], pExit->key + shift );
		    if( pExit->rs_flags != 0
			&& pExit->to_room->exit[rev_dir[door]]
			&& pExit->to_room->exit[rev_dir[door]]->to_room == pRoom
			&& pExit->to_room->vnum > pRoom->vnum )
			fprintf( fp, "%s %s\n", dir_name[door],
				 flag_string( exit_flags, &pExit->rs_flags ) );
		}
	    }
	}
    }

    return;
}


void scriptsave_resets( FILE *fp, RESET_DATA *pReset, int shift, int type )
{
    for( ; pReset; pReset = pReset->next )
    {
	switch( pReset->command )
	{
	case 'M':
	    fprintf( fp, "reset 1000 mob %d %d\n", pReset->arg1 + shift,
		     ( type != SCRIPTSAVE_DALEKEN && pReset->arg2 < 0 ) ?
		     0 : pReset->arg2 );
	    break;

	case 'O':
	    fprintf( fp, "reset 1000 obj %d room\n", pReset->arg1 + shift );
	    break;

	case 'P':
	    fprintf( fp, "reset 1000 obj %d in %d\n", pReset->arg1 + shift,
		     pReset->arg2 + shift );
	    break;

	case 'G':
	case 'E':
	    fprintf( fp, "reset 1000 obj %d %s\n", pReset->arg1 + shift,
		     flag_string( wear_loc_flags, &pReset->arg2 ) );
	    break;

	case 'R':
	    if( type != SCRIPTSAVE_DALEKEN )
		break;
	    if( pReset->arg1 == 0 )
		fprintf( fp, "reset 1000 rand 0 %s\n",
			 flag_string( direction_flags, &pReset->arg2 ) );
	    else
		fprintf( fp, "reset 1000 rand %d\n", pReset->arg1 );
	    break;

	case 'D':
	    break;
	}
    }
}