/***************************************************************************
* Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming *
* License by Wizards of the Coast. All comments referring to D20, OGL, *
* and SRD refer to the System Reference Document for the Open Gaming *
* system. Any inclusion of these derivatives must include credit to the *
* Mud20 system, the full and complete Open Gaming LIcense, and credit to *
* the respective authors. See ../doc/srd.txt for more information. *
* *
* Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. *
* *
* MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey *
* *
* 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 St{rfeld, Tom Madsen, and Katje Nyboe. *
***************************************************************************/
/***************************************************************************
* class.c: All class specific functions go here *
***************************************************************************/
#include "mud.h"
struct class_type class_table [MAX_CLASS];
/*
* does a character have a class besides monster levels? - Kregor
*/
bool IS_CLASSED(CHAR_DATA *ch)
{
push_call("IS_CLASS(%p)",ch);
if (!IS_NPC(ch))
{
pop_call();
return TRUE;
}
//if there's no active class, then it's a monster - Kregor
if (ch->class && ch->class < MAX_CLASS)
{
pop_call();
return TRUE;
}
pop_call();
return FALSE;
}
/*
* Return the level of a given class - Kregor 3/28/07
*/
int class_level( CHAR_DATA *ch, int class )
{
int level = 0;
push_call("class_level(%p,%p)",ch,class);
level = ch->mclass[class];
pop_call();
return level;
}
/*
* Is a skill or spell considered a class skill
* for a cleric with domains - Kregor
*/
bool domain_skill( CHAR_DATA *ch, int sn )
{
int dom;
push_call("domain_skill(%p,%p)",ch,sn);
if (!class_level(ch, CLASS_CLERIC))
{
pop_call();
return FALSE;
}
for (dom = 0 ; dom < MAX_DOMAIN ; dom++)
{
if (!has_domain(ch, dom))
continue;
if (is_spell(sn))
{
if (max_spell_circle(ch, CLASS_CLERIC) >= skill_table[sn].domains[dom])
{
pop_call();
return TRUE;
}
}
else if (class_level(ch, CLASS_CLERIC) >= skill_table[sn].domains[dom])
{
pop_call();
return TRUE;
}
}
pop_call();
return FALSE;
}
/*
* Is a skill or spell considered a class skill
* for a sorcerer with a bloodline - Kregor
*/
bool bloodline_skill( CHAR_DATA *ch, int sn )
{
push_call("bloodline_skill(%p,%p)",ch,sn);
if (!class_level(ch, CLASS_SORCERER))
{
pop_call();
return FALSE;
}
if (get_bloodline(ch) > 0)
{
if (is_spell(sn) && max_spell_circle(ch, CLASS_SORCERER) >= skill_table[sn].bloodline[get_bloodline(ch)])
{
pop_call();
return TRUE;
}
if (class_level(ch, CLASS_SORCERER) >= skill_table[sn].bloodline[get_bloodline(ch)])
{
pop_call();
return TRUE;
}
}
pop_call();
return FALSE;
}
/*
* Determines character abilities based on
* class options and automatic feats - Kregor
*/
bool class_ability( CHAR_DATA *ch, int sn )
{
int lev, style, cnt;
push_call("class_ability(%p,%p)",ch,sn);
if ((lev = class_level(ch, CLASS_RANGER)) > 1)
{
if ((style = get_ranger_style(ch)) > 0)
{
// disable ranger abiliies if wearing heavy armor - kregor
if (armor_type_worn(ch) <= ARMOR_MEDIUM && lev >= skill_table[sn].styles[style])
{
pop_call();
return TRUE;
}
}
}
if ((lev = class_level(ch, CLASS_MONK)) > 0)
{
if ((style = get_monk_style(ch)) > 0)
{
// disable monk abilities if wearing armor - Kregor
if (armor_type_worn(ch) <= ARMOR_NONE && lev >= skill_table[sn].styles[style])
{
pop_call();
return TRUE;
}
}
}
if (domain_skill(ch, sn))
{
pop_call();
return TRUE;
}
for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
{
if (sn == gsn_weapon_prof_simple
|| sn == gsn_weapon_prof_martial
|| sn == gsn_weapon_prof_exotic
|| sn == gsn_armor_proficiency_light
|| sn == gsn_armor_proficiency_medium
|| sn == gsn_armor_proficiency_heavy
|| skill_table[sn].skilltype == FSKILL_WEAPON)
{
if (class_level(ch, cnt) >= skill_table[sn].skill_level[cnt])
{
pop_call();
return TRUE;
}
}
if (cnt == CLASS_DRUID && wears_metal(ch, FALSE)) // lose druid abilities if wearing metal
continue;
if (cnt == CLASS_BLACKGUARD && !IS_EVIL(ch)) // non evil blackguards lose abilities
continue;
if (cnt == CLASS_PALADIN && (!IS_GOOD(ch) || !IS_LAWFUL(ch))) // non LG pallys lose abilities
continue;
if (cnt == CLASS_PALADIN && (!IS_NPC(ch) && ch->pcdata->reputation < 9)) // pally reputation matters!
continue;
if (cnt == CLASS_BLACKGUARD && !IS_EVIL(ch)) // non evil blackguards lose abilities
continue;
if (class_level(ch, cnt) >= skill_table[sn].skill_level[cnt])
{
pop_call();
return TRUE;
}
}
pop_call();
return FALSE;
}
/*
* Is a skill a class skill for a character - Kregor
*/
bool class_skill( CHAR_DATA *ch, int sn )
{
int cnt;
push_call("class_skill(%p,%p)",ch,sn);
if (domain_skill(ch, sn))
{
pop_call();
return TRUE;
}
if (bloodline_skill(ch, sn))
{
pop_call();
return TRUE;
}
if (skill_table[sn].skilltype == FSKILL_SKILL
|| skill_table[sn].skilltype == FSKILL_KNOWLEDGE
|| skill_table[sn].skilltype == FSKILL_CRAFT)
{
for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
{
if (class_level(ch, cnt) >= skill_table[sn].skill_level[cnt])
{
pop_call();
return TRUE;
}
}
}
pop_call();
return FALSE;
}
/*
Chaos 10/10/93
Determines which class has highest level in a skill
Return -1 is none, otherwise return class number
*/
int multi( CHAR_DATA *ch, int sn)
{
int cnt, mlv, tst, dom;
push_call("multi(%p,%p)",ch,sn);
mlv = -1;
tst = -1;
if (IS_NPC(ch))
{
if (!IS_CLASSED(ch))
{
pop_call();
return -1;
}
}
for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
{
if (is_spell(sn))
{
if (max_spell_circle(ch, cnt) >= skill_table[sn].skill_level[cnt])
{
if (mlv < class_level(ch, cnt))
{
tst = cnt;
mlv = class_level(ch, cnt);
}
}
if (cnt == CLASS_CLERIC)
{
for (dom = 0 ; dom < MAX_DOMAIN ; dom++)
{
if (has_domain(ch, dom))
{
if (max_spell_circle(ch, CLASS_CLERIC) >= skill_table[sn].domains[dom])
{
if (mlv < class_level(ch, cnt))
{
tst = cnt;
mlv = class_level(ch, cnt);
}
}
}
}
}
}
else
{
if (!IS_NPC(ch) && cnt == CLASS_CLERIC)
{
if (domain_skill(ch, sn))
{
if (mlv < class_level(ch, cnt))
{
tst = cnt;
mlv = class_level(ch, cnt);
}
}
}
if (cnt == CLASS_SORCERER)
{
if (bloodline_skill(ch, sn))
{
if (mlv < class_level(ch, cnt))
{
tst = cnt;
mlv = class_level(ch, cnt);
}
}
}
if (class_level(ch, cnt) >= skill_table[sn].skill_level[cnt])
{
if (mlv < class_level(ch, cnt))
{
tst = cnt;
mlv = class_level(ch, cnt);
}
}
}
}
pop_call();
return(tst);
}
/*
* Returns total of multiclass levels regarding the given skill.
* For use with abilities and such that multiple class levels stack - Kregor
*/
int multi_class_level( CHAR_DATA *ch, int sn)
{
int cnt, mlv;
push_call("multi_class_level(%p,%p)",ch,sn);
mlv = 0;
if (race_skill(ch, sn))
mlv = ch->level;
if (IS_NPC(ch) && !IS_CLASSED(ch))
{
if (ch->learned[sn])
mlv = ch->level;
pop_call();
return(mlv);
}
for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
{
if (class_level(ch, cnt) >= skill_table[sn].skill_level[cnt])
{
mlv += class_level(ch, cnt);
}
}
if (mlv > ch->level)
{
mlv = ch->level;
}
pop_call();
return(mlv);
}
/*
* Like multi_class_level, but only counts the class levels
* above the level of acquisition - Kregor
*/
int multi_skill_level( CHAR_DATA *ch, int sn)
{
int cnt, mlv;
push_call("multi_skill_level(%p,%p)",ch,sn);
mlv = 0;
if (race_skill(ch, sn))
mlv = ch->level;
if (IS_NPC(ch) && !IS_CLASSED(ch))
{
if (ch->learned[sn])
mlv = ch->level;
pop_call();
return(mlv);
}
for (cnt = 0 ; cnt < MAX_CLASS ; cnt++)
{
if (!class_level(ch, cnt))
continue;
if (class_level(ch, cnt) < skill_table[sn].skill_level[cnt])
continue;
mlv += class_level(ch, cnt);
mlv -= skill_table[sn].skill_level[cnt];
}
if (mlv > ch->level)
{
mlv = ch->level;
}
pop_call();
return(mlv);
}