mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net 
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
pc_olc.cc
*/

#include "config.h"
#include "string.h"
#include "llist.h"
#include "room.h"
#include "repop.h"
#include "hash.h"
#include "server.h"
#include "repop.h"
#include "area.h"
#include "bit.h"
#include "edit.h"
#include "pc.h"
#include "help.h"
#include "global.h"

int saveAreaList();


bool PC::checkSecurity()
{
	if( !in_room )
		return false;
	else if( security > in_room->getArea()->getSecurity() )
		return false;
	return true;
}


void PC::quitEditor()
{
	if( editor )
	{
		delete editor;
		editor = 0;
	}

	out( "Editor done.\n\r" );
}


int saveAreaList();

void PC::do_aedit( const String & arg )
{
	String arg1;
	String arg2;

	if( !arg )
	{
		editor = new AreaEditor( this );
		editor->setArea( in_room->getArea() );
		editor->command( "" );
		return;
	}
	else
	{
		Area * area;
		arg.startArgs();
		arg1 = arg.getArg();	
		if( arg1 == "create" || arg1 == "new" )
		{
			arg2 = arg.getArg();
			if( !(bool)arg2 )
			{
				out( "You must give an index for new area.\n\r" );
				return;
			}

			if( lookupArea( arg2 ) )
			{
				out( "An area with that index already exists.\n\r" );
				return;
			}

			area = new Area;
			area->setKey( arg2 );
			arg2 += ".are";
			area->setFile( arg2 );
			editor = new AreaEditor( this );
			editor->setArea( area );
			out( "New area created.\n\r" );
			areas.add( area );
			area->save();
			saveAreaList();
			return;
		}
		else
		{
			area = lookupArea( arg1 );
			if( !area )
			{
				out( "No such area.\n\r" );
				return;
			}

			if( area->getSecurity() < security )
			{
				out( "That area is out of your security range.\n\r" );
				return;
			}

			editor = new AreaEditor( this );
			editor->setArea( area );
			editor->command( "" );
			return;
		}
	}
}


void PC::do_oedit( const String & arg )
{
	String arg1;
	String arg2;
	String arg3;
	Index index;
	Area * pArea;
	Object * pObj;
	int type;

	if( !(bool)arg )
	{
		editor = new ObjectEditor( this );
		editor->command( "" );
		return;
	}

	arg.startArgs();
	arg1 = arg.getArg();
	arg2 = arg.getArg();
	arg3 = arg.getArgRest();
	if( arg1 == "new" || arg1 == "create" )
	{
		if( !(bool)arg2 || !(bool)arg3 )
		{
			out( "Usage:    oedit { create | new } <type> <index>\n\r" );
			return;
		}

		type = lookupObjType( arg2 );
		if ( !type )
		{
			out ("Wrong item type.\n\r");
			return;
		}

		index = arg3;
		if( index.getScope() )
		{
			if( !( pArea = lookupArea( index.getScope() ) ) )
			{
				out( "No such area.\n\r" );
				return;
			}
		}
		else pArea = inRoom()->getArea();

		if( ( pObj = pArea->lookupObj( index.getKey() ) ) )
		{
			out( "That object already exists.\n\r" );
			return;
		}

		pObj = Object::createObject(type);
		pObj->setShort( "no short desc" );
		pObj->setLong( "no long desc" );
		pArea->addObj( index.getKey(), pObj );
	}
	else
	{
		index = arg1;
		if( !(bool)index.getScope() )
			pArea = inRoom()->getArea();
		else if( !( pArea = lookupArea( index.getScope() ) ) )
		{
			out( "No such zone.\n\r" );
			return;
		}

		if( !( pObj = pArea->lookupObj( index.getKey() ) ) )
		{
			out( "No such Object in that zone.\n\r" );
			return;
		}
	}

	editor = new ObjectEditor( this );
	editor->setIndex( index );
	editor->setArea( pArea );
	((ObjectEditor*)editor)->setObj( pObj );
	editor->command( "" );
	return;
}


