/*
....[@@@..[@@@..............[@.................. 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
------------------------------------------------------------------------------
object.h
*/

#ifndef _OBJECT_H
#define _OBJECT_H

#include "thing.h"
#include "streamable.h"


extern const bitType	obj_type_list[];
extern const bitType	obj_bit_list[];
extern const bitType	wear_bit_list[];


const int OBJ_UNUSED		= 0;
const int OBJ_INVISIBLE		= 1;
const int OBJ_HIDDEN		= 2;
const int OBJ_NOTAKE		= 3;
const int OBJ_NODROP		= 4;
const int OBJ_EDIBLE		= 5;
const int OBJ_NOSAVE		= 6;
const int OBJ_GOOD			= 7;
const int OBJ_EVIL			= 8;
const int OBJ_ANTIGOOD		= 9;
const int OBJ_ANTIEVIL		= 10;
const int OBJ_ANTINEUTRAL	= 11;
const int OBJ_MAGIC			= 12;
const int OBJ_GLOW			= 13;
const int OBJ_SANCTUARY		= 14;
const int OBJ_POISONED		= 15;


const int ITEM_UNUSED			= 0;
const int ITEM_TRASH			= 1;
const int ITEM_JEWEL			= 2;
const int ITEM_GOLD				= 3;
const int ITEM_CONTAINER		= 4;
const int ITEM_LIQUID_CONTAINER	= 5;
const int ITEM_ARMOR			= 6;
const int ITEM_CLOTH			= 7;
const int ITEM_WEAPON			= 8;
const int ITEM_CORPSE			= 9;
const int ITEM_ENERGY			= 10;
const int ITEM_MIN_MAGIC		= 100; //--
const int ITEM_WAND				= 100;
const int ITEM_STAFF			= 101;
const int ITEM_ORB				= 102;
const int ITEM_SCROLL			= 103;
const int ITEM_POTION			= 104;
const int ITEM_FOOD				= 105;
const int ITEM_KEY				= 106;
const int ITEM_MAX_MAGIC		= 120; //--


const int WEAR_NONE		= 0; 
const int WEAR_HEAD		= 1;
const int WEAR_FACE		= 2;
const int WEAR_NECK		= 3;
const int WEAR_BACK		= 4;
const int WEAR_BODY		= 5;
const int WEAR_ARMS		= 6;
const int WEAR_WRIST	= 7;
const int WEAR_HANDS	= 8;
const int WEAR_HOLD		= 9; 
const int WEAR_FINGER	= 10;
const int WEAR_WAIST	= 11;
const int WEAR_LEGS		= 12;
const int WEAR_FEET		= 13;
const int WEAR_SHIELD	= 14;
const int WEAR_WIELD	= 15;


// Wear positions  - bitnums correspond to array positions in eq_list[]

const int EQ_UNDEFINED	=	0;
const int EQ_MIN		=	1;
const int EQ_HEAD		=	1;
const int EQ_FACE		=	2;
const int EQ_NECK_1		=	3;
const int EQ_NECK_2		=	4;
const int EQ_BACK		=	5;
const int EQ_BODY		=	6;
const int EQ_ARMS		=	7;
const int EQ_WRIST_L	=	8;
const int EQ_WRIST_R	=	9;
const int EQ_HANDS		=	10;   
const int EQ_HOLD_L		=	11;
const int EQ_HOLD_R		=	12;
const int EQ_FINGER_L	=	13;
const int EQ_FINGER_R	=	14;
const int EQ_WAIST		=	15;
const int EQ_LEGS		=	16;
const int EQ_FEET		=	17;
const int EQ_SHIELD_L	=	18;
const int EQ_SHIELD_R	=	19;
const int EQ_WIELD_L	=	20;
const int EQ_WIELD_R	=	21;
const int EQ_MAX		=	21; 




const int MAX_OBJ_VAL			=	7;
const int MAX_WEAR_BIT_FIELDS	=	1;
const int MAX_OBJ_BIT_FIELDS	=	1;

class Spell;
class Modifier;
class Affect;
class Object;
class Char;

class Object : public Thing, public Streamable 
{
	protected:
		//Index index;
		short obj_type;
		long value [ MAX_OBJ_VAL ];
		unsigned long wear_bits [ MAX_WEAR_BIT_FIELDS ];
		unsigned long obj_bits [ MAX_OBJ_BIT_FIELDS ];
		short wear_pos;
		long cost;
		short timer;
		Object *in_obj;
		Char *in_char;
		Repop *repop;

	public:
		LList<Spell> spells;	// Spell(s) the object may cast. 
		LList<Modifier> mods;	// Magical mods that affect wearer
		LList<Affect> affects;	// Affects on the object itself
		LList<Object> inv;

		Object()
		:	obj_type( 0 ), wear_pos( 0 ), cost( 0 ), timer( -1 ),
			in_obj( 0 ), in_char( 0 ), repop( 0 )
		{
			memset( (void *)value, 0, sizeof( value[0] ) * MAX_OBJ_VAL );
			memset( (void *)wear_bits, 0, sizeof( wear_bits[0] ) * MAX_WEAR_BIT_FIELDS );
			memset( (void *)obj_bits, 0, sizeof( obj_bits[0] ) * MAX_OBJ_BIT_FIELDS );
		}

		// Copy constructor

