//::////////////////////////////////////////////// //:: FileName: "inc_epicspells" /* Purpose: This is the #include file that contains all constants and functions needed for the Epic Spellcasting System. */ //::////////////////////////////////////////////// //:: Created By: Boneshank (Don Armstrong) //:: Last Updated On: March 18, 2004 //::////////////////////////////////////////////// /* CONSTANTS FOR OPTIONAL FEATURES */ /* moved to prc_inc_switch as runtime switches rather than compiletime // Use the "XP Costs" option, making casters expend some experience when they // cast certain spells? const int XP_COSTS = TRUE; // Use the "Take 10" variant rule? // If TRUE, all Spellcraft checks will be automatically equal to the caster's // Spellcraft skill level, plus 10. The outcome is never a surprise. // If FALSE, every Spellcraft check is a roll of the dice, being equal to the // caster's Spellcraft skill level, plus 1d20. Risky, but more fun! const int TAKE_TEN_RULE = FALSE; // Use the "Primary Ability Modifier Bonus to Skills" variant rule? // If TRUE, caster's use their primary ability (WISDOM for clerics and druids, // CHARISMA for sorcerers) instead of intelligence as a modifier on their // Spellcraft checks for casting and researching epic spells, as well as // their total Lore skill level for determining spell slots per day. const int PRIMARY_ABILITY_MODIFIER_RULE = TRUE; // Enable BACKLASH damage on spells? TRUE for yes, FALSE for no. const int BACKLASH_DAMAGE = TRUE; // Sets the DC adjustment active or inactive for researching spells. // If TRUE, the player's spell foci feats are used to lower the spell's DC which // lowers the overall costs of researching the spell. For example, if the // spell is from the school of Necromancy, and the player has the feat Epic // Spell Focus: Necromancy, then the DC for the rearch would be lowered by // six. This would (under default ELHB settings) lower the gold cost by // 54000 gold and 2160 exp. points, as well as makee the spell accessible // to the player earlier and with a greater chance of success (due to the // Spellcraft check). // Setting this to FALSE will disable this feature. const int FOCI_ADJUST_DC = TRUE; // This sets the multiplier for the cost, in gold, to a player for the // researching of an epic spell. The number is multiplied by the DC of // the spell to be researched. ELHB default is 9000. const int GOLD_MULTIPLIER = 9000; // This sets the number to divide the gold cost by to determine the cost, // in experience, to research an epic spell. The formula is as follows: // XP Cost = Spell's DC x GOLD_MULTIPLIER / XP_FRACTION. The default from // the ELHB is 25. const int XP_FRACTION = 25; // Set the number you want to divide the gold cost by for research failures. // Examples: 2 would result in half the loss of the researcher's gold. // 3 would result in a third of the gold lost. // 4 would result in a quarter, etc. const int FAILURE_FRACTION_GOLD = 2; // Sets the percentage chance that a seed book is destroyed on a use of it. // 0 = the book is never randomly destroyed from reading (using) it. // 100 = the book is always destroyed from reading it. // NOTE! This function is only ever called when the player actually acquires // the seed feat. It is a way to control mass "gift-giving" amongst players const int BOOK_DESTRUCTION = 50; */ // Play cutscenes for learning Epic Spell Seeds and researching Epic Spells? const int PLAY_RESEARCH_CUTS = FALSE; const int PLAY_SPELLSEED_CUT = FALSE; // What school of magic does each spell belong to? (for research cutscenes) // A = Abjuration // C = Conjuration // D = Divination // E = Enchantment // V = Evocation // I = Illusion // N = Necromancy // T = Transmutation // Between the quotation marks, enter the name of the cutscene script. const string SCHOOL_A = ""; const string SCHOOL_C = ""; const string SCHOOL_D = ""; const string SCHOOL_E = ""; const string SCHOOL_V = ""; const string SCHOOL_I = ""; const string SCHOOL_N = ""; const string SCHOOL_T = ""; const string SPELLSEEDS_CUT = ""; /****************************************************************************** FUNCTION DECLARATIONS ******************************************************************************/ // Returns the combined caster level of oPC. int GetTotalCastingLevel(object oPC); // returns TRUE if oPC is an Epic level Dread Necromancer int GetIsEpicDreadNecromancer(object oPC); // returns TRUE if oPC is an Epic level warmage int GetIsEpicWarmage(object oPC); // returns TRUE if oPC is an Epic level healer. int GetIsEpicHealer(object oPC); // returns TRUE if oPC is an Epic level favored soul. int GetIsEpicFavSoul(object oPC); // Returns TRUE if oPC is an Epic level cleric. int GetIsEpicCleric(object oPC); // Returns TRUE if oPC is an Epic level druid. int GetIsEpicDruid(object oPC); // Returns TRUE if oPC is an Epic level sorcerer. int GetIsEpicSorcerer(object oPC); // Returns TRUE if oPC is an Epic level wizard. int GetIsEpicWizard(object oPC); // returns TRUE if oPC is an epic level shaman. int GetIsEpicShaman(object oPC); // returns TRUE if oPC is an epic level witch. int GetIsEpicWitch(object oPC); // returns TRUE if oPC is an epic level sublime chord. int GetIsEpicSublimeChord(object oPC); // returns TRUE if oPC is an epic level archivist. int GetIsEpicArchivist(object oPC); // returns TRUE if oPC is an epic level beguiler. int GetIsEpicBeguiler(object oPC); // returns TRUE if oPC is an epic level ur-priest. int GetIsEpicUrPriest(object oPC); // returns TRUE if oPC is an epic level blighter. int GetIsEpicBlighter(object oPC); // returns TRUE if oPC is an Epic spellcaster int GetIsEpicSpellcaster(object oPC); // Performs a check on the book to randomly destroy it or not when used. void DoBookDecay(object oBook, object oPC); // Returns oPC's spell slot limit, based on Lore and on optional rules. int GetEpicSpellSlotLimit(object oPC); // Returns the number of remaining unused spell slots for oPC. int GetSpellSlots(object oPC); // Replenishes oPC's Epic spell slots. void ReplenishSlots(object oPC); // Decrements oPC's Epic spell slots by one. void DecrementSpellSlots(object oPC); // Lets oPC know how many Epic spell slots remain for use. void MessageSpellSlots(object oPC); // Returns a Spellcraft check for oPC, based on optional rules. int GetSpellcraftCheck(object oPC); // Returns the Spellcraft skill level of oPC, based on optional rules. int GetSpellcraftSkill(object oPC); // Returns TRUE if oPC has enough gold to research the spell. int GetHasEnoughGoldToResearch(object oPC, int nSpellDC); // Returns TRUE if oPC has enough excess experience to research the spell. int GetHasEnoughExperienceToResearch(object oPC, int nSpellDC); // Returns TRUE if oPC has the passed in required feats (Seeds or other Epic spells)... needs BLAH_IP's int GetHasRequiredFeatsForResearch(object oPC, int nReq1, int nReq2 = 0, int nReq3 = 0, int nReq4 = 0, int nSeed1 = 0, int nSeed2 = 0, int nSeed3 = 0, int nSeed4 = 0, int nSeed5 = 0); // Returns success (TRUE) or failure (FALSE) in oPC's researching of a spell. int GetResearchResult(object oPC, int nSpellDC); // Takes the gold & experience (depending on success) from oPC for researching. void TakeResourcesFromPC(object oPC, int nSpellDC, int nSuccess); // Returns TRUE if oPC can cast the spell. int GetCanCastSpell(object oPC, int nEpicSpell); // Returns the adjusted DC of a spell that takes into account oPC's Spell Foci. int GetDCSchoolFocusAdjustment(object oPC, string sChool); // Checks to see if oPC has a creature hide. If not, create and equip one. void EnsurePCHasSkin(object oPC); // Add nFeatIP to oPC's creature hide. void GiveFeat(object oPC, int nFeatIP); // Remove nFeatIP from oPC's creature hide. void TakeFeat(object oPC, int nFeatIP); // Checks to see how many castable epic spell feats oPC has ready to use. // This is used for the control of the radial menu issue. int GetCastableFeatCount(object oPC); // When a contingency spell is active, oCaster loses the use of one slot per day void PenalizeSpellSlotForCaster(object oCaster); // When a contingecy expires, restore the spell slot for the caster. void RestoreSpellSlotForCaster(object oCaster); // Researches an Epic Spell for the caster. void DoSpellResearch(object oCaster, int nSpellDC, int nSpellIP, string sSchool, object oBook); // Cycles through equipped items on oTarget, and unequips any having nImmunityType void UnequipAnyImmunityItems(object oTarget, int nImmType); // Finds a given spell's DC int GetEpicSpellSaveDC(object oCaster = OBJECT_SELF, object oTarget = OBJECT_INVALID, int nSpellID = -1); int GetHasEpicSpellKnown(int nEpicSpell, object oPC); void SetEpicSpellKnown(int nEpicSpell, object oPC, int nState = TRUE); int GetHasEpicSeedKnown(int nEpicSeed, object oPC); void SetEpicSeedKnown(int nEpicSeed, object oPC, int nState = TRUE); #include "prc_inc_spells" #include "prc_class_const" #include "inc_epicspelldef" #include "inc_epicspellfnc" #include "inc_utility" #include "prc_add_spell_dc" //#include "x2_inc_spellhook" /****************************************************************************** FUNCTION BODIES ******************************************************************************/ int GetIsEpicArchivist(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_ARCHIVIST, oPC, FALSE) > 16 && GetAbilityScore(oPC, ABILITY_INTELLIGENCE) > 18; } int GetIsEpicBeguiler(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_BEGUILER, oPC, FALSE) > 17 && GetAbilityScore(oPC, ABILITY_INTELLIGENCE) > 18; } int GetIsEpicCleric(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_CLERIC, oPC, FALSE) > 16 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicDreadNecromancer(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_DREAD_NECROMANCER, oPC, FALSE) > 17 && GetAbilityScore(oPC, ABILITY_CHARISMA) > 18; } int GetIsEpicDruid(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_DRUID, oPC, FALSE) > 16 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicFavSoul(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_FAVOURED_SOUL, oPC, FALSE) > 17 && GetAbilityScore(oPC, ABILITY_CHARISMA) > 18; } int GetIsEpicHealer(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_HEALER, oPC, FALSE) > 16 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicUrPriest(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_UR_PRIEST, oPC, FALSE) > 8 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicShaman(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_SHAMAN, oPC, FALSE) > 16 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicSorcerer(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_SORCERER, oPC, FALSE) > 17 && GetAbilityScore(oPC, ABILITY_CHARISMA) > 18; } int GetIsEpicSublimeChord(object oPC) { return GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) > 8 && GetAbilityScore(oPC, ABILITY_CHARISMA) > 18; } int GetIsEpicBlighter(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_BLIGHTER, oPC, FALSE) > 8 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicWarmage(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_WARMAGE, oPC, FALSE) > 17 && GetAbilityScore(oPC, ABILITY_CHARISMA) > 18; } int GetIsEpicWitch(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_WITCH, oPC, FALSE) > 17 && GetAbilityScore(oPC, ABILITY_WISDOM) > 18; } int GetIsEpicWizard(object oPC) { return GetPrCAdjustedCasterLevel(CLASS_TYPE_WIZARD, oPC, FALSE) >= 17 && GetAbilityScore(oPC, ABILITY_INTELLIGENCE) > 18; } int GetIsEpicSpellcaster(object oPC) { if(GetHitDice(oPC) < 21) return FALSE; if(GetIsEpicArchivist(oPC) || GetIsEpicBeguiler(oPC) || GetIsEpicCleric(oPC) || GetIsEpicDreadNecromancer(oPC) || GetIsEpicDruid(oPC) || GetIsEpicFavSoul(oPC) || GetIsEpicHealer(oPC) || GetIsEpicUrPriest(oPC) || GetIsEpicShaman(oPC) || GetIsEpicSorcerer(oPC) || GetIsEpicSublimeChord(oPC) || GetIsEpicBlighter(oPC) || GetIsEpicWarmage(oPC) || GetIsEpicWitch(oPC) || GetIsEpicWizard(oPC)) return TRUE; return FALSE; } void DoBookDecay(object oBook, object oPC) { if (d100() >= GetPRCSwitch(PRC_EPIC_BOOK_DESTRUCTION)) { DestroyObject(oBook, 2.0); SendMessageToPC(oPC, MES_BOOK_DESTROYED); } } int GetEpicSpellSlotLimit(object oPC) { int nLimit; int nPen = GetLocalInt(oPC, "nSpellSlotPenalty"); int nBon = GetLocalInt(oPC, "nSpellSlotBonus"); // What's oPC's Lore skill?. nLimit = GetSkillRank(SKILL_LORE, oPC); // Variant rule implementation. if (GetPRCSwitch(PRC_EPIC_PRIMARY_ABILITY_MODIFIER_RULE) == TRUE) { if (GetIsEpicSorcerer(oPC) || GetIsEpicFavSoul(oPC) || GetIsEpicWarmage(oPC) || GetIsEpicDreadNecromancer(oPC)) { nLimit -= GetAbilityModifier(ABILITY_INTELLIGENCE, oPC); nLimit += GetAbilityModifier(ABILITY_CHARISMA, oPC); } else if (GetIsEpicCleric(oPC) || GetIsEpicDruid(oPC) || GetIsEpicHealer(oPC) || GetIsEpicBlighter(oPC) || GetIsEpicShaman(oPC) || GetIsEpicUrPriest(oPC)) { nLimit -= GetAbilityModifier(ABILITY_INTELLIGENCE, oPC); nLimit += GetAbilityModifier(ABILITY_WISDOM, oPC); } } // Primary calculation of slots. nLimit /= 10; // Modified calculation (for contingencies, bonuses, etc) nLimit = nLimit + nBon; nLimit = nLimit - nPen; return nLimit; } int GetSpellSlots(object oPC) { int nSlots = GetLocalInt(oPC, "nEpicSpellSlots"); if(!GetIsPC(oPC) && !GetLocalInt(oPC, "EpicSpellSlotsReplenished")) { nSlots = GetEpicSpellSlotLimit(oPC); SetLocalInt(oPC, "EpicSpellSlotsReplenished", TRUE); SetLocalInt(oPC, "nEpicSpellSlots", nSlots); } return nSlots; } void ReplenishSlots(object oPC) { SetLocalInt(oPC, "nEpicSpellSlots", GetEpicSpellSlotLimit(oPC)); MessageSpellSlots(oPC); } void DecrementSpellSlots(object oPC) { SetLocalInt(oPC, "nEpicSpellSlots", GetLocalInt(oPC, "nEpicSpellSlots")-1); MessageSpellSlots(oPC); } void MessageSpellSlots(object oPC) { SendMessageToPC(oPC, "You now have " + IntToString(GetSpellSlots(oPC)) + " Epic spell slots available."); } int GetHasEpicSpellKnown(int nEpicSpell, object oPC) { int nReturn = GetPersistantLocalInt(oPC, "EpicSpellKnown_"+IntToString(nEpicSpell)); if(!nReturn) nReturn = GetHasFeat(GetResearchFeatForSpell(nEpicSpell), oPC); return nReturn; } void SetEpicSpellKnown(int nEpicSpell, object oPC, int nState = TRUE) { SetPersistantLocalInt(oPC, "EpicSpellKnown_"+IntToString(nEpicSpell), nState); } int GetHasEpicSeedKnown(int nEpicSeed, object oPC) { int nReturn = GetPersistantLocalInt(oPC, "EpicSeedKnown_"+IntToString(nEpicSeed)); if(!nReturn) nReturn = GetHasFeat(GetFeatForSeed(nEpicSeed), oPC); return nReturn; } void SetEpicSeedKnown(int nEpicSeed, object oPC, int nState = TRUE) { SetPersistantLocalInt(oPC, "EpicSeedKnown_"+IntToString(nEpicSeed), nState); } int GetSpellcraftCheck(object oPC) { // Get oPC's skill rank. int nCheck = GetSpellcraftSkill(oPC); // Do the check, dependant on "Take 10" variant rule. if (GetPRCSwitch(PRC_EPIC_TAKE_TEN_RULE) == TRUE) nCheck += 10; else nCheck += d20(); return nCheck; } int GetSpellcraftSkill(object oPC) { // Determine initial Spellcraft skill. int nSkill = GetSkillRank(SKILL_SPELLCRAFT, oPC); // Variant rule implementation. if (GetPRCSwitch(PRC_EPIC_PRIMARY_ABILITY_MODIFIER_RULE) == TRUE) { if (GetIsEpicSorcerer(oPC) || GetIsEpicFavSoul(oPC) || GetIsEpicWarmage(oPC) || GetIsEpicDreadNecromancer(oPC)) { nSkill -= GetAbilityModifier(ABILITY_INTELLIGENCE, oPC); nSkill += GetAbilityModifier(ABILITY_CHARISMA, oPC); } else if (GetIsEpicCleric(oPC) || GetIsEpicDruid(oPC) || GetIsEpicHealer(oPC) || GetIsEpicBlighter(oPC) || GetIsEpicShaman(oPC) || GetIsEpicUrPriest(oPC)) { nSkill -= GetAbilityModifier(ABILITY_INTELLIGENCE, oPC); nSkill += GetAbilityModifier(ABILITY_WISDOM, oPC); } } return nSkill; } int GetHasEnoughGoldToResearch(object oPC, int nSpellDC) { int nCost = nSpellDC * GetPRCSwitch(PRC_EPIC_GOLD_MULTIPLIER); if (GetHasGPToSpend(oPC, nCost)) return TRUE; return FALSE; } int GetHasEnoughExperienceToResearch(object oPC, int nSpellDC) { int nXPCost = nSpellDC * GetPRCSwitch(PRC_EPIC_GOLD_MULTIPLIER) / GetPRCSwitch(PRC_EPIC_XP_FRACTION); if (GetHasXPToSpend(oPC, nXPCost)) return TRUE; return FALSE; } int GetHasRequiredFeatsForResearch(object oPC, int nReq1, int nReq2 = 0, int nReq3 = 0, int nReq4 = 0, int nSeed1 = 0, int nSeed2 = 0, int nSeed3 = 0, int nSeed4 = 0, int nSeed5 = 0) { if(DEBUG) { DoDebug("Requirement #1: " + IntToString(nReq1)); DoDebug("Requirement #2: " + IntToString(nReq2)); DoDebug("Requirement #3: " + IntToString(nReq3)); DoDebug("Requirement #4: " + IntToString(nReq4)); DoDebug("Seed #1: " + IntToString(nSeed1)); DoDebug("Seed #2: " + IntToString(nSeed2)); DoDebug("Seed #3: " + IntToString(nSeed3)); DoDebug("Seed #4: " + IntToString(nSeed4)); DoDebug("Seed #4: " + IntToString(nSeed5)); } if ((GetHasFeat(nReq1, oPC) || nReq1 == 0) && (GetHasFeat(nReq2, oPC) || nReq2 == 0) && (GetHasFeat(nReq3, oPC) || nReq3 == 0) && (GetHasFeat(nReq4, oPC) || nReq4 == 0) && (GetHasEpicSeedKnown(nSeed1, oPC) || nSeed1 == -1) && (GetHasEpicSeedKnown(nSeed2, oPC) || nSeed2 == -1) && (GetHasEpicSeedKnown(nSeed3, oPC) || nSeed3 == -1) && (GetHasEpicSeedKnown(nSeed4, oPC) || nSeed4 == -1) && (GetHasEpicSeedKnown(nSeed5, oPC) || nSeed5 == -1)) { return TRUE; } return FALSE; } int GetResearchResult(object oPC, int nSpellDC) { int nCheck = GetSpellcraftCheck(oPC); SendMessageToPC(oPC, "Your spellcraft check was a " + IntToString(nCheck) + ", against a researching DC of " + IntToString(nSpellDC)); if (nCheck >= nSpellDC) { SendMessageToPC(oPC, MES_SPELLCRAFT_CHECK_PASS); return TRUE; } else { SendMessageToPC(oPC, MES_SPELLCRAFT_CHECK_FAIL); return FALSE; } } void TakeResourcesFromPC(object oPC, int nSpellDC, int nSuccess) { if (nSuccess != TRUE) { int nGold = nSpellDC * GetPRCSwitch(PRC_EPIC_GOLD_MULTIPLIER) / GetPRCSwitch(PRC_EPIC_FAILURE_FRACTION_GOLD); SpendGP(oPC, nGold); } else { int nGold = nSpellDC * GetPRCSwitch(PRC_EPIC_GOLD_MULTIPLIER); SpendGP(oPC, nGold); int nXP = nSpellDC * GetPRCSwitch(PRC_EPIC_GOLD_MULTIPLIER) / GetPRCSwitch(PRC_EPIC_XP_FRACTION); SpendXP(oPC, nXP); } } int GetCanCastSpell(object oPC, int nEpicSpell) { int nSpellDC = GetDCForSpell(nEpicSpell); string sChool = GetSchoolForSpell(nEpicSpell); int nSpellXP =GetCastXPForSpell(nEpicSpell); // Adjust the DC to account for Spell Foci feats. nSpellDC -= GetDCSchoolFocusAdjustment(oPC, sChool); int nCheck = GetSpellcraftCheck(oPC); // Does oPC already know it if (!GetHasEpicSpellKnown(nEpicSpell, oPC)) { return FALSE; } if (!(GetSpellSlots(oPC) >= 1)) { // No? Cancel spell, then. SendMessageToPC(oPC, MES_CANNOT_CAST_SLOTS); return FALSE; } if (GetPRCSwitch(PRC_EPIC_XP_COSTS) == TRUE) { // Does oPC have the needed XP available to cast the spell? if (!GetHasXPToSpend(oPC, nSpellXP)) { // No? Cancel spell, then. SendMessageToPC(oPC, MES_CANNOT_CAST_XP); return FALSE; } } // Does oPC pass the Spellcraft check for the spell's casting? if (!(nCheck >= nSpellDC)) { // No? SendMessageToPC(oPC, MES_SPELLCRAFT_CHECK_FAIL); SendMessageToPC(oPC, IntToString(nCheck) + " against a DC of " + IntToString(nSpellDC)); // Failing a Spellcraft check still costs a spell slot, so decrement... DecrementSpellSlots(oPC); return FALSE; } // If the answer is YES to all three, cast the spell! SendMessageToPC(oPC, MES_SPELLCRAFT_CHECK_PASS); SendMessageToPC(oPC, IntToString(nCheck) + " against a DC of " + IntToString(nSpellDC)); SpendXP(oPC, nSpellXP); // Only spends the XP on a successful casting. DecrementSpellSlots(oPC); return TRUE; } void GiveFeat(object oPC, int nFeatIP) { object oSkin = GetPCSkin(oPC); if (oSkin != OBJECT_INVALID) IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(nFeatIP), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); } void TakeFeat(object oPC, int nFeatIP) { object oSkin = GetPCSkin(oPC); itemproperty ipX = GetFirstItemProperty(oSkin); while (GetIsItemPropertyValid(ipX)) { if (GetItemPropertyType(ipX) == ITEM_PROPERTY_BONUS_FEAT) { if(GetItemPropertySubType(ipX) == nFeatIP) { RemoveItemProperty(oSkin, ipX); break; } } ipX = GetNextItemProperty(oSkin); } } int GetCastableFeatCount(object oPC) { int nX = 0; int i = 0; int nFeat = GetFeatForSpell(i); while(nFeat != 0) { //test for the castable feat if(GetHasFeat(nFeat, oPC)) nX += 1; i++; nFeat = GetFeatForSpell(i); } return nX; } void PenalizeSpellSlotForCaster(object oCaster) { int nMod = GetLocalInt(oCaster, "nSpellSlotPenalty"); SetLocalInt(oCaster, "nSpellSlotPenalty", nMod + 1); SendMessageToPC(oCaster, MES_CONTINGENCIES_YES1); SendMessageToPC(oCaster, MES_CONTINGENCIES_YES2); SendMessageToPC(oCaster, "Your epic spell slot limit is now " + IntToString(GetEpicSpellSlotLimit(oCaster)) + "."); } void RestoreSpellSlotForCaster(object oCaster) { int nMod = GetLocalInt(oCaster, "nSpellSlotPenalty"); if (nMod > 0) SetLocalInt(oCaster, "nSpellSlotPenalty", nMod - 1); SendMessageToPC(oCaster, "Your epic spell slot limit is now " + IntToString(GetEpicSpellSlotLimit(oCaster)) + "."); } void DoSpellResearch(object oCaster, int nSpellDC, int nSpellIP, string sSchool, object oBook) { float fDelay = 2.0; string sCutScript; int nResult = GetResearchResult(oCaster, nSpellDC); if (PLAY_RESEARCH_CUTS == TRUE) { if (sSchool == "A") sCutScript = SCHOOL_A; if (sSchool == "C") sCutScript = SCHOOL_C; if (sSchool == "D") sCutScript = SCHOOL_D; if (sSchool == "E") sCutScript = SCHOOL_E; if (sSchool == "I") sCutScript = SCHOOL_I; if (sSchool == "N") sCutScript = SCHOOL_N; if (sSchool == "T") sCutScript = SCHOOL_T; if (sSchool == "V") sCutScript = SCHOOL_V; ExecuteScript(sCutScript, oCaster); fDelay = 10.0; } DelayCommand(fDelay, TakeResourcesFromPC(oCaster, nSpellDC, nResult)); if (nResult == TRUE) { DelayCommand(fDelay, SendMessageToPC(oCaster, GetName(oCaster) + " " + MES_RESEARCH_SUCCESS)); //DelayCommand(fDelay, GiveFeat(oCaster, nSpellIP)); DelayCommand(fDelay, SetEpicSpellKnown(nSpellIP, oCaster, TRUE)); DelayCommand(fDelay, DestroyObject(oBook)); //research time //1 day per 50,000GP +1 int nDays = (nSpellDC * GetPRCSwitch(PRC_EPIC_GOLD_MULTIPLIER))/50000; nDays++; float fSeconds = HoursToSeconds(24*nDays); AdvanceTimeForPlayer(oCaster, fSeconds); } else { DelayCommand(fDelay, SendMessageToPC(oCaster, GetName(oCaster) + " " + MES_RESEARCH_FAILURE)); } } void UnequipAnyImmunityItems(object oTarget, int nImmType) { object oItem; int nX; for (nX = 0; nX <= 13; nX++) // Does not include creature items in search. { oItem = GetItemInSlot(nX, oTarget); // Debug. //SendMessageToPC(oTarget, "Checking slot " + IntToString(nX)); if (oItem != OBJECT_INVALID) { // Debug. //SendMessageToPC(oTarget, "Valid item."); itemproperty ipX = GetFirstItemProperty(oItem); while (GetIsItemPropertyValid(ipX)) { // Debug. //SendMessageToPC(oTarget, "Valid ip"); if (GetItemPropertySubType(ipX) == nImmType) { // Debug. //SendMessageToPC(oTarget, "ip match!!"); SendMessageToPC(oTarget, GetName(oItem) + " cannot be equipped at this time."); AssignCommand(oTarget, ClearAllActions()); AssignCommand(oTarget, ActionUnequipItem(oItem)); break; } else ipX = GetNextItemProperty(oItem); } } } } int GetTotalCastingLevel(object oCaster) { int iBestArcane = GetLevelByTypeArcaneFeats(); int iBestDivine = GetLevelByTypeDivineFeats(); int iBest = (iBestDivine > iBestArcane) ? iBestDivine : iBestArcane; //SendMessageToPC(oCaster, "Epic casting at level " + IntToString(iBest)); return iBest; } int GetDCSchoolFocusAdjustment(object oPC, string sChool) { int nNewDC = 0; if (sChool == "A") // Abjuration spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_ABJURATION, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_ABJURATION, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_ABJURATION, oPC)) nNewDC = 2; } if (sChool == "C") // Conjuration spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_CONJURATION, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_CONJURATION, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_CONJURATION, oPC)) nNewDC = 2; } if (sChool == "D") // Divination spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_DIVINATION, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_DIVINIATION, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_DIVINATION, oPC)) nNewDC = 2; } if (sChool == "E") // Enchantment spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_ENCHANTMENT, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_ENCHANTMENT, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_ENCHANTMENT, oPC)) nNewDC = 2; } if (sChool == "V") // Evocation spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_EVOCATION, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_EVOCATION, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_EVOCATION, oPC)) nNewDC = 2; } if (sChool == "I") // Illusion spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_ILLUSION, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_ILLUSION, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_ILLUSION, oPC)) nNewDC = 2; } if (sChool == "N") // Necromancy spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_NECROMANCY, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_NECROMANCY, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_NECROMANCY, oPC)) nNewDC = 2; } if (sChool == "T") // Transmutation spell? { if (GetHasFeat(FEAT_EPIC_SPELL_FOCUS_TRANSMUTATION, oPC)) nNewDC = 6; else if (GetHasFeat(FEAT_GREATER_SPELL_FOCUS_TRANSMUTATION, oPC)) nNewDC = 4; else if (GetHasFeat(FEAT_SPELL_FOCUS_TRANSMUTATION, oPC)) nNewDC = 2; } return nNewDC; } int GetEpicSpellSaveDC(object oCaster = OBJECT_SELF, object oTarget = OBJECT_INVALID, int nSpellID = -1) { int iDiv = GetPrCAdjustedCasterLevelByType(TYPE_DIVINE, oCaster); // ie. wisdom determines DC int iWiz = GetPrCAdjustedCasterLevel(CLASS_TYPE_WIZARD, oCaster); // int determines DC int iWMa = GetPrCAdjustedCasterLevel(CLASS_TYPE_WARMAGE, oCaster); // cha determines DC int iDNc = GetPrCAdjustedCasterLevel(CLASS_TYPE_DREAD_NECROMANCER, oCaster); // cha determines DC int iSor = GetPrCAdjustedCasterLevel(CLASS_TYPE_SORCERER, oCaster); // cha determines DC int iWit = GetPrCAdjustedCasterLevel(CLASS_TYPE_WITCH, oCaster); // wis determines DC int iArc = GetPrCAdjustedCasterLevel(CLASS_TYPE_ARCHIVIST, oCaster); // int determines DC int iBeg = GetPrCAdjustedCasterLevel(CLASS_TYPE_BEGUILER, oCaster); // int determines DC int iTpl = GetPrCAdjustedCasterLevel(CLASS_TYPE_TEMPLAR, oCaster); // cha determines DC int iBest = 0; int iAbility; if(nSpellID == -1) nSpellID = PRCGetSpellId(); if (iArc > iBest) { iAbility = ABILITY_INTELLIGENCE; iBest = iWit; } if (iTpl > iBest) { iAbility = ABILITY_CHARISMA; iBest = iTpl; } if (iWiz > iBest) { iAbility = ABILITY_INTELLIGENCE; iBest = iWiz; } if (iWMa > iBest) { iAbility = ABILITY_CHARISMA; iBest = iWMa; } if (iDNc > iBest) { iAbility = ABILITY_CHARISMA; iBest = iDNc; } if (iSor > iBest) { iAbility = ABILITY_CHARISMA; iBest = iSor; } if (iWit > iBest) { iAbility = ABILITY_WISDOM; iBest = iWit; } if (iBeg > iBest) { iAbility = ABILITY_INTELLIGENCE; iBest = iBeg; } if (iDiv > iBest) { iAbility = ABILITY_WISDOM; iBest = iDiv; } int nDC; if (iBest) nDC = 20 + GetAbilityModifier(iAbility, oCaster); else nDC = 20; // DC = 20 if the epic spell is cast some other way. nDC += GetDCSchoolFocusAdjustment(oCaster, Get2DACache("spells", "school", nSpellID)); nDC += GetChangesToSaveDC(oTarget, oCaster, nSpellID, GetSpellSchool(nSpellID)); return nDC; } // Test main //void main(){}