area/
build/testing/
log/
player/
player/backup/
/* The following code is based on ILAB OLC by Jason Dinkel */
/* Mobprogram code by Lordrom for Nevermore Mud */

/* Object and Room Progs added by SpiralSOFT! */
#include <glib.h>

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <merc.h>
#include <tables.h>
#include <olc.h>
#include <recycle.h>

#define MPEDIT( fun )           bool fun(CHAR_DATA *ch, char*argument)

bool find_objmob(CHAR_DATA *mob, OBJ_INDEX_DATA *pObjIndex)
{
	OBJ_DATA *obj;

	for (obj = mob->carrying; obj != NULL; obj = obj->next_content )
	{
		if (obj->pIndexData == pObjIndex)
			return TRUE;			
	}
	return FALSE;
}

/* OLC
 * Reset one room.  Called by reset_area and olc.
 */
void reset_room( ROOM_INDEX_DATA *pRoom )
{
	RESET_DATA  *pReset;
	GSList *ResetList;
	CHAR_DATA   *pMob;
	/* CHAR_DATA	*mob; */
	OBJ_DATA    *pObj;
	CHAR_DATA   *LastMob = NULL;
	OBJ_DATA    *LastObj = NULL;
	int iExit;
	int level = 0;
	bool last;
	
	if ( !pRoom )
		return;
	
	
	/*pMob        = NULL; */
	
	
	last        = FALSE;
	
	for ( iExit = 0;  iExit < MAX_DIR;  iExit++ )
	{
		EXIT_DATA *pExit;
		if ( ( pExit = pRoom->exit[iExit] )
	  /*  && !IS_SET( pExit->exit_info, EX_BASHED )   ROM OLC */ )  
		{
			pExit->exit_info = pExit->rs_flags;
			if ( ( pExit->to_room != NULL )
				&& ( ( pExit = pExit->to_room->exit[rev_dir[iExit]] ) ) )
			{
                /* nail the other side */
				pExit->exit_info = pExit->rs_flags;
			}
		}
	}
	
	for ( ResetList = pRoom->reset_list; ResetList != NULL; ResetList = g_slist_next(ResetList) )
	{
		MOB_INDEX_DATA  *pMobIndex;
		OBJ_INDEX_DATA  *pObjIndex;
		ROOM_INDEX_DATA *pRoomIndexPrev;
		OBJ_INDEX_DATA  *pObjToIndex;
		ROOM_INDEX_DATA *pRoomIndex;
		char buf[MAX_STRING_LENGTH];
		int count=0;
		
		pReset = (RESET_DATA*)ResetList->data;
		switch ( pReset->command )
		{
			default:
				bug( "Reset_room: bad command %c.", pReset->command );
				break;
				
			case 'M':
				
				if ( !( pMobIndex = get_mob_index( pReset->arg1 ) ) )
				{
					bug( "Reset_room: 'M': bad vnum %d.", pReset->arg1 );
					continue;
				}
				
				if ( ( pRoomIndex = get_room_index( pReset->arg3 ) ) == NULL )
				{
					bug( "Reset_area: 'R': bad vnum %d.", pReset->arg3 );
					continue;
				}

				if ( pMobIndex->count >= pReset->arg2 )
				{
					last = FALSE;
					break;
				}
				
				pMob = create_mobile( pMobIndex );
				
            			/*
             			* Pet shop mobiles get ACT_PET set.
             			*/
					
				pRoomIndexPrev = get_room_index( pRoomIndex->vnum - 1 );
				if ( pRoomIndexPrev
					&& IS_SET( pRoomIndexPrev->room_flags, ROOM_PET_SHOP ) )
					SET_BIT( pMob->act, ACT_PET);
				
				char_to_room( pMob, pRoomIndex );

				
				LastMob = pMob;
				level  = URANGE( 0, pMob->level - 2, LEVEL_HERO - 1 ); /* -1 ROM */
				last = TRUE;
				
				break;
				
			case 'O':
				if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
				{
					bug( "Reset_room: 'O' 1 : bad vnum %d", pReset->arg1 );
					sprintf (buf,"%d %d %d %d",pReset->arg1, pReset->arg2, pReset->arg3,
						pReset->arg4 );
					bug(buf,1);
					continue;
				}
				
				if ( !( pRoomIndex = get_room_index( pReset->arg3 ) ) )
				{
					bug( "Reset_room: 'O' 2 : bad vnum %d.", pReset->arg3 );
					sprintf (buf,"%d %d %d %d",pReset->arg1, pReset->arg2, pReset->arg3,
						pReset->arg4 );
					bug(buf,1);
					continue;
				}
				if ( pRoomIndex->area->nplayer > 0
					|| count_obj_list( pObjIndex, pRoomIndex->contents ) > 0 )
				{
					last = FALSE;
					break;
				}
				pObj = create_object( pObjIndex,number_range(1,50) );
				pObj->cost = 0;
				obj_to_room( pObj, pRoomIndex );
				last = TRUE;
				break;
				
			case 'P':
				if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
				{
					bug( "Reset_room: 'P': bad vnum %d.", pReset->arg1 );
					continue;
				}
				
				if ( !( pObjToIndex = get_obj_index( pReset->arg3 ) ) )
				{
					bug( "Reset_room: 'P': bad vnum %d.", pReset->arg3 );
					continue;
				}
				
				if ( pRoom->area->nplayer > 0
					|| !( LastObj = get_obj_type( pObjToIndex ) ) 
         /*     || ( LastObj->in_room == NULL && !last)
              || ( pObjIndex->count >= limit && number_range(0,4) != 0 )
              || ( count = count_obj_list( pObjIndex, LastObj->contains ) ) > pReset->arg4  )
         */
					||  ( count = count_obj_list( pObjIndex, LastObj->contains ) ) > pReset->arg4 )
				{
					last = FALSE;
					break;
				}
				                /* lastObj->level  -  ROM */
				
				pObj = create_object( pObjIndex, number_range(1,50) );
				obj_to_obj( pObj, LastObj );
				last = TRUE;
				break;
				
			case 'G':
			case 'E':
				if ( !( pObjIndex = get_obj_index( pReset->arg1 ) ) )
				{
					bug( "Reset_room: 'E' or 'G': bad vnum %d.", pReset->arg1 );
					continue;
				}
				
				if ( !last )
					break;
				
				if ( !LastMob )
				{
					bug( "Reset_room: 'E' or 'G': null mob for vnum %d.",
						pReset->arg1 );
					last = FALSE;
					break;
				}

				/*
				 * Check mobile if they don't already have said eq..
				 */

				if (find_objmob(LastMob, pObjIndex))
					continue;

				if ( LastMob->pIndexData->pShop )   /* Shop-keeper? */
				{
					int olevel=0;
					
					switch ( pObjIndex->item_type )
					{
						default:                olevel = 0;                      break;
						case ITEM_PILL:         olevel = number_range( 0,10); break;
						case ITEM_POTION:       olevel = number_range( 0,10); break;
						case ITEM_SCROLL:       olevel = number_range( 5,15); break;
						case ITEM_WAND:         olevel = number_range( 10, 20 ); break;
						case ITEM_STAFF:        olevel = number_range( 15, 25 ); break;
						case ITEM_ARMOR:        olevel = number_range(  5, 15 ); break;
						case ITEM_WEAPON:       olevel = number_range(  5, 15 ); break;
					}
					
					pObj = create_object( pObjIndex, olevel );
					SET_BIT( pObj->extra_flags, ITEM_INVENTORY );  /* ROM OLC */
					
				}
				else   /* ROM OLC else version */
				{
					pObj = create_object( pObjIndex, number_range( 1,50)); 
				}
				obj_to_char( pObj, LastMob );
				if ( pReset->command == 'E' )
					equip_char( LastMob, pObj, pReset->arg3 );
				last = TRUE;
				break;
				
			case 'D':
				break;
				
			case 'R':
				if ( !( pRoomIndex = get_room_index( pReset->arg1 ) ) )
				{
					bug( "Reset_room: 'R': bad vnum %d.", pReset->arg1 );
					continue;
				}
				
				{
					EXIT_DATA *pExit;
					int d0;
					int d1;
					
					for ( d0 = 0; d0 < pReset->arg2 - 1; d0++ )
					{
						d1                   = number_range( d0, pReset->arg2-1 );
						pExit                = pRoomIndex->exit[d0];
						pRoomIndex->exit[d0] = pRoomIndex->exit[d1];
						pRoomIndex->exit[d1] = pExit;
					}
				}
				break;
		}
	}
	
	
	
	return;
}

