SmaugWizard/Backup/
SmaugWizard/Backup/L/
SmaugWizard/Boards/
SmaugWizard/Building/
SmaugWizard/Corpses/
SmaugWizard/Councils/
SmaugWizard/Deity/
SmaugWizard/Gods/
SmaugWizard/MudProgs/
SmaugWizard/Player/L/
SmaugWizard/Src/
SmaugWizard/Src/res/
/****************************************************************************
 * [S]imulated [M]edieval [A]dventure multi[U]ser [G]ame      |				*
 * -----------------------------------------------------------|   \\._.//	*
 * SmaugWiz (C) 1998 by Russ Pillsbury (Windows NT version)   |   (0...0)	*
 * -----------------------------------------------------------|    ).:.(	*
 * SMAUG (C) 1994, 1995, 1996 by Derek Snider                 |    {o o}	*
 * -----------------------------------------------------------|   / ' ' \	*
 * SMAUG code team: Thoric, Altrag, Blodkai, Narn, Haus,      |~'~.VxvxV.~'~*
 * Scryn, Swordbearer, Rennard, Tricops, and Gorog.           |				*
 * ------------------------------------------------------------------------ *
 * Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael        *
 * Chastain, Michael Quan, and Mitchell Tse.                                *
 * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,          *
 * Michael Seifert, Hans Henrik Staerfeldt, Tom Madsen, and Katja Nyboe.    *
 * ------------------------------------------------------------------------ *
 *			    Skills Interface file										*
 ****************************************************************************/
#ifndef		SKILL_H
#define		SKILL_H

#define		deCurrentSkillVersion		"1000"

#ifdef	SMAUGSERVER_CPP
	char *SpellSaveNames [6] = {
		"none", "poison_death", "wands", "para_petri", "breath",
		"spell_staff" };

	char *SpellSaveEffectNames [8] = {
		"none", "negate", "eightdam", "quarterdam", "halfdam", "3qtrdam",
		"reflect", "absorb" };
#endif
extern	char *SpellSaveNames [6];
extern	char *SpellSaveEffectNames [8];


#define ASSIGN_GSN(gsn, skill)								\
do															\
{															\
    if (((gsn) = SkillTable.Lookup((skill))) == -1 )		\
	fprintf(stderr, "ASSIGN_GSN: Skill %s not found.\n",	\
		(skill) );											\
} while(0)


#define SET_SDAM(skill, val)	((skill)->SetInfo (((skill)->GetInfo() & SDAM_MASK) + ((val) & 7)))
#define SET_SACT(skill, val)	((skill)->SetInfo (((skill)->GetInfo() & SACT_MASK) + (((val) & 7) << 3)))
#define SET_SCLA(skill, val)	((skill)->SetInfo (((skill)->GetInfo() & SCLA_MASK) + (((val) & 7) << 6)))
#define SET_SPOW(skill, val)	((skill)->SetInfo (((skill)->GetInfo() & SPOW_MASK) + (((val) & 3) << 9)))


/* RIS by gsn lookups. -- Altrag.
   Will need to add some || stuff for spells that need a special GSN. */

#define IS_FIRE(dt)		(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsFireSpell ())
#define IS_COLD(dt)		(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsColdSpell ())
#define IS_ACID(dt)		(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsAcidSpell ())
#define IS_ELECTRICITY(dt)	(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsElectricitySpell ())
#define IS_ENERGY(dt)		(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsEnergySpell ())
#define IS_DRAIN(dt)		(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsDrainSpell ())
#define IS_POISON(dt)		(SkillTable.IsValid(dt) &&			     \
				SkillTable.GetSkill (dt)->IsPoisonSpell ())


// Skills include spells as a particular case.
class CSkill {
public:
				CSkill ()
				{ ClearAddrRange (&m_pName, &m_UseRec, sizeof (m_UseRec)); }
				~CSkill ();

	void		Read (FILE* fp);
	void		Write (FILE* fp);

