/*
....[@@@..[@@@..............[@.................. 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@falcon.mercer.peachnet.edu 
MUD++ development mailing list    mudpp-list@spice.com
------------------------------------------------------------------------------
magic.cc
*/

#include "string.h"
#include "llist.h"
#include "room.h"
#include "char.h"
#include "affect.h"
#include "spell.h"

int str_cmp( const char *, const char * );


const Spell spell_lookup_table[] =
{
{ "none",			Spell::spell_none,				0			},
{ "giant form",		Spell::spell_giant_form,		TAR_ANY		},
{ "lightning bolt",	Spell::spell_lightning_bolt,	TAR_ANY		},
{ "sanctuary",		Spell::spell_sanctuary,		TAR_ANY		},
{ "", 0, 0 }
};

const Spell * spellNone = &spell_lookup_table[0];

// This function allows things like 'cast detec invi'
// Checks abbreviations for each word instead of whole phrase.
// Returns the remainder of str after matching
// 'cast detect invi Fusion' returns ' Fusion' in remainder 

bool check_abbrev( const char * str, const char * compare,
							char* remainder )
{
	// Needs a little more work
	while( 1 )
	{
		if( *str == ' ' )
			while( *compare && !isspace( *compare ) )
				compare++;

		if( !*compare )
		{
			if( !*str )
				return true;
			else if( !isspace( *str ) )
				return false;
			
			while( *str && isspace( *str ) )
				str++;

			if( !*str )
				return true;

			strcpy( remainder, str );

			return true;
		}

		if( !*str )
			return true;

		if( *str != *compare )
			return false;
		
		str++; compare++;
	}
}


// Single argument lookupSpell is not used for player spell parser.
// Refer to the 2 argument version after this one. This version is used
// by the database loading functions to match spell names to lookup
// when we know the string only contains a name of a spell.
const Spell * lookupSpell( const char * str )
{
	int i;

	if( !*str )
		return &spell_lookup_table[0];

	for( i=1; *spell_lookup_table[ i ].name; i++ )
	{
		if( *spell_lookup_table[ i ].name != *str )
			continue;

		if( !str_cmp( str, spell_lookup_table[ i ].name ) )
			return &spell_lookup_table[ i ];
	}

	return &spell_lookup_table[0];
}


// char * target is a buffer passed to allow the lookup function to parse
// the spell out and return the remainder of the string, most likely
// the target of the spell.
const Spell * lookupSpell( const char * str, char * target )
{
	int i;

	if( !*str )
		return &spell_lookup_table[0];

	// Preliminary
	// Will port my spell parser from Lost Realms later

	for( i=1; *spell_lookup_table[ i ].name; i++ )
	{
		if( *spell_lookup_table[ i ].name != *str )
			continue;

		if( check_abbrev( str, spell_lookup_table[ i ].name, target ) )
			return &spell_lookup_table[ i ];
	}

	return &spell_lookup_table[0];
}



void Spell::spell_none( Thing *, Thing *  ) 
{
}


void Spell::spell_giant_form( Thing *, Thing *target )
{
	if( target->affected( AFF_GIANT ) )
		return;

	Affect * paf = new Affect( this, AFF_GIANT, 10 );
	paf->addMod( MOD_STR, 10 );
	paf->addMod( MOD_HP, 10 );

	target->addAffect( paf );
	target->out( "You feel stronger all of the sudden!\n\r" );
}


void Spell::spell_sanctuary( Thing *, Thing *target )
{
	Char *vict;
	Object *obj;

	if( target->affected( AFF_SANCTUARY ) )
		return;

	Affect * paf = new Affect( this, AFF_SANCTUARY, 10 );
	paf->addMod( MOD_INT, 2 );
	paf->addMod( MOD_HP, 10 );

	if( ( vict = target->asChar() ) )
		obj = 0;
	else
		obj = target->asObj();

	if( vict )
	{
		vict->addAffect( paf );
		vict->out( "You begin to glow...\n\r" );
		vict->inRoom()->outAllCharExcept( vict->getShort(), vict, 0 );
		vict->inRoom()->outAllCharExcept(
					 " begins to glow with a bright light.\n\r", vict, 0 );
	}
}


void Spell::spell_lightning_bolt( Thing *, Thing *target )
{
	Char *vict;
	Object *obj;
	int dam;

	if( ( vict = target->asChar() ) )
		obj = 0;
	else
		obj = target->asObj();

	dam = 10;
	if( vict->affected( AFF_SANCTUARY ) )
	{
		dam /= 2;
	}

	vict->damage( dam, 0 );
}