#pragma once
#include <iostream>
#include <string>
#include <bitset>

using namespace std;
using std::string;
using std::bitset;

#include "Item.h"
#include "List.h"

#define	maxNameLength	16
const	maxBitArray		= 32;		//bitset restriction...
const	maxNumAvatars	= 10;		//Used with Avatar.dat file system...

enum PC_Races
{
	rDwarf = 0, rElf, rGnome, rHalfElf, rHalfling, rHuman, MAX_pcRACES
};
enum Classes
{
	c0LvlHuman = 0, cWarrior, cPriest, cRogue, cWizard, cCustom, cMAX_CLASSES
};
enum NWPs
{
	nwpAlchemy = 0, nwpAlertness, nwpAnimalTraining, nwpAppraising,										//	4
	nwpBalance, nwpBargain, nwpBeeKeeping, nwpBegging, nwpBlacksmithing, nwpBlindFighting,				//	10
	nwpBoasting, nwpBoating, nwpBoatwright, nwpBodyLang, nwpBowyer, nwpBrewing, nwpBribery,				//	17
	nwpBureaucracy, nwpButcher,																			//	19
	//WP 'Canon' (large guns)
	nwpCamouflage, nwpCarpentry, nwpCandleMaker, nwpCartography, nwpCartwright, nwpChanting,			//	25
	nwpCharioteering, nwpCheeseMaking, nwpClayWorking, nwpClimbing, nwpCloseQuarterFighting,			//	30
	nwpCobbling, nwpCommerce, nwpConcealment, nwpCooking,												//	34
	nwpDairyman, nwpDancing, nwpDangerSense, nwpDiagnostics, nwpDiplomacy, nwpDirectionSense,			//	40
	nwpDisguise, nwpDistanceSense,																		//	42
	nwpEavesdropping, nwpEndurance, nwpEngineering, nwpEtiquette, nwpEvasion,							//	47
	nwpFarming, nwpFieldOfStudy, nwpFireBuilding, nwpFishing, nwpFletcher, nwpForaging, nwpForgery,		//	54
	nwpGaming, nwpGemCutting, nwpHerbalism, nwpHiding, nwpHunting,										//	59
	nwpIntimidation,																					//	60
	nwpJumping,																							//	61
	nwpLangAncient, nwpLangModern, nwpLeadership, nwpLeatherworking, nwpLockPicking, nwpLocksmithing,	//	67
	nwpManipulation, nwpMiller, nwpMining, nwpMusicalInstrument,										//	71
	nwpNavigation, nwpNightsight,																		//	73
	nwpObservation, nwpOrienteering,																	//	75
	nwpPickPockets,																						//	76
	nwpReadWrite, nwpRiding, nwpRopeNetMaking, nwpRunning,												//	80
	nwpSeamanship, nwpSeamstressTailor, nwpSetSnaresAndTraps, nwpShadowing, nwpShepherd,				//	85
	nwpShipwright, nwpSignaling, nwpSinging, nwpSoundAnalysis, nwpSpeedCasting, nwpSpellcraft,			//	91
	nwpStealth, nwpStonemasonry, nwpStreetSense, nwpSurvival, nwpSwimming,								//	96
	nwpTeaching, nwpTightropeWalking, nwpTrapDetect, nwpTumbling,										//	100
	nwpVetHealing, nwpVentriloquism,																	//	102
	nwpWaterDivine, nwpWeaving, nwpWineMaking,															//	105
	MAX_NWPs
};
enum WeaponProficiencies
{
	wpArquebus = 0, wpAwlPike, wpAxeBattle, 
	wpBardiche, wpBecDeCorbin, wpBillGuisarme, wpBlowgun, wpBowCompLong, wpBowCompShort, wpBowLong, wpBowShort,  
	wpClub, wpCrossbowHand, wpCrossbowHeavy, wpCrossbowLight, 
	wpDagger, wpDart, wpDirk,  
	wpFauchard, wpFauchardFork, wpFlailFoot, wpFlailHorse, wpFlintLocks,
	wpGlaiveGuisarme, wpGuisarme, wpGuisarmeVoulge, 
	wpHalberd, wpHookFauchard, 
	wpJavelin,
	wpKhopesh, wpKnife, 
	wpLanceHvy, wpLanceLgt, wpLanceMed, wpLucernHammer, 
	wpMaceFoot, wpMaceHorse, wpMancatcher, wpMilitaryFork, wpMorningStar, 
	wpPartisan, wpPickFoot, wpPickHorse, 
	wpQuarterstaff, 
	wpRansuer,
	wpScourge, wpSickle, wpSpectum, wpSling, wpSpear, wpStaffSling,
	wpSwordBastard, wpSwordBroad, wpSwordLong, wpSwordScimitar, wpSwordShort, wpSwordTwoHanded, 
	wpTrident, 
	wpVoulge, 
	wpWarhammer, wpWhip, 
	MAX_WEAPONPRO
};
enum CmbtVals
{
	cmbtRace = 0, cmbtCombatValue, cmbtSaveValue, cmbtHDLevel, cmbtArmorAllowed, cmbtWeaponsAllowed, cmbtHPAfter9th, cmbtTOTAL_CmbtValues
};
enum OptVals
{
	FighterCon = 0, FighterExStr, AnimalEmp, BonusHitCreature, ReadLang, AuraOfPro, Backstab, CastAnyPriest, 
	ClimbWalls, FindRemove, HealAsPal, HearNoise, HideShadows, AnyMageSpell, MoveSilent, OpenLocks, PickPockets,
	FollowAsWarrior, FollowAsCleric, FollowAsThief, FollowAsMage,
	TOTAL_OptVals
};
enum Restrict
{
	CantKeepMuch = 0, MustDonate, NonHuman9, NonHuman12, HasEthos, Cant10Magic, 
	Cant6Magic, CantClass, CantAlign, TOTAL_Restricts
};
const int noKit = 0;
enum WarriorKits
{
	//FIGHTER
	warAmazon = noKit + 1, 
	warBarbarian, 
	warBeastRider, 
	warBerserker, 
	warCavalier, 
	warGladiator, 
	warMyrmidon, 
	warNobleWarrior, 
	warPeasantHero, 
	warPirate, 
	warOutlaw, 
	warSamurai, 
	warSavage, 
	warSwashbuckler, 
	warWildernessWarrior,
	