	short		GetType () { return m_Type; }
	void		SetType (short t) { m_Type = t; }
	char		*GetName () { return m_pName; }
	BOOL		HasName () { return m_pName && *m_pName; }
	void		SetName (char* n) { m_pName = n; }
	int			GetFlags () { return m_Flags; }
	void		SetFlags (int f) { m_Flags = f; }
	int			GetValue () { return m_Value; }
	void		SetValue (int v) { m_Value = v; }
	short		GetTarget () { return m_Target; }
	void		SetTarget (short t) { m_Target = t; }
	int			GetInfo () { return m_Info; }
	void		SetInfo (int i) { m_Info = i; }
	short		GetMinimumPosition () { return m_MinPos; }
	void		SetMinimumPosition (short p) { m_MinPos = p; }
	char		GetSaves () { return m_Saves; }
	void		SetSaves (char s) { m_Saves = s; }
	short		GetSlot () { return m_Slot; }
	void		SetSlot (short s) { m_Slot = s; }
	short		GetMinMana () { return m_MinMana; }
	void		SetMinMana (int m) { m_MinMana = m; }
	short		GetRange () { return m_Range; }
	void		SetRange (short r) { m_Range = r; }
	short		GetBeats () { return m_Beats; }
	void		SetBeats (short b) { m_Beats = b; }
	short		GetGuild () { return m_Guild; }
	void		SetGuild (int g) { m_Guild = g; }
	short		GetMinLevel () { return m_MinLevel; }
	void		SetMinLevel (int lev) { m_MinLevel = lev; }

	DO_FUN		*GetSkillFunction () { return m_SkillFun; }
	void		SetSkillFunction (DO_FUN* f) { m_SkillFun = f; }
	SPELL_FUN	*GetSpellFunction () { return m_SpellFun; }
	void		SetSpellFunction (SPELL_FUN* f) { m_SpellFun = f; }
	BOOL		ValidDamageMsg () { return m_pDamMsg && m_pDamMsg[0] != '\0'; }
	char		*GetDamageMsg () { return m_pDamMsg; }
	void		SetDamageMsg (char* m) { m_pDamMsg = m; }
	BOOL		ValidOffMsg () { return m_OffMsg && m_OffMsg[0] != '\0'; }
	char		*GetOffMsg () { return m_OffMsg; }
	void		SetOffMsg (char* m) { m_OffMsg = m; }
	char		*GetHitCharMsg () { return m_HitChar; }
	void		SetHitCharMsg (char* m) { m_HitChar = m; }
	BOOL		ValidHitCharMsg () { return m_HitChar && m_HitChar[0] != '\0'; }
	char		*GetHitVictMsg () { return m_HitVict; }
	void		SetHitVictMsg (char* m) { m_HitVict = m; }
	BOOL		ValidHitVictMsg () { return m_HitVict && m_HitVict[0] != '\0'; }
	char		*GetHitRoomMsg () { return m_HitRoom; }
	void		SetHitRoomMsg (char* m) { m_HitRoom = m; }
	BOOL		ValidHitRoomMsg () { return m_HitRoom && m_HitRoom[0] != '\0'; }
	char		*GetHitDest () { return m_HitDest; }
	void		SetHitDest (char* d) { m_HitDest = d; }
	BOOL		ValidHitDest () { return m_HitDest && m_HitDest[0] != '\0'; }
	char		*GetMissCharMsg () { return m_MissChar; }
	void		SetMissCharMsg (char* m) { m_MissChar = m; }
	BOOL		ValidMissCharMsg () { return m_MissChar && m_MissChar[0] != '\0'; }
	char		*GetMissVictMsg () { return m_MissVict; }
	void		SetMissVictMsg (char* m) { m_MissVict = m; }
	BOOL		ValidMissVictMsg () { return m_MissVict && m_MissVict[0] != '\0'; }
	char		*GetMissRoomMsg () { return m_MissRoom; }
	void		SetMissRoomMsg (char* m) { m_MissRoom = m; }
	BOOL		ValidMissRoomMsg () { return m_MissRoom && m_MissRoom[0] != '\0'; }
	char		*GetDieCharMsg () { return m_DieChar; }
	void		SetDieCharMsg (char* m) { m_DieChar = m; }
	BOOL		ValidDieCharMsg () { return m_DieChar && m_DieChar[0] != '\0'; }
	char		*GetDieVictMsg () { return m_DieVict; }
	void		SetDieVictMsg (char* m) { m_DieVict = m; }
	BOOL		ValidDieVictMsg () { return m_DieVict && m_DieVict[0] != '\0'; }
	char		*GetDieRoomMsg () { return m_DieRoom; }
	void		SetDieRoomMsg (char* m) { m_DieRoom = m; }
	BOOL		ValidDieRoomMsg () { return m_DieRoom && m_DieRoom[0] != '\0'; }
	char		*GetImmuneCharMsg () { return m_ImmChar; }
	void		SetImmuneCharMsg (char* m) { m_ImmChar = m; }
	BOOL		ValidImmuneCharMsg () { return m_ImmChar && m_ImmChar[0] != '\0'; }
	char		*GetImmuneVictMsg () { return m_ImmVict; }
	void		SetImmuneVictMsg (char* m) { m_ImmVict = m; }
	BOOL		ValidImmuneVictMsg () { return m_ImmVict && m_ImmVict[0] != '\0'; }
	char		*GetImmuneRoomMsg () { return m_ImmRoom; }
	void		SetImmuneRoomMsg (char* m) { m_ImmRoom = m; }
	BOOL		ValidImmuneRoomMsg () { return m_ImmRoom && m_ImmRoom[0] != '\0'; }
	char		*GetDiceRoll () { return m_pDice; }
	void		SetDiceRoll (char* d) { m_pDice = d; }
	char		GetDifficulty () { return m_Difficulty; }
	void		SetDifficulty (char d) { m_Difficulty = d; }
	char		GetParticipants () { return m_Participants; }
	void		SetParticipants (char p) { m_Participants = p; }
	char		*GetComponents () { return m_pComponents; }
	void		SetComponents (char* c) { m_pComponents = c; }
	char		*GetTeachers () { return m_pTeachers; }
	BOOL		HasTeachers () { return m_pTeachers && *m_pTeachers; }
	void		SetTeachers (char* t) { m_pTeachers = t; }
	CSmaugAffect *GetAffects () { return m_pAffects; }
	void		SetAffects (CSmaugAffect* aff) { m_pAffects = aff; }
	timerset	GetUseRec () { return m_UseRec; }

