/****************************************************************************
* [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