	//PALADIN
	palPaladin,
	palChevalier,
	palDivinate,
	palEnvoy,
	palEquerry,
	palErrant,
	palExpatriate, 
	palGhosthunter,
	palInquisitor,
	palMedician,
	palMilitarist,
	palSkyrider,
	palSquire, 
	palVotary, 
	palWyrmslayer,
	
	//RANGER
	ranBeastmaster,
	ranExplorer,
	ranFalconer,
	ranFeralan,
	ranForestRunner,
	ranGiantKiller, 
	ranGreenwoodRanger,
	ranGuardian,
	ranJustifier,
	ranMountainMan,
	ranPathfinder, 
	ranSeaRanger,
	ranSeeker,
	ranStalker,
	ranWarden,
	MAX_warKits
};
enum PriestKits
{
	//PRIEST
	priAmazonPriestess = MAX_warKits,
	priBarbarian,
	priBerserker,
	priFightingMonk,
	priNobleman,
	priOutlaw, 
	priPacifist,
	priPeasant,
	priProphet,
	priSavage,
	priScholar,

	//DRUID
	druAdviser,
	druAvenger,
	druBeastfriend,
	druGuardian,
	druHivemaster,
	druLost, 
	druNaturalPhilosopher,
	druOutlaw,
	druPacifist,
	druSavage,
	druShapeshifter,
	druTotemic, 
	druVillage,
	druWanderer,
	MAX_priKits
};
enum RogueKits
{
	//ROGUE
	rogAcrobat = MAX_priKits,
	rogAdventurer,
	rogAssassin,
	rogBandit,
	rogBeggar,
	rogBountyHunter, 
	rogBuccaneer,
	rogBurglar,
	rogCutpurse,
	rogFence,
	rogInvestigator,
	rogScout, 
	rogSmuggler,
	rogSpy,
	rogSwashbuckler,
	rogSwindler,
	rogThug,
	rogTroubleshooter,

	//BARD
	barTrueBard,
	barBlade,
	barCharlatan,
	barGallant,
	barGypsy,
	barHerald,
	barJester, 
	barJongleur,
	barLoremaster,
	barMeistersinger,
	barRiddlemaster,
	barSkald,
	barThespian,