	short		GetClassLevel (int cl) { return m_ClassLevel [cl]; }
	void		SetClassLevel (int cl, int lev)
				{ m_ClassLevel.SetAtGrow (cl, lev); }
	short		GetClassAdept (int cl) { return m_ClassAdept [cl]; }
	void		SetClassAdept (int cl, int adp)
				{ m_ClassAdept.SetAtGrow (cl, adp); }

	short		GetRaceLevel (int r)
				{ return r < m_RaceLevel.GetSize () ? m_RaceLevel [r] : 0; }
	void		SetRaceLevel (int r, int lev)
				{ m_RaceLevel.SetAtGrow (r, lev); }
	short		GetRaceAdept (int r)
				{ return r < m_RaceAdept.GetSize () ? m_RaceAdept [r] : 0; }
	void		SetRaceAdept (int r, int adp)
				{ m_RaceAdept.SetAtGrow (r, adp); }

#define SSAV_MASK		(UINT_MAX & ~(BV11 | BV12 | BV13))

	int			GetSaveEffect () { return (m_Info >> 11) & 7; }

	void		SetSaveEffect (int v)
				{ m_Info = (m_Info & SSAV_MASK) + ((v & 7) << 11); }

	const char	*GetSaveName ()
				{ ASSERT (m_Saves < DIM (SpellSaveNames));
				  return SpellSaveNames [m_Saves]; }

	const char	*GetSaveEffectName ()
				{ return SpellSaveEffectNames [(m_Info >> 11) & 7]; }


