Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
581 lines
22 KiB
Plaintext
581 lines
22 KiB
Plaintext
//:://////////////////////////////////////////////
|
|
//:: Alternate magic system gain evaluation script
|
|
//:: prc_amagsys_gain
|
|
//:://////////////////////////////////////////////
|
|
/** @file
|
|
This file determines if the given character
|
|
has gained new spells / powers / utterances /
|
|
whathaveyou since the last time it was run.
|
|
If so, it starts the relevant selection
|
|
conversations.
|
|
|
|
Add new classes to their respective magic
|
|
user type block, or if such doesn't exist
|
|
yet for the system the class belongs to,
|
|
make a new block for them at the end of main().
|
|
|
|
|
|
@author Ornedan
|
|
@date Created - 2006.12.14
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
|
|
//:: Updated for .35 by Jaysyn 2023/03/11
|
|
|
|
//:://////////////////////////////////////////////
|
|
|
|
#include "inc_dynconv"
|
|
#include "psi_inc_psifunc"
|
|
#include "inc_newspellbook"
|
|
#include "true_inc_trufunc"
|
|
#include "tob_inc_tobfunc"
|
|
#include "shd_inc_shdfunc"
|
|
#include "inv_inc_invfunc"
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function prototypes */
|
|
//////////////////////////////////////////////////
|
|
|
|
void CheckSpellbooks(object oPC);
|
|
void CheckPsionics(object oPC);
|
|
void CheckInvocations(object oPC);
|
|
void CheckToB(object oPC);
|
|
void CheckShadow(object oPC);
|
|
void CheckTruenaming(object oPC);
|
|
int CheckMissingPowers(object oPC, int nClass);
|
|
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel);
|
|
int CheckMissingUtterances(object oPC, int nClass, int nLexicon);
|
|
int CheckMissingManeuvers(object oPC, int nClass);
|
|
int CheckMissingMysteries(object oPC, int nClass);
|
|
int CheckMissingInvocations(object oPC, int nClass);
|
|
void AMSCompatibilityCheck(object oPC);
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function definitions */
|
|
//////////////////////////////////////////////////
|
|
|
|
void main()
|
|
{
|
|
object oPC = OBJECT_SELF;
|
|
|
|
// Sanity checks - Shifted or polymorphed characters may have their hide fucked up, and might be missing access to their hide-feats
|
|
// @todo Shifting probably doesn't do this anymore, could be ditchable - Ornedan, 20061214
|
|
if(GetLocalInt(oPC, "nPCShifted"))
|
|
return;
|
|
effect eTest = GetFirstEffect(oPC);
|
|
while(GetIsEffectValid(eTest))
|
|
{
|
|
if(GetEffectType(eTest) == EFFECT_TYPE_POLYMORPH)
|
|
return;
|
|
eTest = GetNextEffect(oPC);
|
|
}
|
|
|
|
DelayCommand(0.0f, CheckSpellbooks(oPC));
|
|
}
|
|
|
|
// Handle new spellbooks
|
|
void CheckSpellbooks(object oPC)
|
|
{
|
|
if(!GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
|
|
return;
|
|
if(!GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_SUEL_ARCHANAMACH, 1, 5))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_FAVOURED_SOUL, 0, 9))
|
|
return;
|
|
// if(CheckMissingSpells(oPC, CLASS_TYPE_MYSTIC, 0, 9))
|
|
// return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 9))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_DREAD_NECROMANCER, 1, 9))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_HEXBLADE, 1, 4))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 5))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_JUSTICEWW, 1, 4))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_KNIGHT_WEAVE, 1, 6))
|
|
return;
|
|
// if(CheckMissingSpells(oPC, CLASS_TYPE_WITCH, 0, 9))
|
|
// return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_SUBLIME_CHORD, 4, 9))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_ARCHIVIST, 0, 9))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 9))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_HARPER, 1, 3))
|
|
return;
|
|
// if(CheckMissingSpells(oPC, CLASS_TYPE_TEMPLAR, 0, 9))
|
|
// return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_ASSASSIN, 1, 4))
|
|
return;
|
|
if(CheckMissingSpells(oPC, CLASS_TYPE_CELEBRANT_SHARESS, 1, 4))
|
|
return;
|
|
|
|
DelayCommand(0.0f, CheckPsionics(oPC));
|
|
}
|
|
|
|
// Handle psionics
|
|
void CheckPsionics(object oPC)
|
|
{
|
|
if(CheckMissingPowers(oPC, CLASS_TYPE_PSION))
|
|
return;
|
|
if(CheckMissingPowers(oPC, CLASS_TYPE_WILDER))
|
|
return;
|
|
if(CheckMissingPowers(oPC, CLASS_TYPE_PSYWAR))
|
|
return;
|
|
if(CheckMissingPowers(oPC, CLASS_TYPE_PSYCHIC_ROGUE))
|
|
return;
|
|
if(CheckMissingPowers(oPC, CLASS_TYPE_FIST_OF_ZUOKEN))
|
|
return;
|
|
if(CheckMissingPowers(oPC, CLASS_TYPE_WARMIND))
|
|
return;
|
|
//expanded knowledge
|
|
if(CheckMissingPowers(oPC, -1))
|
|
return;
|
|
//epic expanded knowledge
|
|
if(CheckMissingPowers(oPC, -2))
|
|
return;
|
|
|
|
DelayCommand(0.0f, CheckInvocations(oPC));
|
|
}
|
|
|
|
// Handle Invocations
|
|
void CheckInvocations(object oPC)
|
|
{
|
|
if(CheckMissingInvocations(oPC, CLASS_TYPE_DRAGONFIRE_ADEPT))
|
|
return;
|
|
if(CheckMissingInvocations(oPC, CLASS_TYPE_WARLOCK))
|
|
return;
|
|
if(CheckMissingInvocations(oPC, CLASS_TYPE_DRAGON_SHAMAN))
|
|
return;
|
|
//extra invocations
|
|
if(CheckMissingInvocations(oPC, CLASS_TYPE_INVALID))
|
|
return;
|
|
//epic extra invocations
|
|
if(CheckMissingInvocations(oPC, -2))
|
|
return;
|
|
|
|
DelayCommand(0.0f, CheckToB(oPC));
|
|
}
|
|
|
|
// Handle Tome of Battle
|
|
void CheckToB(object oPC)
|
|
{
|
|
if(CheckMissingManeuvers(oPC, CLASS_TYPE_CRUSADER))
|
|
return;
|
|
if(CheckMissingManeuvers(oPC, CLASS_TYPE_SWORDSAGE))
|
|
return;
|
|
if(CheckMissingManeuvers(oPC, CLASS_TYPE_WARBLADE))
|
|
return;
|
|
|
|
DelayCommand(0.0f, CheckShadow(oPC));
|
|
}
|
|
|
|
// Handle Shadowcasting
|
|
void CheckShadow(object oPC)
|
|
{
|
|
if(CheckMissingMysteries(oPC, CLASS_TYPE_SHADOWCASTER))
|
|
return;
|
|
if(CheckMissingMysteries(oPC, CLASS_TYPE_SHADOWSMITH))
|
|
return;
|
|
|
|
DelayCommand(0.0f, CheckTruenaming(oPC));
|
|
}
|
|
|
|
// Handle Truenaming - Three different Lexicons to check
|
|
void CheckTruenaming(object oPC)
|
|
{
|
|
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_EVOLVING_MIND))
|
|
return;
|
|
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_CRAFTED_TOOL))
|
|
return;
|
|
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_PERFECTED_MAP))
|
|
return;
|
|
|
|
if(!GetIsDM(oPC))
|
|
DelayCommand(0.0f, AMSCompatibilityCheck(oPC));
|
|
}
|
|
|
|
int CheckMissingPowers(object oPC, int nClass)
|
|
{
|
|
int nLevel = GetLevelByClass(nClass, oPC);
|
|
if(!nLevel && nClass != -1 && nClass != -2)
|
|
return FALSE;
|
|
else if(nClass == -1 && !GetHasFeat(FEAT_EXPANDED_KNOWLEDGE_1))
|
|
return FALSE;
|
|
else if(nClass == -2 && !GetHasFeat(FEAT_EPIC_EXPANDED_KNOWLEDGE_1))
|
|
return FALSE;
|
|
|
|
int nCurrentPowers = GetPowerCount(oPC, nClass);
|
|
int nMaxPowers = GetMaxPowerCount(oPC, nClass);
|
|
|
|
if(nCurrentPowers < nMaxPowers)
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "nClass", nClass);
|
|
StartDynamicConversation("psi_powconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int CheckMissingInvocations(object oPC, int nClass)
|
|
{
|
|
int nLevel = GetLevelByClass(nClass, oPC);
|
|
if(!nLevel && (nClass == CLASS_TYPE_DRAGONFIRE_ADEPT || nClass == CLASS_TYPE_WARLOCK || nClass == CLASS_TYPE_DRAGON_SHAMAN))
|
|
return FALSE;
|
|
else if(nClass == CLASS_TYPE_INVALID && !GetHasFeat(FEAT_EXTRA_INVOCATION_I))
|
|
return FALSE;
|
|
else if(nClass == -2 && !GetHasFeat(FEAT_EPIC_EXTRA_INVOCATION_I))
|
|
return FALSE;
|
|
|
|
int nCurrentInvocations = GetInvocationCount(oPC, nClass);
|
|
if(DEBUG) DoDebug("Current Invocations: " + IntToString(nCurrentInvocations));
|
|
int nMaxInvocations = GetMaxInvocationCount(oPC, nClass);
|
|
if(DEBUG) DoDebug("Max Invocations: " + IntToString(nMaxInvocations));
|
|
|
|
if(nCurrentInvocations < nMaxInvocations)
|
|
{
|
|
// Mark the class for which the PC is to gain invocations and start the conversation
|
|
SetLocalInt(oPC, "nClass", nClass);
|
|
StartDynamicConversation("inv_invokeconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void AddSpellsForLevel(int nClass, int nLevel)
|
|
{
|
|
object oPC = OBJECT_SELF;
|
|
object oSkin = GetPCSkin(oPC);
|
|
//object oToken = GetHideToken(oPC);
|
|
string sFile = GetFileForClass(nClass);
|
|
string sSpellbook;
|
|
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
|
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
|
sSpellbook = "Spellbook"+IntToString(nClass);
|
|
else
|
|
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(nLevel);
|
|
|
|
// Create spells known persistant array if it is missing
|
|
int nSize = persistant_array_get_size(oPC, sSpellbook);
|
|
if (nSize < 0)
|
|
{
|
|
persistant_array_create(oPC, sSpellbook);
|
|
nSize = 0;
|
|
}
|
|
|
|
//check for learnable spells
|
|
object oToken_Class = GetObjectByTag("SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nLevel));
|
|
int nSpells_Total = persistant_array_get_size(oToken_Class, "Lkup");
|
|
int i;
|
|
for(i = 0; i < nSpells_Total; i++)
|
|
{
|
|
int nSpellbookID = persistant_array_get_int(oToken_Class, "Lkup", i);
|
|
if(Get2DAString(sFile, "AL", nSpellbookID) != "1")
|
|
{
|
|
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
|
nSize++;
|
|
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
|
{
|
|
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
|
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
|
AddSpellUse(oPC, nSpellbookID, nClass, sFile, "NewSpellbookMem_" + IntToString(nClass), nSpellbookType, oSkin, nFeatID, nIPFeatID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
|
{
|
|
int nLevel;
|
|
|
|
//:: Rakshasa cast as sorcerers
|
|
if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC);
|
|
|
|
//:: Aranea cast as sorcerers
|
|
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_SHAPECHANGER, oPC);
|
|
|
|
//::Arkamoi cast as sorcerers
|
|
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
|
|
|
//:: Driders cast as sorcerers
|
|
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_ABERRATION, oPC);
|
|
|
|
//:: Marrutact cast as 6/7 sorcerers
|
|
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
|
|
|
//:: Redspawn Arcaniss cast as 3/4 sorcerers
|
|
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
|
|
|
//:: Gloura cast as bards
|
|
else if(nClass == CLASS_TYPE_BARD && GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
|
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
|
|
|
else
|
|
nLevel = nClass == CLASS_TYPE_SUBLIME_CHORD ? GetLevelByClass(nClass, oPC) : GetSpellslotLevel(nClass, oPC);
|
|
|
|
if (DEBUG) DoDebug("CheckMissingSpells 1 Class: " + IntToString(nClass));
|
|
if (DEBUG) DoDebug("CheckMissingSpells 1 Level: " + IntToString(nLevel));
|
|
|
|
if(!nLevel)
|
|
return FALSE;
|
|
if(nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER)
|
|
{
|
|
if((GetLevelByClass(nClass, oPC) == nLevel) //no PrC
|
|
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oPC) || GetHasFeat(FEAT_DRACONIC_BREATH, oPC))) //no Draconic feats that apply
|
|
return FALSE;
|
|
}
|
|
else if(nClass == CLASS_TYPE_ARCHIVIST)
|
|
{
|
|
int nLastGainLevel = GetPersistantLocalInt(oPC, "LastSpellGainLevel");
|
|
nLevel = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
|
|
|
|
if(nLastGainLevel < nLevel)
|
|
{
|
|
if(nLevel == 1)
|
|
{
|
|
//count the number of available at 1st level spells
|
|
int nSpellsAvailable = 3 + GetAbilityModifier(ABILITY_INTELLIGENCE, oPC);
|
|
SetLocalInt(oPC, "LrnLvlUp", nSpellsAvailable);
|
|
}
|
|
else if(nLevel > 1)
|
|
//add additional 2 spells form cleric list
|
|
SetLocalInt(oPC, "LrnLvlUp", 2);
|
|
|
|
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_ARCHIVIST);
|
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, TRUE, FALSE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
//add cleric spells known for level 0
|
|
else if(persistant_array_get_size(oPC, "Spellbook_Known_"+IntToString(CLASS_TYPE_ARCHIVIST)+"_0") < 5) // TODO: replace with GetSpellKnownCurrentCount
|
|
{
|
|
ActionDoCommand(AddSpellsForLevel(CLASS_TYPE_ARCHIVIST, 0));
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
if (DEBUG) DoDebug("CheckMissingSpells 2 Class: " + IntToString(nClass));
|
|
if (DEBUG) DoDebug("CheckMissingSpells 2 Level: " + IntToString(nLevel));
|
|
|
|
int i;
|
|
for(i = nMinLevel; i <= nMaxLevel; i++)
|
|
{
|
|
int nMaxSpells = GetSpellKnownMaxCount(nLevel, i, nClass, oPC);
|
|
if(nMaxSpells > 0)
|
|
{
|
|
int nCurrentSpells = GetSpellKnownCurrentCount(oPC, i, nClass);
|
|
int nSpellsAvailable = GetSpellUnknownCurrentCount(oPC, i, nClass);
|
|
|
|
if(nCurrentSpells < nMaxSpells && nSpellsAvailable > 0)
|
|
{
|
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS && bKnowsAllClassSpells(nClass))
|
|
{
|
|
ActionDoCommand(AddSpellsForLevel(nClass, i));
|
|
}
|
|
else
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "SpellGainClass", nClass);
|
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
|
SetLocalInt(oPC, "SpellbookMaxSpelllevel", nMaxLevel);
|
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//Advanced Learning check
|
|
nLevel = GetLevelByClass(nClass, oPC);
|
|
int nALSpells = GetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass));
|
|
if(nClass == CLASS_TYPE_BEGUILER && nALSpells < (nLevel+1)/4)//one every 4 levels starting at 3.
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_BEGUILER);
|
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
|
SetLocalInt(oPC, "AdvancedLearning", 1);
|
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
return TRUE;
|
|
}
|
|
else if(nClass == CLASS_TYPE_DREAD_NECROMANCER && nALSpells < nLevel/4)//one every 4 levels
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_DREAD_NECROMANCER);
|
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
|
SetLocalInt(oPC, "AdvancedLearning", 1);
|
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
return TRUE;
|
|
}
|
|
else if(nClass == CLASS_TYPE_WARMAGE)
|
|
{
|
|
if((nLevel >= 40 && nALSpells < 9) ||// :/
|
|
(nLevel >= 36 && nLevel < 40 && nALSpells < 8) ||
|
|
(nLevel >= 32 && nLevel < 36 && nALSpells < 7) ||
|
|
(nLevel >= 28 && nLevel < 32 && nALSpells < 6) ||
|
|
(nLevel >= 24 && nLevel < 28 && nALSpells < 5) ||
|
|
(nLevel >= 16 && nLevel < 24 && nALSpells < 4) ||
|
|
(nLevel >= 11 && nLevel < 16 && nALSpells < 3) ||
|
|
(nLevel >= 6 && nLevel < 11 && nALSpells < 2) ||
|
|
(nLevel >= 3 && nLevel < 6 && nALSpells < 1))
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_WARMAGE);
|
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
|
SetLocalInt(oPC, "AdvancedLearning", 1);
|
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else if(nClass == CLASS_TYPE_NIGHTSTALKER && nALSpells < (nLevel+1)/6)//one every 6 levels starting at 5th
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_NIGHTSTALKER);
|
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
|
SetLocalInt(oPC, "AdvancedLearning", 1);
|
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
int CheckMissingUtterances(object oPC, int nClass, int nLexicon)
|
|
{
|
|
int nLevel = GetLevelByClass(nClass, oPC);
|
|
if(!nLevel)
|
|
return FALSE;
|
|
|
|
int nCurrentUtterances = GetUtteranceCount(oPC, nClass, nLexicon);
|
|
int nMaxUtterances = GetMaxUtteranceCount(oPC, nClass, nLexicon);
|
|
if(DEBUG) DoDebug("CheckMissingUtterances(" + IntToString(nClass) + ", " + IntToString(nLexicon) + ", " + GetName(oPC) + ") = " + IntToString(nCurrentUtterances) + ", " + IntToString(nMaxUtterances));
|
|
|
|
if(nCurrentUtterances < nMaxUtterances)
|
|
{
|
|
// Mark the class for which the PC is to gain Utterances and start the conversation
|
|
SetLocalInt(oPC, "nClass", nClass);
|
|
StartDynamicConversation("true_utterconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int CheckMissingManeuvers(object oPC, int nClass)
|
|
{
|
|
int nLevel = GetLevelByClass(nClass, oPC);
|
|
if(!nLevel)
|
|
return FALSE;
|
|
|
|
int nCurrentManeuvers = GetManeuverCount(oPC, nClass, MANEUVER_TYPE_MANEUVER);
|
|
int nMaxManeuvers = GetMaxManeuverCount(oPC, nClass, MANEUVER_TYPE_MANEUVER);
|
|
int nCurrentStances = GetManeuverCount(oPC, nClass, MANEUVER_TYPE_STANCE);
|
|
int nMaxStances = GetMaxManeuverCount(oPC, nClass, MANEUVER_TYPE_STANCE);
|
|
|
|
if(nCurrentManeuvers < nMaxManeuvers || nCurrentStances < nMaxStances)
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "nClass", nClass);
|
|
StartDynamicConversation("tob_moveconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
int CheckMissingMysteries(object oPC, int nClass)
|
|
{
|
|
int nLevel = GetLevelByClass(nClass, oPC);
|
|
if(!nLevel)
|
|
return FALSE;
|
|
|
|
int nCurrentMysteries = GetMysteryCount(oPC, nClass);
|
|
int nMaxMysteries = GetMaxMysteryCount(oPC, nClass);
|
|
|
|
if(nCurrentMysteries < nMaxMysteries)
|
|
{
|
|
// Mark the class for which the PC is to gain powers and start the conversation
|
|
SetLocalInt(oPC, "nClass", nClass);
|
|
StartDynamicConversation("shd_mystconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
|
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//AMS Compatibility functions - xwarren:
|
|
void CopyAMSArray(object oPC, object oAMSToken, int nClass, string sArray, int nMin, int nMax, int nLoopSize = 100)
|
|
{
|
|
string sFile = GetFileForClass(nClass);
|
|
int i = nMin;
|
|
while(i < nMin + nLoopSize && i < nMax)
|
|
{
|
|
int nSpellbookID = persistant_array_get_int(oPC, sArray, i);
|
|
int nSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
|
if(DEBUG) DoDebug("Copying spell "+IntToString(nSpell));
|
|
array_set_int(oAMSToken, sArray, i, nSpell);
|
|
i++;
|
|
}
|
|
if(i < nMax)
|
|
DelayCommand(0.0, CopyAMSArray(oPC, oAMSToken, nClass, sArray, i, nMax));
|
|
}
|
|
|
|
void DoBuckUpAMS(object oPC, int nClass, string sSpellbook, object oHideToken, object oAMSToken)
|
|
{
|
|
if(DEBUG) DoDebug("Creating buck-up copy of "+sSpellbook);
|
|
if(array_exists(oAMSToken, sSpellbook))
|
|
array_delete(oAMSToken, sSpellbook);
|
|
array_create(oAMSToken, sSpellbook);
|
|
int nSize = persistant_array_get_size(oPC, sSpellbook);
|
|
DelayCommand(0.0, CopyAMSArray(oPC, oAMSToken, nClass, sSpellbook, 0, nSize));
|
|
}
|
|
|
|
void AMSCompatibilityCheck(object oPC)
|
|
{
|
|
//Get an extra hide token with amagsys info
|
|
object oAMSToken = GetHideToken(oPC, TRUE);
|
|
object oHideToken = GetHideToken(oPC); //ebonfowl: no longer used but I'm leaving it to not have to edit other functions
|
|
|
|
int i;
|
|
for(i = 1; i <= 8; i++)
|
|
{
|
|
int nClass = GetClassByPosition(i, oPC);
|
|
string sSpellbook;
|
|
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
|
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
|
{
|
|
sSpellbook = "Spellbook"+IntToString(nClass);
|
|
int nSize1 = persistant_array_get_size(oPC, sSpellbook);
|
|
int nSize2 = array_get_size(oAMSToken, sSpellbook);
|
|
if(nSize1 > nSize2)
|
|
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
|
|
}
|
|
else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
|
|
{
|
|
int j;
|
|
for(j = 0; j <= 9; j++)
|
|
{
|
|
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(j);
|
|
int nSize1 = persistant_array_get_size(oPC, sSpellbook);
|
|
int nSize2 = array_get_size(oAMSToken, sSpellbook);
|
|
if(nSize1 > nSize2)
|
|
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
|
|
}
|
|
}
|
|
}
|
|
} |