/* OLC
 * Reset one area.
 */
void reset_area( AREA_DATA *pArea )
{
	ROOM_INDEX_DATA *pRoom;
	int  vnum;
	
	
	for ( vnum = pArea->min_vnum; vnum <= pArea->max_vnum; vnum++ )
	{
		if ( ( pRoom = get_room_index(vnum) ) )
		{
			reset_room(pRoom);
		}
	}
	return;
}

const struct olc_cmd_type mpedit_table[] =
{
/*	{	command		function	}, */

	{	"commands",	show_commands	},
	{	"create",	mpedit_create	},
	{	"code",		mpedit_code	},
	{	"show",		mpedit_show	},
	{	"list",		mpedit_list	},
	{	"?",		show_help	},

	{	NULL,		0		}
};

void mpedit( CHAR_DATA *ch, char *argument)
{
    MPROG_CODE *pMcode;
    char arg[MAX_INPUT_LENGTH];
    char command[MAX_INPUT_LENGTH];
    int cmd;
    AREA_DATA *ad;

    smash_tilde(argument);
    str_cpy(arg, argument);
    argument = one_argument( argument, command);

    EDIT_MPCODE(ch, pMcode);

    if (pMcode)
    {
	ad = get_vnum_area( pMcode->vnum );

	if ( ad == NULL ) /* ??? */
	{
		edit_done(ch);
		return;
	}

	if ( !IS_BUILDER(ch, ad) )
	{
		send_to_char("MPEdit: Insufficient security to modify code.\n\r", ch);
		edit_done(ch);
		return;
	}
    }

    if (command[0] == '\0')
    {
        mpedit_show(ch, argument);
        return;
    }

    if (!str_cmp(command, "done") )
    {
        edit_done(ch);
        return;
    }

    for (cmd = 0; mpedit_table[cmd].name != NULL; cmd++)
    {
	if (!str_prefix(command, mpedit_table[cmd].name) )
	{
		if ((*mpedit_table[cmd].olc_fun) (ch, argument) && pMcode)
			if ((ad = get_vnum_area(pMcode->vnum)) != NULL)
				SET_BIT(ad->area_flags, AREA_CHANGED);
		return;
	}
    }

    interpret(ch, arg);

    return;
}