	BOOL	HasSpell (int bit) { return (m_Flags & bit) != 0; }
	BOOL	IsAreaSpell () { return (m_Flags & SF_AREA) != 0; }
	BOOL	IsObjectSpell () { return (m_Flags & SF_OBJECT) != 0; }
	BOOL	IsCharacterSpell () { return (m_Flags & SF_CHARACTER) != 0; }
	BOOL	IsNoSelf () { return (m_Flags & SF_NOSELF) != 0; }
	BOOL	IsSecret () { return (m_Flags & SF_SECRETSKILL) != 0; }
	BOOL	IsNoScribe () { return (m_Flags & SF_NOSCRIBE) != 0; }
	BOOL	IsNoBrew () { return (m_Flags & SF_NOBREW) != 0; }
	BOOL	IsPkSensitive () { return (m_Flags & SF_PKSENSITIVE) != 0; }
	BOOL	IsAccumulative () { return (m_Flags & SF_ACCUMULATIVE) != 0; }
	BOOL	IsRecastable () { return (m_Flags & SF_RECASTABLE) != 0; }
	BOOL	IsStopOnFail () { return (m_Flags & SF_STOPONFAIL) != 0; }
	BOOL	IsGroupSpell () { return (m_Flags & SF_GROUPSPELL) != 0; }
	BOOL	IsWaterSpell () { return (m_Flags & SF_WATER) != 0; }
	BOOL	IsDistantSpell () { return (m_Flags & SF_DISTANT) != 0; }
	BOOL	IsNoFightSpell () { return (m_Flags & SF_NOFIGHT) != 0; }


//#define SPELL_ACTION(skill)	( ((skill)->info >>  3) & 7 )
	int		GetSpellAction () { return (m_Info >> 3) & 7; }
	BOOL	IsDestroySpell () { return ((m_Info >> 3) & 7) == SA_DESTROY; }
	BOOL	IsCreateSpell () { return ((m_Info >> 3) & 7) == SA_CREATE; }

//#define SPELL_DAMAGE(skill)	( ((skill)->info      ) & 7 )
	int		GetSpellDamage () { return m_Info & 7; }
	BOOL	IsFireSpell () { return (m_Info & 7) == SD_FIRE; }
	BOOL	IsPoisonSpell () { return (m_Info & 7) == SD_POISON; }
	BOOL	IsColdSpell () { return (m_Info & 7) == SD_COLD; }
	BOOL	IsAcidSpell () { return (m_Info & 7) == SD_ACID; }
	BOOL	IsElectricitySpell () { return (m_Info & 7) == SD_ELECTRICITY; }
	BOOL	IsEnergySpell () { return (m_Info & 7) == SD_ENERGY; }
	BOOL	IsDrainSpell () { return (m_Info & 7) == SD_DRAIN; }

//#define SPELL_CLASS(skill)	( ((skill)->info >>  6) & 7 )
	int		GetSpellClass () { return (m_Info >> 6) & 7; }
	BOOL	IsLifeSpell () { return ((m_Info >> 6) & 7) == SC_LIFE; }
	BOOL	IsDeathSpell () { return ((m_Info >> 6) & 7) == SC_DEATH; }
	BOOL	IsIllusionSpell () { return ((m_Info >> 6) & 7) == SC_ILLUSION; }
	BOOL	HasNoSpellClass () { return ((m_Info >> 6) & 7) == SC_NONE; }

//#define SPELL_POWER(skill)	( ((skill)->info >>  9) & 3 )
	int		GetSpellPower () { return (m_Info >> 9) & 3; }

	friend class CSkillTable;

protected:
    char		*m_pName;				// Name of skill
    SPELL_FUN	*m_SpellFun;			// Spell pointer (for spells)
	DO_FUN		*m_SkillFun;			// Skill pointer (for skills)
    short		m_Target;				// Legal targets
    short		m_MinPos;				// Position for caster / user
    short		*pgsn;					// Pointer to associated gsn
    short		m_Slot;					// Slot for #OBJECT loading
    short		m_MinMana;				// Minimum mana used
    short		m_Beats;				// Waiting time after use
	short		m_Range;				// for projectiles
    char		*m_pDamMsg;				// Damage message
    char		*m_OffMsg;				// Wear off message
	short		m_Guild;			// Which guild the skill belongs to
	short		m_MinLevel;			// Minimum level to be able to cast
	short		m_Type;				// Spell/Skill/Weapon/Tongue
	int			m_Info;
	int			m_Flags;			// extra stuff
	char		*m_HitChar;			// Success message to caster
	char		*m_HitVict;			// Success message to victim
	char		*m_HitRoom;			// Success message to room
	char		*m_HitDest;
	char		*m_MissChar;		// Failure message to caster
	char		*m_MissVict;		// Failure message to victim
	char		*m_MissRoom;		// Failure message to room
	char		*m_DieChar;			// Victim death msg to caster
	char		*m_DieVict;			// Victim death msg to victim
	char		*m_DieRoom;			// Victim death msg to room
	char		*m_ImmChar;			// Victim immune msg to caster
	char		*m_ImmVict;			// Victim immune msg to victim
	char		*m_ImmRoom;			// Victim immune msg to room
	char		*m_pDice;			// Dice roll
	int			m_Value;			// Misc value
	char		m_Saves;			// What saving spell applies
	char		m_Difficulty;		// Difficulty of casting/learning
	char		*m_pComponents;		// Spell components, if any
	char		*m_pTeachers;		// Skill requires a special teacher
	char		m_Participants;		// # of required participants
	CSmaugAffect	*m_pAffects;	// Spell affects, if any
	timerset	m_UseRec;			// Usage record