void PC::do_medit( const String & arg )
{
	String arg1;
	String arg2;
	Index index;
	NPC * pNPC;
	Area * pArea;

	if( !(bool)arg )
	{
		editor = new NPCEditor( this );
		editor->command( "" );
		return;
	}

	arg.startArgs();
	arg1 = arg.getArg();
	arg2 = arg.getArgRest();
	if( arg1 == "new" || arg1 == "create" )
	{
		if( !(bool)arg2 )
		{
			out( "Usage:    medit { create | new } <index>\n\r" );
			return;
		}

		index = arg2;
		if( index.getScope() )
		{
			if( !( pArea = lookupArea( index.getScope() ) ) )
			{
				out( "No such area.\n\r" );
				return;
			}
		}
		else pArea = inRoom()->getArea();

		if( ( pNPC = pArea->lookupNPC( index.getKey() ) ) )
		{
			out( "That NPC already exists.\n\r" );
			return;
		}

		pNPC = new NPC;
		pNPC->setShort( "no short desc" );
		pNPC->setLong( "no long desc" );
		pArea->addNPC( index.getKey(), pNPC );
	}
	else
	{
		index = arg1;
		if( !(bool)index.getScope() )
			pArea = inRoom()->getArea();
		else if( !( pArea = lookupArea( index.getScope() ) ) )
		{
			out( "No such zone.\n\r" );
			return;
		}

		if( !( pNPC = pArea->lookupNPC( index.getKey() ) ) )
		{
			out( "No such NPC in that zone.\n\r" );
			return;
		}
	}

	editor = new NPCEditor( this );
	editor->setIndex( index );
	editor->setArea( pArea );
	((NPCEditor*)editor)->setNPC( pNPC );
	editor->command( "" );
	return;
}


void PC::do_redit( const String & arg )
{
	Index index;
	Area *pArea;
	Room *pRoom;

	if( !(bool)arg )
	{
		editor = new RoomEditor( this );
		((RoomEditor*)editor)->setRoom( inRoom() );
		editor->command( "" );
		return;
	}

	arg.startArgs();
	String arg1 = arg.getArg();
	String arg2 = arg.getArg();

	if( arg1 == "new" || arg1 == "create" )
	{
		if( !(bool)arg2 )
		{
			out( "No index specified for new room.\n\r" );
			return;
		}
		else
		{
			index = arg2;
			if( !(bool)index.getKey() )
			{
				out( "Room index must contain an index key.\n\r" );
				return;
			}
			else if( index.getScope() )
			{
				if( !( pArea = lookupArea( index.getScope() ) ) )
				{
					out( "No such area.\n\r" );
					return;
				}
			}
			else pArea = in_room->getArea();

			if( ( pRoom = pArea->lookupRoom( index.getKey() ) ) )
			{
				out( "A room already exists with that index.\n\r" );
				return;
			}

			pRoom = new Room( pArea, index.getKey() );
			pArea->addRoom( pRoom );
			editor = new RoomEditor( this );
			((RoomEditor*)editor)->setRoom( pRoom );
			editor->command( "" );
		}
		return;
	}

	// Now find a command so see if it is a room index
	index = arg1;
	if( index.getScope() )
	{
		if( !( pArea = lookupArea( index.getScope() ) ) )
		{
			out( "No such area " );
			out( index.getScope() );
			out( "\n\r" );
			return;
		}
		else if( !( pRoom = pArea->lookupRoom( index.getKey() ) ) )
		{
			out( "No such room " );
			out( index.asString() );
			out( " in area " );
			out( index.getScope() );
			out( "\n\r" );
			return;
		} 
	
		editor = new RoomEditor( this );
		((RoomEditor*)editor)->setRoom( pRoom );
		editor->command( "" );
		return;	
	}
	else
	{
		if( !( pRoom = inRoom()->getArea()->lookupRoom( index.getKey() ) ) )
		{
			out( "No such room in this area.\n\r" );
			return;
		} 

		editor = new RoomEditor( this );
		((RoomEditor*)editor)->setRoom( pRoom );
		editor->command( "" );
		return;
	}	
}