void do_mpedit(CHAR_DATA *ch, char *argument)
{
    MPROG_CODE *pMcode;
    char command[MAX_INPUT_LENGTH];

    argument = one_argument(argument, command);

    if( is_number(command) )
    {
	int vnum = atoi(command);
	AREA_DATA *ad;

	if ( (pMcode = get_mprog_index(vnum)) == NULL )
	{
		send_to_char("MPEdit : That vnum does not exist.\n\r",ch);
		return;
	}

	ad = get_vnum_area(vnum);

	if ( ad == NULL )
	{
		send_to_char( "MPEdit : VNUM is not assigned to this area.\n\r", ch );
		return;
	}

	if ( !IS_BUILDER(ch, ad) )
	{
		send_to_char("MPEdit : Insufficient security to edit this area.\n\r", ch );
		return;
	}

	ch->desc->pEdit		= (void *)pMcode;
	ch->desc->editor	= ED_MPCODE;

	return;
    }

    if ( !str_cmp(command, "create") )
    {
	if (argument[0] == '\0')
	{
		send_to_char( "Sintax : mpedit create [vnum]\n\r", ch );
		return;
	}

	mpedit_create(ch, argument);
	return;
    }

    send_to_char( "Sintax : mpedit [vnum]\n\r", ch );
    send_to_char( "           mpedit create [vnum]\n\r", ch );

    return;
}