	CWordArray	m_ClassLevel;		// Level needed by class
	CWordArray	m_ClassAdept;		// Max attainable % in this skill
	CWordArray	m_RaceLevel;		// Level needed by race
	CWordArray	m_RaceAdept;		// Max attainable % for this race
};


class CSkillTable {
public:
			CSkillTable (int max)
			{ m_Max = max; m_Top = 0; m_sk = new CSkill* [max];
			  ZeroMemory (m_sk, sizeof (m_sk) * max); }
			~CSkillTable () { delete [] m_sk; }

	CString	GetCurrentVersion () { return deCurrentSkillVersion; }
	void	RemoveAll ();
	BOOL	IsValid (int sn)
			{ return sn >= 0 && sn < m_Max && m_sk [sn] &&
			  m_sk [sn]->m_pName; }

	BOOL	Read (FILE* fp);
	void	Add (CSkill* skill);
	void	Write (FILE* fp, int sn) { m_sk [sn]->Write (fp); }
	void	Sort ();
	int		Lookup (const char *name);
	int		Bsearch (const char *name, int first, int top);
	int		BsearchExact (const char *name, int first, int top);
	int		ChBsearch (CCharacter *ch, const char *name, int first, int top);
	CSkill	*GetSkill (int sn) { return IsValid (sn) ? m_sk [sn] : NULL; }
	CSkill	*GetValidSkill (int sn);
	CSkill	*Find (const char *name) { return GetSkill (Lookup (name)); }

	int		GetCount () { return m_Top; }
	char	*GetName (int sn) { return m_sk [sn]->m_pName; }
	BOOL	HasName (int sn) { return m_sk [sn]->HasName (); }
	short	GetSlot (int sn) { return m_sk [sn]->m_Slot; }
	short	GetType (int sn) { return m_sk [sn]->m_Type; }
	short	GetMinMana (int sn) { return m_sk [sn]->m_MinMana; }
	short	GetClassLevel (int sn, int cl)
			{ return m_sk [sn]->GetClassLevel (cl); }
	short	GetClassAdept (int sn, int cl)
			{ return m_sk [sn]->GetClassAdept (cl); }
	short	GetTarget (int sn) { return m_sk [sn]->m_Target; }
	short	GetMinimumPosition (int sn) { return m_sk [sn]->m_MinPos; }
	short	GetBeats (int sn) { return m_sk [sn]->m_Beats; }
	short	GetGuild (int sn) { return m_sk [sn]->m_Guild; }
	char	GetDifficulty (int sn) { return m_sk [sn]->m_Difficulty; }
	timerset	GetUseRec (int sn) { return m_sk [sn]->GetUseRec (); }

	void	SetClassLevel (int sn, int cl, int lev)
			{ m_sk [sn]->SetClassLevel(cl, lev); }
	void	SetClassAdept (int sn, int cl, int adp)
			{ m_sk [sn]->SetClassAdept(cl, adp); }

	char		*GetTeachers (int sn) { return m_sk [sn]->m_pTeachers; }
	DO_FUN		*GetSkillFunction (int sn) { return m_sk [sn]->m_SkillFun; }
	SPELL_FUN	*GetSpellFunction (int sn) { return m_sk [sn]->m_SpellFun; }

	int		GetSaveEffectFromName (const char* name);

private:
	int		m_Top;			// top Skill loaded
	int		m_Max;
	CSkill	**m_sk;
};

#ifdef	SMAUGSERVER_CPP
	CSkillTable		SkillTable (MAX_SKILL);
	CSkillTable		HerbTable (MAX_HERB);
#else
	extern CSkillTable	SkillTable;
	extern CSkillTable	HerbTable;
#endif

#endif		// SKILL_H