	//NINJA
	ninStealerIn,
	ninShadowWarrior,
	ninIntruder,
	ninConsort,
	ninPathfinder,
	ninLoneWolf, 
	ninSpiritWarrior,
	ninSpy,
	MAX_rogKits
};
enum WizardKits
{
	//WIZARD
	wizAcademician = MAX_rogKits,
	wizAmazonSorceress,
	wizAnagakok,
	wizMilitantWizard,
	wizMystic, 
	wizPatrician,
	wizPeasant,
	wizSavage,
	wizWitch,
	wizWuJen,
	MAX_wizKits
};
//This const has to be at the tail end of the kit enums...
const int kitsMaxKits = MAX_wizKits;
enum AvatarStatuses
{
	asNewAv = 0, asMultiClass, 
	asMAX
};
const bool ClassesAllowed[cMAX_CLASSES][MAX_pcRACES] =
{	//Dwarf  Elf   Gnome  HaElf HaLin  Human
	{ true,  true, true,  true, true,  true },	//0-lvl
	{ true,  true, true,  true, true,  true },	//Warrior
	{ true,  true, false, true, true,  true },	//Priest
	{ true,  true, true,  true, true,  true },	//Rogue
	{ false, true, true,  true, false, true },	//Mage
	{ true,  true, true,  true, true,  true }	//Special
};
const bool WeaponsAllowed[MAX_WEAPONPRO][cMAX_CLASSES] =
{	//0-lvl	Warrior	Priest	Rogue	Wizard	Custom
	{ true,	true,	false,	false,	false,	true }, //	wpArquebus
	{ true,	true,	false,	false,	false,	true }, //	wpAwlPike
	{ true,	true,	false,	false,	false,	true }, //	wpAxeBattle
	{ true,	true,	false,	false,	false,	true }, //	wpBardiche
	{ true,	true,	false,	false,	false,	true }, //	wpBecDeCorbin
	{ true,	true,	false,	false,	false,	true }, //	wpBillGuisarme
	{ true,	true,	false,	false,	false,	true }, //	wpBlowgun
	{ true,	true,	false,	false,	false,	true }, //	wpBowCompLong
	{ true,	true,	false,	false,	false,	true }, //	wpBowCompShort
	{ true,	true,	false,	false,	false,	true }, //	wpBowLong
	{ true,	true,	false,	true,	false,	true }, //	wpBowShort
	{ true,	true,	true,	true,	false,	true }, //	wpClub
	{ true,	true,	false,	true,	false,	true }, //	wpCrossbowHand
	{ true,	true,	false,	false,	false,	true }, //	wpCrossbowHeavy
	{ true,	true,	false,	false,	false,	true }, //	wpCrossbowLight
	{ true,	true,	false,	true,	true,	true }, //	wpDagger
	{ true,	true,	false,	true,	true,	true }, //	wpDart
	{ true,	true,	false,	true,	true,	true }, //	wpDirk
	{ true,	true,	false,	false,	false,	true }, //	wpFauchard
	{ true,	true,	false,	false,	false,	true }, //	wpFauchardFork
	{ true,	true,	true,	false,	false,	true }, //	wpFlailFoot
	{ true,	true,	true,	false,	false,	true }, //	wpFlailHorse
	{ true,	true,	false,	false,	false,	true }, //	wpFlintLocks
	{ true,	true,	false,	false,	false,	true }, //	wpGlaiveGuisarme
	{ true,	true,	false,	false,	false,	true }, //	wpGuisarme
	{ true,	true,	false,	false,	false,	true }, //	wpGuisarmeVoulge
	{ true,	true,	false,	false,	false,	true }, //	wpHalberd
	{ true,	true,	false,	false,	false,	true }, //	wpHookFauchard
	{ true,	true,	false,	false,	false,	true }, //	wpJavelin
	{ true,	true,	false,	false,	false,	true }, //	wpKhopesh
	{ true,	true,	false,	true,	true,	true }, //	wpKnife
	{ true,	true,	false,	false,	false,	true }, //	wpLanceHvy
	{ true,	true,	false,	false,	false,	true }, //	wpLanceLgt
	{ true,	true,	false,	false,	false,	true }, //	wpLanceMed
	{ true,	true,	true,	false,	false,	true }, //	wpLucernHammer
	{ true,	true,	true,	false,	false,	true }, //	wpMaceFoot
	{ true,	true,	true,	false,	false,	true }, //	wpMaceHorse
	{ true,	true,	false,	true,	false,	true }, //	wpMancatcher
	{ true,	true,	false,	false,	false,	true }, //	wpMilitaryFork
	{ true,	true,	true,	false,	false,	true }, //	wpMorningStar
	{ true,	true,	false,	false,	false,	true }, //	wpPartisan
	{ true,	true,	false,	false,	false,	true }, //	wpPickFoot
	{ true,	true,	false,	false,	false,	true }, //	wpPickHorse
	{ true,	true,	true,	true,	true,	true }, //	wpQuarterstaff
	{ true,	true,	false,	false,	false,	true }, //	wpRansuer
	{ true,	true,	false,	false,	false,	true }, //	wpScourge
	{ true,	true,	false,	false,	false,	true }, //	wpSickle
	{ true,	true,	false,	false,	false,	true }, //	wpSpectum
	{ true,	true,	true,	true,	true,	true }, //	wpSling
	{ true,	true,	false,	false,	false,	true }, //	wpSpear
	{ true,	true,	true,	true,	false,	true }, //	wpStaffSling
	{ true,	true,	false,	false,	false,	true }, //	wpSwordBastard
	{ true,	true,	false,	true,	false,	true }, //	wpSwordBroad
	{ true,	true,	false,	true,	false,	true }, //	wpSwordLong
	{ true,	true,	false,	false,	false,	true }, //	wpSwordScimitar
	{ true,	true,	false,	true,	false,	true }, //	wpSwordShort
	{ true,	true,	false,	false,	false,	true }, //	wpSwordTwoHanded
	{ true,	true,	false,	false,	false,	true }, //	wpTrident
	{ true,	true,	false,	false,	false,	true }, //	wpVoulge
	{ true,	true,	true,	false,	false,	true }, //	wpWarhammer
	{ true,	true,	false,	true,	false,	true }	//	wpWhip
};
class Avatar
{
public:
	Avatar();
	~Avatar();
	void		Reset				();
	const		Avatar&	operator=	(const Avatar &other);
	const		Avatar*	operator=	(const Avatar *other);
	void		Copy				(Avatar other);

