/*************************************************************************** * 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); }