		Object( const Object &x )
		:	Thing( x ), obj_type( x.obj_type ), wear_pos( 0 ), cost( x.cost ),
			timer( x.timer ), in_obj( 0 ), in_char( 0 ), repop( 0 ),
			spells( x.spells ), mods( x.mods ), affects( x.affects )
		{
			memcpy( (void *)value, (void *)x.value,
					sizeof( value[0] ) * MAX_OBJ_VAL );
			memcpy( (void *)wear_bits, (void * )x.wear_bits,
					sizeof( wear_bits[0] ) * MAX_WEAR_BIT_FIELDS );
			memcpy( (void *)obj_bits, (void *)x.obj_bits,
					sizeof( obj_bits[0] ) * MAX_OBJ_BIT_FIELDS );
		}


		Object( int type )
		:	obj_type( type ),wear_pos(0),cost(0),timer( -1 ),
			in_obj(0),in_char(0),repop(0)
		{
			memset( (void *)wear_bits, 0, sizeof( wear_bits[0] ) * MAX_WEAR_BIT_FIELDS );
			memset( (void *)value, 0, sizeof( value[0] ) * MAX_OBJ_VAL );
			memset( (void *)obj_bits, 0, sizeof( obj_bits[0] ) * MAX_OBJ_BIT_FIELDS );
		}

		Object( int type, const char *n, const char *s, const char *l )
		:	Thing( n, s, l ),
			obj_type( type )
		{
			memset( (void *)wear_bits, 0, sizeof( wear_bits[0] ) * MAX_WEAR_BIT_FIELDS );
			memset( (void *)value, 0, sizeof( value[0] ) * MAX_OBJ_VAL );
			memset( (void *)obj_bits, 0, sizeof( obj_bits[0] ) * MAX_OBJ_BIT_FIELDS );
		}

		virtual ~Object();

		virtual Object * asObj() { return this; }

		virtual void extract();

//		const Index & getIndex() const { return index; }
//		void setIndex( const Index & x ) { index = x; }
//		void setIndexScope( const String & x ) { index.setScope( x ); }
//		void setIndexKey( const String & x ) { index.setKey( x ); }
//		const String getIndexScope() const { return index.getScope(); }
//		const String getIndexKey() const { return index.getKey(); }

		int readFrom( InFile &in );
		int writeTo( OutFile & ) const;
		int readProtoFrom( InFile &in );
		int writeProtoTo( OutFile & ) const;

		void out( const char * ) {}
		void out( const String & ) {}

		void setRepop( Repop * x ) { repop = x; }
		Repop * getRepop() { return repop; }
		void toWorld();
		void fromWorld();
		void toChar( Char * );
		void fromChar();
		void toRoom( Room * );
		void fromRoom();
		void toObj( Object * );
		void fromObj();
		Char *inChar() { return in_char; } 
		Char *carriedBy() { return in_char; }
		Object *inObj() { return in_obj; }
		virtual void addAffect( Affect * ) {} 
		virtual void rmAffect( int ) {} 
		const char *showWearBits();
		int getType();
		const char *typeName();
		void setType( int t );
		bool isWearable();
		int wearBit( int bit );
		int wearPos();
		int worn();
		void setWearPos( int pos );
		void toggleWearBit( int bit );
		void setValue( int x ) { cost = x; }
		int getValue() { return cost; }
		void setCost( int x ) { cost = x; }
		int getCost() { return cost; }
		void setTimer( int x ) { timer = x; }
		int getTimer() { return timer; }
		int tick() { timer--; return timer; }

		// This is an interface specification.
		// Derivative classes simply implement one or more
		// features.
		virtual bool isGold() { return obj_type == ITEM_GOLD; }
		virtual bool isWeapon() { return obj_type == ITEM_WEAPON; }
		virtual bool isContainer() { return obj_type == ITEM_CONTAINER; }
		virtual bool isLiquidContainer() { return obj_type == ITEM_LIQUID_CONTAINER; }
		virtual bool isArmor() { return obj_type == ITEM_ARMOR; }	
		virtual bool isClothing() { return obj_type == ITEM_CLOTH; }	
		virtual bool isFood() { return obj_type == ITEM_FOOD; }	
		virtual bool isCorpse() { return obj_type == ITEM_CORPSE; }
		virtual bool isJewel() { return obj_type == ITEM_JEWEL; }
		virtual bool isScroll() { return obj_type == ITEM_SCROLL; }
		virtual bool isPotion() { return obj_type == ITEM_POTION; }
		virtual bool isWand() { return obj_type == ITEM_WAND; }
		virtual bool isStaff() { return obj_type == ITEM_STAFF; }
		virtual bool isOrb() { return obj_type == ITEM_ORB; }
		virtual bool isKey() { return obj_type == ITEM_KEY; }

		virtual Spell * getSpell1(); // Just for utility
		virtual Spell * getSpell2();
		virtual Spell * getSpell3();
		virtual Spell * getSpell4();

		virtual void cast( Thing * );

		virtual int getWeightCap();
		virtual int getVolCap();
		virtual int getWeightContained();
		virtual int getVolContained();

		// inventory methods
		virtual void addObjInv( Object * );
		virtual Object *getObjInv( const char * );
		virtual Object *getObjInv( const String & );
		virtual void rmObjInv( Object * );
		virtual void resetInv();
		virtual Object * getCurObjInv();
		virtual Object * getNextObjInv();
};

extern const bitType obj_flags[];
#endif