	//Names------------------------------------------------------------------
	void		SetLName			(string LName);
	void		SetMName			(string MName);
	void		SetFName			(string FName);
	string		GetLName			() const;
	string		GetFName			() const;
	string		GetMName			() const;

	//Alignment--------------------------------------------------------------
	void		SetAlign			(int Law, int Good);
	string		GetAlign			() const;

	//Sex/Race/Height/Weight-------------------------------------------------
	void		SetSex				(int data);
	int			GetSex				() const;
	void		SetRace				(int data);
	int			GetRace				() const;
	string		GetRaceStr			(int data) const;
	void		SetHeight			(int data);
	int			GetHeight			() const;
	void		SetRandomHeight		();
	void		SetWeight			(int data);
	int			GetWeight			() const;
	void		SetRandomWeight		();

	//Class------------------------------------------------------------------
	void		SetClass			(int d);
	int			GetClass			(int i) const;
	string		GetClassStr			(int i) const;
	string		GetClassNam			(int i) const;
	void		SetNumClass			(int i);
	int			GetNumClass			() const;

	//Class Kits-------------------------------------------------------------
	void		SetKit				(int i, int data);
	int			GetKit				(int i) const;
	string		GetKitStr			(int i) const;
	string		GetKitNam			(int i) const;
	void		SetNumKit			(int i);
	int			GetNumKit			() const;

	//Stats------------------------------------------------------------------
	void		SetSStr				(int data);
	int			GetSStr				() const;
	void		SetStrE				(int data);
	int			GetStrE				() const;
	void		SetSDex				(int data);
	int			GetSDex				() const;
	void		SetSCon				(int data);
	int			GetSCon				() const;
	void		SetSInt				(int data);
	int			GetSInt				() const;
	void		SetSWis				(int data);
	int			GetSWis				() const;
	void		SetSCha				(int data);
	int			GetSCha				() const;
	void		SetSCom				(int data);
	int			GetSCom				() const;

	void		ResetStartingStats	();
	
	void		SetAStr				(float data);
	float		GetAStr				() const;
	void		SetADex				(float data);
	float		GetADex				() const;
	void		SetACon				(float data);
	float		GetACon				() const;
	void		SetAInt				(float data);
	float		GetAInt				() const;
	void		SetAWis				(float data);
	float		GetAWis				() const;
	void		SetACha				(float data);
	float		GetACha				() const;
	void		SetACom				(float data);
	float		GetACom				() const;

