Mud20/accounts/
Mud20/accounts/c/
Mud20/accounts/f/
Mud20/accounts/k/
Mud20/accounts/s/
Mud20/accounts/t/
Mud20/area_current/
Mud20/area_current/newareas/
Mud20/bin/
Mud20/clans/
Mud20/gods/
Mud20/old-sources/
Mud20/player/
Mud20/player/a/del/
Mud20/player/b/
Mud20/player/b/bak/
Mud20/player/b/del/
Mud20/player/f/
Mud20/player/f/bak/
Mud20/player/f/del/
Mud20/player/k/
Mud20/player/k/bak/
Mud20/player/k/del/
Mud20/player/k/dmp/
Mud20/player/m/
Mud20/player/m/bak/
Mud20/player/o/
Mud20/player/o/bak/
Mud20/player/p/
Mud20/player/s/
Mud20/player/s/bak/
Mud20/player/s/del/
Mud20/player/t/
Mud20/player/t/del/
Mud20/player/v/
Mud20/public_html/
Mud20/races/
Mud20/skilltables/
__MACOSX/Mud20/accounts/
__MACOSX/Mud20/accounts/c/
__MACOSX/Mud20/accounts/f/
__MACOSX/Mud20/accounts/k/
__MACOSX/Mud20/accounts/s/
__MACOSX/Mud20/area_current/
__MACOSX/Mud20/area_current/core_areas/
__MACOSX/Mud20/area_current/helps/
__MACOSX/Mud20/area_current/newareas/
__MACOSX/Mud20/backups/
__MACOSX/Mud20/bin/
__MACOSX/Mud20/clans/
__MACOSX/Mud20/gods/
__MACOSX/Mud20/log/
__MACOSX/Mud20/old-sources/
__MACOSX/Mud20/player/
__MACOSX/Mud20/player/a/del/
__MACOSX/Mud20/player/b/
__MACOSX/Mud20/player/b/bak/
__MACOSX/Mud20/player/f/
__MACOSX/Mud20/player/f/bak/
__MACOSX/Mud20/player/f/del/
__MACOSX/Mud20/player/k/
__MACOSX/Mud20/player/k/bak/
__MACOSX/Mud20/player/k/del/
__MACOSX/Mud20/player/k/dmp/
__MACOSX/Mud20/player/m/
__MACOSX/Mud20/player/m/bak/
__MACOSX/Mud20/player/o/
__MACOSX/Mud20/player/o/bak/
__MACOSX/Mud20/player/p/
__MACOSX/Mud20/player/s/
__MACOSX/Mud20/player/s/bak/
__MACOSX/Mud20/player/t/del/
__MACOSX/Mud20/player/v/
__MACOSX/Mud20/public_html/
__MACOSX/Mud20/races/
__MACOSX/Mud20/skilltables/
/***************************************************************************
 * 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);
}