MPEDIT (mpedit_create)
{
    MPROG_CODE *pMcode;
    int value = atoi(argument);
    AREA_DATA *ad;

    if (IS_NULLSTR(argument) || value < 1)
    {
	send_to_char( "Sintax : mpedit create [vnum]\n\r", ch );
	return FALSE;
    }

    ad = get_vnum_area(value);

    if ( ad == NULL )
    {
    	send_to_char( "MPEdit : VNUM not assigned to this area.\n\r", ch );
    	return FALSE;
    }
    
    if ( !IS_BUILDER(ch, ad) )
    {
        send_to_char("MPEdit : Insufficient security to create MobProgs.\n\r", ch);
        return FALSE;
    }

    if ( get_mprog_index(value) )
    {
	send_to_char("MPEdit: Code vnum already exists.\n\r",ch);
	return FALSE;
    }

    pMcode			= new_mpcode();
    pMcode->vnum		= value;
    pMcode->next		= mprog_list;
    mprog_list			= pMcode;
    ch->desc->pEdit		= (void *)pMcode;
    ch->desc->editor		= ED_MPCODE;

    send_to_char("MobProgram Code Created.\n\r",ch);

    return TRUE;
}

MPEDIT(mpedit_show)
{
    MPROG_CODE *pMcode;
    char buf[MAX_STRING_LENGTH];

    EDIT_MPCODE(ch,pMcode);

    sprintf(buf,
           "Vnum:       [%d]\n\r"
           "Code:\n\r%s\n\r",
           pMcode->vnum, pMcode->code->str);
    send_to_char(buf, ch);

    return FALSE;
}

MPEDIT(mpedit_code)
{
    MPROG_CODE *pMcode;
    EDIT_MPCODE(ch, pMcode);

    if (argument[0] =='\0')
    {
       string_append(ch, &pMcode->code->str);
       return TRUE;
    }

    send_to_char("Syntax: code\n\r",ch);
    return FALSE;
}

MPEDIT( mpedit_list )
{
    int count = 1;
    MPROG_CODE *mprg;
    char buf[MAX_STRING_LENGTH];
    GString *buffer;
    bool fAll = !str_cmp(argument, "all");
    char blah;
    AREA_DATA *ad;

    buffer = g_string_new("");

    for (mprg = mprog_list; mprg !=NULL; mprg = mprg->next)
	if ( fAll || ENTRE(ch->in_room->area->min_vnum, mprg->vnum, ch->in_room->area->max_vnum) )
	{
		ad = get_vnum_area(mprg->vnum);

		if ( ad == NULL )
			blah = '?';
		else
		if ( IS_BUILDER(ch, ad) )
			blah = '*';
		else
			blah = ' ';

		sprintf(buf, "[%3d] (%c) %5d\n\r", count, blah, mprg->vnum );
		buffer = g_string_append(buffer, buf);

		count++;
	}

    if ( count == 1 )
    {
    	if ( fAll )
    		buffer = g_string_append( buffer, "MobProgram does not exist.\n\r" );
    	else
    		buffer = g_string_append( buffer, "MobPrograms do not exist in this area.\n\r" );
    }

    page_to_char(buffer->str, ch);
    g_string_free(buffer,TRUE);

    return FALSE;
}