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
------------------------------------------------------------------------------
editnpc.cc
*/

#include "config.h"
#include "string.h"
#include "llist.h"
#include "index.h"
#include "room.h"
#include "hash.h"
#include "bit.h"
#include "edit.h"
#include "area.h"
#include "pc.h"
#include "npc.h"
#include "global.h"
#include "trigs.h"

void NPCEditor::command( const String & arg )
{
	String str;
	String str2;
	String arg1;
	String arg2;
	Index index1;
	int val1;
	int i;
	struct TriggerData * td;

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

	if( !npc && !(bool)arg1 )
	{
		pc->out( "No NPC to edit.\n\r" );
		return;
	}
	else if( !area )
		area = pc->inRoom()->getArea();

	if( arg1 == "new" || arg1 == "create" )
	{
		index1 = arg2;
		if( !(bool)index1.getKey() )
		{
			pc->out( "Usage:  new [scope:]<index>\n\r" );
			return;
		}

		if( !(bool)index1.getScope() )
		{
			area = pc->inRoom()->getArea();
			index1.setScope( area->getKey() );
		}
		else
		{
			area = lookupArea( index1.getScope() );
			if( !area )
			{
				pc->out( "No such area(scope) " );
				pc->out( index1.getScope() );
				pc->out( ".\n\r" );
				return;
			}
		}

		if( area->lookupNPC( index1.getKey() ) )
		{
			pc->out( "NPC " );
			pc->out( index1.asString() );
			pc->out( " already exists.\n\r" );
			return;
		}
 	
		setIndex( index1 );
		npc = new NPC;
		npc->setShort( "no short" );
		npc->setLong( "no long" );
		area->addNPC( index1.getKey(), npc );
		pc->out( "New NPC created.\n\r" );
		return;
	}
	else if( arg1 == "list" )
	{
		NPC * pNPC;
		for_each( area->npcIndex, pNPC )
			str.sprintfAdd( "%15s - %s\n\r", area->npcIndex.getKey().chars(),
										pNPC->getShort().chars() );
		pc->out( str );
		return;
	}
	else if( arg1 == "help" || arg1 == "?" )
	{
		pc->view( "../help/medit.hlp" );
		pc->page( "" );
		return;
	}
	else if( arg1 == "save" )
	{
		area->save();
		area->rmDirtyBit();
		pc->out( "Zone saved.\n\r" );
		return;
	}
	else if( arg1 == "npc-bits" )
	{
		pc->view( "../help/npc-bits.hlp" );
		pc->page( "" );
		return;
	}
	else if( arg1 == "sizes" )
	{
		pc->view( "../help/sizes.hlp" );
		pc->page( "" );
		return;
	}
	else if( arg1 == "races" )
	{
		pc->view( "../help/races.hlp" );
		pc->page( "" );
		return;
	}

	if( !npc )
	{
		pc->out( "No NPC to edit.\n\r" );
		return;
	}

	if( !(bool)arg || arg[0] == '\n' )
	{
		// Display NPC and return
		str << "Index: " << getIndex().asString() << "\n\r";
		npc->describeItself( str );
		pc->out( str );
		return;
	}

	if( arg1 == "name" || arg1 == "keywords" )
	{
		npc->setName( arg2 );
		pc->out( "Keywords set.\n\r" );
		return;
	}
	else if( arg1 == "short" )
	{
		npc->setShort( arg2 );
		pc->out( "Short description set.\n\r" );
		return;
	}
	else if( arg1 == "long" )
	{
		npc->setLong( arg2 );
		pc->out( "Long description set.\n\r" );
		return;
	}
	else if( arg1 == "level" )
	{
		if( ( val1 = arg2.asInt() > 0 ) )
		{
			npc->setLevel( arg2.asInt() );
			pc->out( "Level set.\n\r" );
			return;
		}
		pc->out( "Invalid level.\n\r" );
		return;
	}
	else if( arg1 == "hp" )
	{
		npc->setMaxHP( arg2.asInt() );
		pc->out( "Max hit-points set.\n\r" );	
		return;
	}
	else if( arg1 == "mana" )
	{
		npc->setMaxMana( arg2.asInt() );
		pc->out( "Max mana set.\n\r" );	
		return;
	}
	else if( arg1 == "race" )
	{
		if( ( val1 = lookupRace( arg2 ) ) )
		{
			// Set initial stats according to race
			npc->setRace( val1 );
			pc->out( "Race set.\n\r" );
			return;
		}
		pc->out( "No such race.\n\r" );	
		return;
	}
	else if( arg1 == "size" )
	{
		if( ( val1 = lookupSize( arg2 ) ) )
		{
			// Set initial stats according to race
			npc->setSize( val1 );
			pc->out( "Size set.\n\r" );
			return;
		}
		pc->out( "No such size.\n\r" );	
		return;
	}
	else if( arg1 == "sex" )
	{
		if( arg2 == "male" )
			npc->setSex( MALE );
		else if( arg2 == "female" )
			npc->setSex( FEMALE );
		else if( arg2 == "neuter" )
			npc->setSex( NEUTER );
		else return;
		pc->out( "Sex set.\n\r" );
		return;
	}
	else if( arg1 == "str" || arg1 == "strength" )
	{
		npc->setStr( arg2.asInt() );
		pc->out( "Strength set.\n\r" );
		return;
	}
	else if( arg1 == "int" || arg1 == "intelligence" )
	{
		npc->setInt( arg2.asInt() );
		pc->out( "Intelligence set.\n\r" );
		return;
	}
	else if( arg1 == "con" || arg1 == "constitution" )
	{
		npc->setCon( arg2.asInt() );
		pc->out( "Constitution set.\n\r" );
		return;
	}
	else if( arg1 == "chs" || arg1 == "charisma" )
	{
		npc->setCharisma( arg2.asInt() );
		pc->out( "Charisma set.\n\r" );
		return;
	}
	else if( arg1 == "spd" || arg1 == "speed" )
	{
		npc->setSpd( arg2.asInt() );
		pc->out( "Speed set.\n\r" );
		return;
	}
	else if( arg1 == "dex" || arg1 == "dexterity" )
	{
		npc->setDex( arg2.asInt() );
		pc->out( "Dexterity set.\n\r" );
		return;
	}
	else if( arg1 == "wis" || arg1 == "wisdom" )
	{
		npc->setWis( arg2.asInt() );
		pc->out( "Wisdom set.\n\r" );
		return;
	}
	else if( arg1 == "armor" )
	{
		npc->setArmor( arg2.asInt() );
		pc->out( "Armor set.\n\r" );
		return;
	}
	else if ( arg1 == "trigadd" )
	{
		void * fun;

		arg2.startArgs();
		arg1 = arg2.getArg();
		str2 = arg2.getArg();
		
		val1 = lookupBit( ctrig_types, arg1 );
		if ( val1 == 0 )
		{
			pc->out("No such bit.\n\r");
			return;
		}

		fun = lookupCtrig( val1, str2.chars() );
		if ( fun == NULL )
		{
			pc->out("No such function for that type of trigger.\n\r");
			return;
		}

		for_each(npc->triggers, td )
		{
			if ( td->type == val1 )
				break;
		}

		if ( td != NULL )
		{
			pc->out("Replacing old trigger.\n\r");
			npc->removeTrigger(td);
		}

		td = new (struct TriggerData);
		td->type = val1;
		td->fun = fun;
		npc->addTrigger(td);
		pc->out("Trigger added.\n\r");
		return;

	}
	else if ( arg1 == "trigdel" )
	{
		val1 = lookupBit( ctrig_types, arg2 );
		if ( val1 == 0 )
		{
			pc->out("No such bit.\n\r");
			return;
		}

		for_each(npc->triggers, td )
		{
			if ( td->type == val1 )
				break;
		}

		if ( td == NULL )
		{
			pc->out("This npc has no such trigger.\n\r");
			return;
		}

		npc->removeTrigger(td);
		pc->out("Trigger removed.\n\r");
		return;
	}
	else if ( arg1 == "triglist" )
	{
		if ( !(bool)arg2 )
		{
			// list types of triggers
			str << "Trigger types for NPCs " <<endl;
			for ( i=1; ctrig_types[i].name; i++ )
			{
				str << ctrig_types[i].name << endl;
			}
			pc->out(str);
			return;
		}
		else
		{
			// list triggers for given type
			const char * name;
			val1 = lookupBit( ctrig_types, arg2 );
			if ( val1 == 0 )
			{
				pc->out("No such bit.\n\r");
				return;
			}
			str << "Triggers for type " << arg2 << ":" << endl;	
			for ( i = 0; ; i++ )
			{
				name = getCtrigName(val1, i);
				if ( !name )
					break;
				str << name << endl;
			}
			pc->out(str);
			return;
		}
	}

	if( ( val1 = getNPCBit( arg1 ) ) )
	{
		npc->toggleNPCBit( val1 );
		pc->out( "NPC Bit toggled.\n\r" );
		return;
	}
}