	void		CheckStatsByRace	();

	//Custom Character Class methods
	void		SetCmbtValue		(int Index, double Data);
	double		GetCmbtValue		(int Index) const;
	int			GetCustomCmbtValue	() const;

	double		GetTotalMult		() const;

	void		SetOptionalAbil		(int Index, bool Data);
	void		ReverseOptional		(int Index);
	bool		GetOptionalAbil		(int Index) const;
	string		GetOptTF			(int Index) const;

	void		SetRestriction		(int Index, bool Data);
	void		ReverseRestrict		(int Index);
	bool		GetRestriction		(int Index) const;
	string		GetResTF			(int Index) const;

	void		SetSaveAsClass		(int data);
	int			GetSaveAsClass		() const;

	void		calTotalMult		();
	void		ResetCustom			();

	//Weapon proficiencies...
	void		AssignNumWeaPros	();
	int			GetNumMaxWPslots	() const;
	int			GetNumWPsUsed		() const;
	void		CalcWPsSlots		();
	void		AssignWeaponSlot	(int index, int data);
	int			GetWPSlotCost		(int i) const;
	string		GetWProName			(int i) const;
	void		ResetWPs			();

	//Non-weapon Proficiencies...
	void		AssignNumNWPs		();
	int			GetNumMaxNWPslots	() const;
	int			GetNumNWPSAllocated	() const;
	void		CalNWPslots			();
	void		AssignNWPSlot		(int index, int data);
	int			GetNWPnumSlotsAll	(int index) const;
	void		ResetNWPs			();
	string		GetNWPStr			(int index);

	void		SetID				(int index);
	int			GetID				() const;

	void		SetWorldX			(int x);
	int			GetWorldX			() const;

	void		SetWorldY			(int y);
	int			GetWorldY			() const;

	void		SetWorldZ			(int z);
	int			GetWorldZ			() const;

	void		SetDungeonX			(int x);
	int			GetDungeonX			() const;
	void		SetDungeonY			(int y);
	int			GetDungeonY			() const;
	void		SetDungeonZ			(int z);
	int			GetDungeonZ			() const;

	void		Action				(string Action, int maxWorldX, int maxWorldY, int maxWorldZ);

	void		SetFacing			(int direction);
	int			GetFacing			() const;

	void		SetStatus			(int index, bool data);
	bool		GetStatus			(int index) const;

private:
	//Names...
	char	LastName[maxNameLength], FirsName[maxNameLength], MiddName[maxNameLength];

	//Attributes...
	float	aStr, aDex, aCon, aInt, aWis, aCha, aCom;			//(A)djusted values after modifications
	int		sStr, sExStr, sDex, sCon, sInt, sWis, sCha, sCom;	//(S)tarting Stats at creation - limited
	int		Sex, Race, Height, Weight, numClasses, numKits;

	int		alignGood, alignLawful;

	//Class and Kits...
	int		avClass[4];
	int		classLvl[4];
	int		avKit[4];
	int		avClassXP[4];

	//Custom Class Variables
	double	CombatValues[cmbtTOTAL_CmbtValues];					//Required Basics
	double	TotalMult;											//Multiplier for final experience point tally
	int		SaveAsClass;
	bool	OptionalAbilities[TOTAL_OptVals];					//Optional Abilities
	bool	Restrictions[TOTAL_Restricts];						//Optional Restrictions

	//Weapon proficiencies...
	int		MaxWeaponSlots;
	int		numWPs;
	int		weaponPros[MAX_WEAPONPRO];

	//Non-weapon Proficiencies...
	int		MaxNWPSlots;
	int		AllocatedNWPs;
	int		nwp[MAX_NWPs];

	//Unique Identifier
	int		ID_Num;

	//Location information...
	int		worldX;			//World map X coordinate - also value to point at dungeon datafile...
	int		worldY;			//World map Y coordinate - also value to point at dungeon datafile...
	int		worldZ;
	int		dungeonX;
	int		dungeonY;
	int		dungeonZ;

	int		facing;

	bitset<maxBitArray> Statuses;
};

/*
Alignment Range Values
Lawful  > 66		Good    > 66
Nuetral > 33		Nuetral > 33
Choatic				Evil
*/