void PC::do_hedit( const String & arg )
{
	Help * help;

	if ( !(bool)arg )
	{
		editor = new HelpEditor(this);
		editor->command("");
		return;
	}
	else
	{
		// or hashtable ?
		for_each(helps_ll, help)
		{
			if ( help->isName(arg) )
				break;
		}

		if ( help )
		{
			editor = new HelpEditor(this);
			((HelpEditor*)editor)->setHelp(help);
			editor->command("");
			return;
		}
		else
		{
			help = new Help();
			help->setName(arg);
			help->setFileName( String("change.me.filename") );
			editor = new HelpEditor(this);
			((HelpEditor*)editor)->setHelp(help);
			Help::add(help);
			editor->command("");
			return;
		}
	}
}


void PC::do_mload( const String & arg )
{
	Index index( arg );
	const NPC *prototype;

	// Check for scope, if not provide default scope
	// Default to the area we are standing in, if not
	// resolved then clear the area field and look for global

	if( !(bool)index.getScope() )
	{
		index.setScope( in_room->getArea()->getKey() );
		if( !( prototype = lookupNPC( index ) ) )
			index.setScope( "" );
	}

	if( !( prototype = lookupNPC( index ) ) )
	{
		out( "No such mobile.\n\r" );
		return;
	}

	NPC * pNPC = new NPC( *prototype );
	pNPC->toWorld();

	// Add a hit attack to the npc's list.
	// Bare handed is 1 to size squared ( human = 3 * 3 ) for max dam
	pNPC->addAttack( CLAW, 1, pNPC->getSize() * pNPC->getSize() );
	in_room->addCharInv( pNPC );
	String str;
	str << "Mobile '" << pNPC->getShort() << "' loaded.\n\r";
	out( str );
	str.clr();
	str << name << " has created " << pNPC->getShort() << "\n\r";
	in_room->outAllCharExcept( str, this, 0 );
}


void PC::do_oload( const String & arg )
{
	Index index( arg );
	const Object * prototype;

	// Check for scope, if not provide default scope
	// Default to the area we are standing in, if not
	// resolved then clear the area field and look for global

	if( !(bool)index.getScope() )
	{
		index.setScope( in_room->getArea()->getKey() );
		if( !( prototype = lookupObj( index ) ) )
			index.setScope( "" );
	}

	if( !( prototype = lookupObj( index ) ) )
	{
		out( "No such object.\n\r" );
		return;
	}

	Object * pObj = prototype->clone();
	pObj->toWorld();
	inRoom()->addObjInv( pObj );

	String str;
	str << "Object '" << pObj->getShort() << "' loaded.\n\r";
	out( str );
	str.clr();
	str << name << " has created " << pObj->getShort() << "\n\r";
	in_room->outAllCharExcept( str, this, 0 );
}


void PC::do_repops( const String & arg )
{
	Repop *repop;
	String str;
	int i = 1;

	if( arg == "list" )
	{
		in_room->repops.reset();
		while( ( repop = in_room->repops.peek() ) )
		{
			str << '[' << i++ << "] " << repop->type << " " << repop->index.asString();
			if( repop->getPtr() )
				str << " -> " << repop->getPtr()->getShort();
			str << "\n\r";
			in_room->repops.next();
		}

		out( str );	
	}
	else if( arg == "room" )
	{
		in_room->repop();
		out( "Room reset.\n\r" );		
	}
	else if( arg == "area" )
	{
		in_room->getArea()->repop();
		out( "Area reset.\n\r" );
	}
	else if( arg == "world" )
	{
		LList<Area> tList = areas;
		Area *area;
		tList.reset();
		while( ( area = tList.peek() ) )
		{
			tList.next();
			area->repop();
		}
	}
	else
	{
		out( "Usage:    repop  { list | room | area | world }\n\r" );
		return;
	}
}


void saveHelps();
void saveGuilds();
void savePersistentData();

// we have to make more accurate functions
void PC::do_dbsave( const String & )
{
	LList<Area> tList = areas;
	Area *area;
	tList.reset();
	while( ( area = tList.peek() ) )
	{
		tList.next();
		area->save();
	}
	saveAreaList();
	saveHelps();
	saveGuilds();
	savePersistentData();
	out( "Zone database saved.\n\r" );
}