Updated AMS marker feats. Removed arcane & divine marker feats. Updated Dread Necromancer for epic progression. Updated weapon baseitem models. Updated new weapons for crafting & npc equip. Updated prefix. Updated release archive.
1171 lines
49 KiB
Plaintext
1171 lines
49 KiB
Plaintext
//::///////////////////////////////////////////////
|
||
//:: Name New Spellbooks spell learning conversation
|
||
//:: FileName prc_s_spellgain.nss
|
||
//:://////////////////////////////////////////////
|
||
/**
|
||
New spellbooks spell learning conversation.
|
||
To be called after a level up event.
|
||
Allows to learn new spells, and to unlearn spells
|
||
Each conversation instance is tied to some class's spellbook
|
||
|
||
so far only relevant for spontaneous casters, because the prepared
|
||
caster classes provided by the PRC know all spells of their class spellbook
|
||
|
||
Author: ?
|
||
Created: ?
|
||
*/
|
||
|
||
//:://////////////////////////////////////////////
|
||
//:://////////////////////////////////////////////
|
||
|
||
|
||
/**
|
||
modified on Apr 2008 by motu99
|
||
added choices to unlearn spells for spont casters, added switches for Bioware or PnP unlearning
|
||
*/
|
||
|
||
/**
|
||
PnP rules for unlearning spells:
|
||
|
||
Sorcerer:
|
||
Upon reaching 4th level, and at every even-numbered sorcerer level
|
||
after that (6th, 8th, and so on), a sorcerer can choose to learn a
|
||
new spell in place of one he already knows. In effect, the
|
||
sorcerer “loses” the old spell in exchange for the new one.
|
||
The new spell’s level must be the same as that of the spell
|
||
being exchanged, and it must be at least two levels lower than
|
||
the highest-level sorcerer spell the sorcerer can cast. A
|
||
sorcerer may swap only a single spell at any given level, and
|
||
must choose whether or not to swap the spell at the same time
|
||
that he gains new spells known for the level.
|
||
|
||
Bard:
|
||
Upon reaching 5th level, and at every third bard level after that
|
||
(8th, 11th, and so on), a bard can choose to learn a new spell in
|
||
place of one he already knows. In effect, the bard “loses” the
|
||
old spell in exchange for the new one. The new spell’s level must be
|
||
the same as that of the spell being exchanged, and it must be at least
|
||
two levels lower than the highest-level bard spell the bard can cast.
|
||
A bard may swap only a single spell at any given level, and must choose
|
||
whether or not to swap the spell at the same time that he gains new spells
|
||
known for the level.
|
||
|
||
Favored Soul:
|
||
Upon reaching 4th level, and at every even-numbered
|
||
favored soul level after that (6th, 8th, and so on), a favored
|
||
soul can choose to learn a new spell in place of one she
|
||
already knows. In effect, the favored soul “loses” the old
|
||
spell in exchange for the new one. The new spell’s level
|
||
must be the same as that of the spell being exchanged, and
|
||
it must be at least two levels lower than the highest-level
|
||
favored soul spell the favored soul can cast. A favored soul
|
||
may swap only a single spell at any given level, and must
|
||
choose whether or not to swap the spell at the same time
|
||
that she gains new spells known for the level.
|
||
|
||
Warmage:
|
||
When a warmage gains access to a
|
||
new level of spells, he automatically knows all the spells for
|
||
that level listed on the warmage’s spell list. Essentially, his
|
||
spell list is the same as his spells known list. Warmages also
|
||
have the option of adding to their existing spell list through
|
||
their advanced learning ability as they increase in level (see
|
||
below). See page 90 for the warmage’s spell list.
|
||
|
||
Advanced Learning (Ex): At 3rd, 6th, 11th, and 16th
|
||
level, a warmage can add a new spell to his list, representing
|
||
the result of personal study and experimentation. The spell
|
||
must be a wizard spell of the evocation school, and of a level
|
||
no higher than that of the highest-level spell the warmage
|
||
already knows. Once a new spell is selected, it is forever added
|
||
to that warmage’s spell list and can be cast just like any other
|
||
spell on the warmage’s list.
|
||
|
||
Hexblade:
|
||
Upon reaching 12th level, and at every third hexblade level
|
||
after that (15th and 18th), a hexblade can choose to learn a new spell in place of one he
|
||
already knows. In effect, the hexblade “loses” the
|
||
old spell in exchange for the new one. The new spell’s
|
||
level must be the same as that of the spell being exchanged,
|
||
and it must be at least two levels lower than the highest-level
|
||
hexblade spell the hexblade can cast. For instance, upon
|
||
reaching 12th level, a hexblade could trade in a single 1st-
|
||
level spell (two spell levels below the highest-level hexblade
|
||
spell he can cast, which is 3rd) for a different 1st-level spell.
|
||
At 15th level, he could trade in a single 1st-level or 2nd-level
|
||
spell (since he now can cast 4th-level hexblade spells) for a
|
||
different spell of the same level. A hexblade may swap only
|
||
a single spell at any given level, and must choose whether or
|
||
not to swap the spell at the same time that he gains new spells
|
||
known for the level.
|
||
Through 3rd level, a hexblade has no caster level. At 4th
|
||
level and higher, his caster level is one-half his hexblade
|
||
|
||
Duskblade:
|
||
Upon reaching 5th level, and at every odd-numbered
|
||
Duskblade level after that (7th, 9th, and so on), a Duskblade
|
||
can choose to learn a new spell in place of one she
|
||
already knows. In effect, the Duskblade “loses” the old
|
||
spell in exchange for the new one. The new spell’s level
|
||
must be the same as that of the spell being exchanged, and
|
||
it must be at least two levels lower than the highest-level
|
||
Duskblade spell the Duskblade can cast. A Duskblade
|
||
may swap only a single spell at any given level, and must
|
||
choose whether or not to swap the spell at the same time
|
||
that she gains new spells known for the level.
|
||
|
||
Suel Archanamach:
|
||
He has access to any spell of the
|
||
abjuration, divination, illusion, and transmutation schools
|
||
on the sorcerer/wizard spell list. He casts spells just as a
|
||
sorcerer does, including the ability to replace a known Suel
|
||
arcanamach spell with a new spell at every even-numbered
|
||
class level beginning at 4th
|
||
*/
|
||
|
||
#include "prc_inc_function"
|
||
#include "inc_dynconv"
|
||
#include "inc_newspellbook"
|
||
#include "inc_sp_gain_mem"
|
||
#include "x3_inc_string"
|
||
|
||
//////////////////////////////////////////////////
|
||
/* Constant definitions */
|
||
//////////////////////////////////////////////////
|
||
|
||
const int STAGE_UNLEARN_CHOICE = 0;
|
||
const int STAGE_SELECT_UNLEARN_LEVEL = 1;
|
||
const int STAGE_SELECT_UNLEARN_SPELL = 2;
|
||
const int STAGE_CONFIRM_UNLEARN = 3;
|
||
const int STAGE_SELECT_LEVEL = 4;
|
||
const int STAGE_SELECT_SPELL = 5;
|
||
const int STAGE_CONFIRM = 6;
|
||
const int STAGE_CONFIRM_ALL = 7;
|
||
const int STAGE_ADVLEARN_LEVEL = 8;
|
||
const int STAGE_ADVLEARN_SPELL = 9;
|
||
const int STAGE_ADVLEARN_CONFIRM = 10;
|
||
|
||
const int STRREF_SELECTED_HEADER1 = 16824209; // "You have selected:"
|
||
const int STRREF_SELECTED_HEADER2 = 16824210; // "Is this correct?"
|
||
const int STRREF_END_CONVO_SELECT = 16824212; // "Finish"
|
||
const int LEVEL_STRREF_START = 16824809;
|
||
const int STRREF_YES = 4752; // "Yes"
|
||
const int STRREF_NO = 4753; // "No"
|
||
const int CHOICE_RETURN_TO_PREVIOUS = 0xEFFFFFFF;
|
||
|
||
const string SPELLGAIN_CONV_CLASS = "SpellGainClass";
|
||
const string SPELLGAIN_CONV_LEVEL = "SelectedLevel";
|
||
const string SPELLGAIN_CONV_SPELL = "SelectedSpell";
|
||
const string SPELLGAIN_CONV_UNLEARN_LEVEL = "UnlrnLvl"; // maximum spell level that can be unlearned at level up
|
||
const string SPELLGAIN_CONV_UNLEARN_COUNT = "UnlrnCnt"; // max nr of spells that can be unlearned at level up
|
||
const string SPELLGAIN_CONV_LEARN_LEVELUP = "LrnLvlUp"; // prep casters: nr of new spells to be learned at level up
|
||
|
||
|
||
//////////////////////////////////////////////////
|
||
/* Aid functions */
|
||
//////////////////////////////////////////////////
|
||
|
||
// all spells known by a (spont) caster are stored in one single array, with no differentiation for spell level
|
||
// Here we need to determine the spells known at specific spell levels. This requires a pass over the whole array.
|
||
// For efficiency we determine the spells known for ALL spell levels and cache the result
|
||
const string SPELLS_KNOWN_CACHE = "SKCCCache";
|
||
|
||
void DeleteSKCCCache(object oPC)
|
||
{
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "0");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "1");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "2");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "3");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "4");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "5");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "6");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "7");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "8");
|
||
DeleteLocalInt(oPC, SPELLS_KNOWN_CACHE + "9");
|
||
}
|
||
|
||
// caches the nr of spells that oPC currently knows at the different spell levels
|
||
void CacheSpellsKnown(int nClass, object oPC)
|
||
{
|
||
// Loop over all spells known and count the number of spells of each level known
|
||
int nKnown0, nKnown1, nKnown2, nKnown3, nKnown4;
|
||
int nKnown5, nKnown6, nKnown7, nKnown8, nKnown9;
|
||
|
||
// persistant storage of spellbook on the hide
|
||
//object oToken = GetHideToken(oPC);
|
||
string sSpellbook = GetSpellsKnown_Array(nClass);
|
||
int nSpellsKnown_AllLevels = persistant_array_get_size(oPC, sSpellbook);
|
||
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
int i;
|
||
for(i = 0; i < nSpellsKnown_AllLevels; i++)
|
||
{
|
||
int nSpellbookID = persistant_array_get_int(oPC, sSpellbook, i);
|
||
int nSpellLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookID));
|
||
switch(nSpellLevel)
|
||
{
|
||
case 0: nKnown0++; break; case 1: nKnown1++; break;
|
||
case 2: nKnown2++; break; case 3: nKnown3++; break;
|
||
case 4: nKnown4++; break; case 5: nKnown5++; break;
|
||
case 6: nKnown6++; break; case 7: nKnown7++; break;
|
||
case 8: nKnown8++; break; case 9: nKnown9++; break;
|
||
}
|
||
}
|
||
|
||
// Cache the values (one higher)
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "0", ++nKnown0);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "1", ++nKnown1);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "2", ++nKnown2);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "3", ++nKnown3);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "4", ++nKnown4);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "5", ++nKnown5);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "6", ++nKnown6);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "7", ++nKnown7);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "8", ++nKnown8);
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + "9", ++nKnown9);
|
||
}
|
||
|
||
// updates the cached values of spells known for nSpellLevel
|
||
int UpdateSpellsKnown(int nClass, int nSpellLevel, object oPC)
|
||
{
|
||
// persistant storage of spellbook on the hide
|
||
//object oToken = GetHideToken(oPC);
|
||
string sSpellbook = GetSpellsKnown_Array(nClass);
|
||
int nSpellsKnown_AllLevels = persistant_array_get_size(oPC, sSpellbook);
|
||
|
||
int nKnown;
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
int i;
|
||
for(i = 0; i < nSpellsKnown_AllLevels; i++)
|
||
{
|
||
int nSpellbookID = persistant_array_get_int(oPC, sSpellbook, i);
|
||
if (nSpellLevel == StringToInt(Get2DACache(sFile, "Level", nSpellbookID)))
|
||
{
|
||
nKnown++;
|
||
}
|
||
}
|
||
|
||
// Cache the value (one higher)
|
||
SetLocalInt(oPC, SPELLS_KNOWN_CACHE + IntToString(nSpellLevel), nKnown + 1);
|
||
return nKnown;
|
||
}
|
||
|
||
// gets the nr of spells that oPC currently knows at nSpellLevel with nClass
|
||
int GetSpellsKnown(int nClass, int nSpellLevel, object oPC)
|
||
{
|
||
// Check cache
|
||
string sCache = SPELLS_KNOWN_CACHE + IntToString(nSpellLevel);
|
||
int nKnown = GetLocalInt(oPC, sCache);
|
||
|
||
// Cache not yet set up?
|
||
if(!nKnown)
|
||
{
|
||
// then set the cache up and get the nr of spells known at nSpellLevel from the cache
|
||
CacheSpellsKnown(nClass, oPC);
|
||
nKnown = GetLocalInt(oPC, sCache);
|
||
}
|
||
|
||
// decrement the value retrieved from cache, because we stored one higher than the actual value to catch a legitimate count of 0
|
||
--nKnown;
|
||
|
||
if(DEBUG) DoDebug("GetSpellsKnown(" + GetName(oPC) + ", " +IntToString(nSpellLevel)+ ", " +IntToString(nClass)+ ") = " + IntToString(nKnown));
|
||
return nKnown;
|
||
}
|
||
|
||
// gets the total nr of spells up to nMaxSpellLevel that oPC currently knows
|
||
// caches results for all spell levels (because all spells known are stored in one single array)
|
||
int GetTotalNrOfSpellsKnown(int nClass, int nMaxSpellLevel, object oPC)
|
||
{
|
||
// Check cache at spell level 0
|
||
string sCache = SPELLS_KNOWN_CACHE + "0";
|
||
int nKnown = GetLocalInt(oPC, sCache);
|
||
// cache not present? Then make it
|
||
if(!nKnown)
|
||
{
|
||
CacheSpellsKnown(nClass, oPC);
|
||
nKnown = GetLocalInt(oPC, sCache);
|
||
}
|
||
|
||
// nr of known level 0 spells (cached value minus 1)
|
||
--nKnown;
|
||
|
||
// get other spell levels, up to max level
|
||
int nSpellLevel;
|
||
for (nSpellLevel = 1; nSpellLevel <= nMaxSpellLevel; nSpellLevel++)
|
||
{
|
||
// cached value is one higher than the actual value, so decrement by one
|
||
nKnown += (GetLocalInt(oPC, SPELLS_KNOWN_CACHE + IntToString(nSpellLevel)) - 1);
|
||
}
|
||
|
||
if(DEBUG) DoDebug("GetTotalNrOfSpellsKnown(" + GetName(oPC) + ", " + IntToString(nMaxSpellLevel) + ", " +IntToString(nClass)+ ") = " + IntToString(nKnown));
|
||
return nKnown;
|
||
}
|
||
|
||
// gets the maximum spell level, at which nClass can unlearn a spell at nCasterLevel according to PnP rules
|
||
// if nClass cannot unlearn a spell at nCasterLevel, we return -1
|
||
int GetPnPUnlearnMaxSpellLevel(int nClass, int nCasterLevel)
|
||
{
|
||
int nLevelModifier;
|
||
|
||
if( nClass == CLASS_TYPE_SORCERER
|
||
|| nClass == CLASS_TYPE_SUEL_ARCHANAMACH
|
||
|| nClass == CLASS_TYPE_FAVOURED_SOUL
|
||
|| nClass == CLASS_TYPE_MYSTIC
|
||
|| nClass == CLASS_TYPE_SUBLIME_CHORD)
|
||
{
|
||
// casterlevel must be at least four and an even nur
|
||
if (nCasterLevel >= 4 && ((nCasterLevel & 0x1) == 0))
|
||
nLevelModifier = 2;
|
||
}
|
||
else if (nClass == CLASS_TYPE_BARD)
|
||
{
|
||
// casterlevel must be at least five; then every three levels
|
||
if (nCasterLevel >= 5 && ((nCasterLevel - 2) % 3 == 0))
|
||
nLevelModifier = 2;
|
||
}
|
||
else if (nClass == CLASS_TYPE_DUSKBLADE)
|
||
{
|
||
// casterlevel must be at least five; then every odd level
|
||
if (nCasterLevel >= 5 && (nCasterLevel & 0x1))
|
||
nLevelModifier = 2;
|
||
}
|
||
else if (nClass == CLASS_TYPE_HEXBLADE)
|
||
{
|
||
// casterlevel must be at least twelve; then every three levels
|
||
if (nCasterLevel >= 12 && (nCasterLevel % 3 == 0))
|
||
nLevelModifier = 2;
|
||
}
|
||
|
||
if (nLevelModifier)
|
||
return GetMaxSpellLevelForCasterLevel(nClass, nCasterLevel) - nLevelModifier;
|
||
else
|
||
return -1;
|
||
}
|
||
|
||
// note that this also sets the local variables SPELLGAIN_CONV_UNLEARN_LEVEL and SPELLGAIN_CONV_UNLEARN_COUNT
|
||
int DetermineNrOfSpellsToUnlearn(int nClass, object oPC)
|
||
{
|
||
int nUnlearnCount = GetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT);
|
||
if (!nUnlearnCount)
|
||
{
|
||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||
int bBioUnlearn = GetPRCSwitch(PRC_BIO_UNLEARN);
|
||
int nMaxSpellLevel_Unlearn;
|
||
int nKnown_Total;
|
||
|
||
// determine the maximum level at which we can unlearn spells
|
||
if (bBioUnlearn)
|
||
// Bioware rules allow to unlearn spells up to the maximum level nClass can cast
|
||
nMaxSpellLevel_Unlearn = GetMaxSpellLevelForCasterLevel(nClass, nCasterLevel);
|
||
else
|
||
// in PnP we can only unlearn a limited amount of spells; at very specific casterlevels; and only some levels below our max
|
||
// if the function returns -1, we cannot unlearn any spells at this nCasterLevel
|
||
nMaxSpellLevel_Unlearn = GetPnPUnlearnMaxSpellLevel(nClass, nCasterLevel);
|
||
|
||
// are we able to unlearn spells at this nCasterlevel?
|
||
if (nMaxSpellLevel_Unlearn >= 0
|
||
// can only unlearn spells, if we know at least one spell up to the max level we may unlearn
|
||
&& ((nKnown_Total = GetTotalNrOfSpellsKnown(nClass, nMaxSpellLevel_Unlearn, oPC)) > 0))
|
||
{
|
||
// set the maximum caster level we can unlearn
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_LEVEL, nMaxSpellLevel_Unlearn);
|
||
|
||
// get the max nr of spells that can be unlearned from the switch
|
||
nUnlearnCount = GetPRCSwitch(PRC_UNLEARN_SPELL_MAXNR);
|
||
|
||
// if switch is not set, use default rules to determine max nr of spells that can be unlearned
|
||
if (!nUnlearnCount)
|
||
{
|
||
if (bBioUnlearn)
|
||
{
|
||
// Bioware casters can in principle unlearn all spells they know
|
||
nUnlearnCount = nKnown_Total;
|
||
}
|
||
else
|
||
{
|
||
// in full PnP we can only unlearn one single spell
|
||
nUnlearnCount = 1;
|
||
}
|
||
}
|
||
|
||
// make sure we never unlearn more than we actually know
|
||
if (nUnlearnCount > nKnown_Total) nUnlearnCount = nKnown_Total;
|
||
}
|
||
else
|
||
{
|
||
// if we cannot unlearn at this level, set the unlearn count to -1, so we know we cannot unlearn and that we already set up this stage
|
||
nUnlearnCount = -1;
|
||
}
|
||
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT, nUnlearnCount);
|
||
}
|
||
return nUnlearnCount;
|
||
}
|
||
|
||
void LearnSpecificSpell(int nClass, int nSpellLevel, int nSpellbookID, object oPC)
|
||
{
|
||
// get location of persistant storage on the hide
|
||
string sSpellbook = GetSpellsKnown_Array(nClass, nSpellLevel);
|
||
//object oToken = GetHideToken(oPC);
|
||
|
||
// 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;
|
||
}
|
||
|
||
// Mark the spell as known (e.g. add it to the end of oPCs spellbook)
|
||
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
||
|
||
// increment the spells known value in the cache
|
||
string sCache = SPELLS_KNOWN_CACHE + IntToString(nSpellLevel);
|
||
int nKnown = GetLocalInt(oPC, sCache);
|
||
if (nKnown) SetLocalInt(oPC, sCache, ++nKnown);
|
||
|
||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS)
|
||
{
|
||
// get the associated feat and IPfeat IDs
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// Add spell use feats (this also places the bonus feat on the hide, so we can check whether oPC knows this spell by testing for the featID on the hide)
|
||
AddSpellUse(oPC, nSpellbookID, nClass, sFile, "NewSpellbookMem_" + IntToString(nClass), SPELLBOOK_TYPE_SPONTANEOUS, GetPCSkin(oPC), nFeatID, nIPFeatID);
|
||
}
|
||
}
|
||
|
||
|
||
//////////////////////////////////////////////////
|
||
/* Main function */
|
||
//////////////////////////////////////////////////
|
||
|
||
void main()
|
||
{
|
||
object oPC = GetPCSpeaker();
|
||
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
|
||
int nStage = GetStage(oPC);
|
||
int nClass = GetLocalInt(oPC, SPELLGAIN_CONV_CLASS);
|
||
|
||
// Check which of the conversation scripts called the scripts
|
||
if(nValue == 0) // All of them set the DynConv_Var to non-zero value, so something is wrong -> abort
|
||
return;
|
||
|
||
// this conversation is always called for a specific class!
|
||
|
||
if(nValue == DYNCONV_SETUP_STAGE)
|
||
{
|
||
// Check if this stage is marked as already set up
|
||
// This stops list duplication when scrolling
|
||
if(!GetIsStageSetUp(nStage, oPC))
|
||
{
|
||
// variable named nStage determines the current conversation node
|
||
// Function SetHeader to set the text displayed to the PC
|
||
// Function AddChoice to add a response option for the PC. The responses are shown in order added
|
||
if (nStage == STAGE_UNLEARN_CHOICE)
|
||
{
|
||
// first determine the nr of spells that might be unlearned
|
||
int nUnlearnCount = DetermineNrOfSpellsToUnlearn(nClass, oPC);
|
||
|
||
// if we can unlearn spells, give oPC a choice
|
||
if (nUnlearnCount > 0)
|
||
{
|
||
SetHeader("You can unlearn " +IntToString(nUnlearnCount) +" spells\nDo you want to unlearn a spell?");
|
||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||
AddChoice(GetStringByStrRef(STRREF_YES), TRUE);
|
||
AddChoice(GetStringByStrRef(STRREF_NO), FALSE);
|
||
}
|
||
//check if it's Advanced Learning dialog
|
||
else if(GetLocalInt(oPC, "AdvancedLearning"))
|
||
{
|
||
nStage = STAGE_ADVLEARN_LEVEL;
|
||
SetStage(nStage, oPC);
|
||
}
|
||
else
|
||
{
|
||
// otherwise proceed directly to spell learning stage
|
||
nStage = STAGE_SELECT_LEVEL;
|
||
SetStage(nStage, oPC);
|
||
}
|
||
MarkStageSetUp(STAGE_UNLEARN_CHOICE, oPC);
|
||
}
|
||
|
||
// the second if is intentional, Dont change to else if!!
|
||
if(nStage == STAGE_SELECT_UNLEARN_LEVEL)
|
||
{
|
||
int nSpellLevelMin = GetLocalInt(oPC, "SpellbookMinSpelllevel");
|
||
// the maximum spell level at which we can unlearn spells was already set up in the previous phase, just retrieve it
|
||
int nSpellLevelMax = GetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_LEVEL);
|
||
|
||
int nChoiceAdded = FALSE;
|
||
|
||
int nSpellLevel;
|
||
// go through all spell levels, starting at the minimum level for nClass and ending at the maximum level that can be unlearned
|
||
for(nSpellLevel = nSpellLevelMin; nSpellLevel <= nSpellLevelMax; nSpellLevel++)
|
||
{
|
||
// get spells known to oPC at the given level
|
||
int nSpells_Known = GetSpellsKnown(nClass, nSpellLevel, oPC);
|
||
|
||
// only add a choice, if we know spells at that level
|
||
if(nSpells_Known > 0)
|
||
{
|
||
AddChoice(GetStringByStrRef(7544)/*"Spell Level"*/ + " " + IntToString(nSpellLevel), nSpellLevel);
|
||
nChoiceAdded = TRUE;
|
||
}
|
||
}
|
||
|
||
// if we added at least one spell level, set the header
|
||
if (nChoiceAdded == TRUE)
|
||
{
|
||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||
SetHeader("Select a level from which to unlearn a spell");
|
||
}
|
||
else
|
||
{
|
||
SetHeader("You do not have any spells to unlearn");
|
||
// if we didn't find a single spell to unlearn (shouldn't happen), set the unlearn count to -1 to indicate that cannot unlearn any spells at this point
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT, -1);
|
||
}
|
||
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
|
||
}
|
||
else if(nStage == STAGE_SELECT_UNLEARN_SPELL)
|
||
{
|
||
// get the level at which we want to unlearn the spell
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
// Determine the array where the spells known to oPC are stored (one array for all spell levels)
|
||
string sSpellbook = GetSpellsKnown_Array(nClass);
|
||
//object oToken = GetHideToken(oPC);
|
||
|
||
// determine the total nr of spells known to oPC
|
||
int nSpellsKnown_AllLevels = persistant_array_get_size(oPC, sSpellbook);
|
||
|
||
// Set up header
|
||
SetHeader("Select a spell to unlearn");
|
||
|
||
// List all spells known at the given level
|
||
int i;
|
||
for(i = 0; i < nSpellsKnown_AllLevels; i++)
|
||
{
|
||
// get the spellbookID (= row nr in cls_spell_*) for the i-th spell known
|
||
int nSpellbookID = persistant_array_get_int(oPC, sSpellbook, i);
|
||
// get the level of that spell and check whether it is equal to the spell level we selected
|
||
int nLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookID));
|
||
if (nLevel == nSpellLevel)
|
||
{
|
||
// get the real spellID, get the spell name from the real SpellID and add a choice
|
||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||
AddChoice(sName, nSpellbookID, oPC);
|
||
}
|
||
}
|
||
|
||
SetDefaultTokens();
|
||
MarkStageSetUp(nStage, oPC);
|
||
}
|
||
else if(nStage == STAGE_CONFIRM_UNLEARN)
|
||
{
|
||
// get the spellbookID (= row nr in cls_spell_*) for the spell we want to unlearn
|
||
int nSpellbookID = GetLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
|
||
// get the real spellID and the feat ID from cls_spell_*
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// show the full spell description (as determined from the feat)
|
||
string sToken = GetStringByStrRef(16824209) + "\n\n"; // "You have selected:"
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nFeatID))) + "\n";
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "DESCRIPTION", nFeatID))) + "\n\n";
|
||
sToken += GetStringByStrRef(16824210); // "Is this correct?"
|
||
SetHeader(sToken);
|
||
|
||
AddChoice(GetStringByStrRef(STRREF_YES), TRUE);
|
||
AddChoice(GetStringByStrRef(STRREF_NO), FALSE);
|
||
|
||
MarkStageSetUp(nStage, oPC);
|
||
SetDefaultTokens();
|
||
}
|
||
else if(nStage == STAGE_SELECT_LEVEL)
|
||
{
|
||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||
int nSpellLevelMin = GetLocalInt(oPC, "SpellbookMinSpelllevel");
|
||
// int nSpellLevelMax = GetLocalInt(oPC, "SpellbookMaxSpelllevel");
|
||
int nSpellLevelMax = GetMaxSpellLevelForCasterLevel(nClass, nCasterLevel);
|
||
|
||
int nSpellLevel;
|
||
int nAddedASpellLevel = FALSE;
|
||
|
||
if (GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS)
|
||
{
|
||
// go through all spell levels that are available for nClass up to the maximum spell level that oPC can cast
|
||
for(nSpellLevel = nSpellLevelMin; nSpellLevel <= nSpellLevelMax; nSpellLevel++)
|
||
{
|
||
// get the maximum nr of spells oPC is allowed to know at the given spell level
|
||
int nSpells_Max = GetSpellsKnown_MaxCount(nCasterLevel, nClass, nSpellLevel, oPC);
|
||
// if we cannot know any spells yet, no sense to do something
|
||
if (nSpells_Max > 0)
|
||
{
|
||
// get the nr of spells oPC knows at the given nSpellLevel and nClass
|
||
int nSpells_Known = GetSpellsKnown(nClass, nSpellLevel, oPC);
|
||
|
||
// we can only learn more spells, when the spells currently known at the given nSpellLevel are less than the max
|
||
if(nSpells_Known < nSpells_Max)
|
||
{
|
||
// get total nr of spells available for the given class and spell level
|
||
int nSpells_Total = GetSpellsInClassSpellbook_Count(nClass, nSpellLevel);
|
||
// are there still unknown spells in the class spellbook that we can transfer?
|
||
if(nSpells_Total > nSpells_Known)
|
||
{
|
||
nAddedASpellLevel = TRUE;
|
||
AddChoice(GetStringByStrRef(7544)/*"Spell Level"*/ + " " + IntToString(nSpellLevel), nSpellLevel);
|
||
}
|
||
else
|
||
if(DEBUG) DoDebug("ERROR: prc_s_spellgain: Insufficient spells to fill level " + IntToString(nSpellLevel) + "; Class: " + IntToString(nClass));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else if (GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED && GetLocalInt(oPC, SPELLGAIN_CONV_LEARN_LEVELUP) > 0)
|
||
{
|
||
nAddedASpellLevel = TRUE;
|
||
// go through all spell levels that are available for nClass up to the maximum spell level that oPC can cast
|
||
// 0-level spells already added
|
||
for(nSpellLevel = nSpellLevelMin + 1; nSpellLevel <= nSpellLevelMax; nSpellLevel++)
|
||
{
|
||
AddChoice(GetStringByStrRef(7544)/*"Spell Level"*/ + " " + IntToString(nSpellLevel), nSpellLevel);
|
||
}
|
||
}
|
||
|
||
// if there is at least one spell level at which we can still learn spells, go to the spel level selection phase
|
||
if(nAddedASpellLevel)
|
||
{
|
||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||
// "<classname> spellbook.\nSelect a spell level to gain spells from."
|
||
SetHeader(ReplaceChars(GetStringByStrRef(16828405), "<classname>", GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClass)))));
|
||
}
|
||
// if we couldn't add a single level from which to learn spells, we are finished, so allow exit
|
||
else
|
||
{
|
||
SetHeaderStrRef(16828406); // "You can select more spells when you next gain a level."
|
||
AllowExit(DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, oPC);
|
||
SetCustomToken(DYNCONV_TOKEN_EXIT, GetStringByStrRef(STRREF_END_CONVO_SELECT));
|
||
}
|
||
|
||
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
|
||
}
|
||
else if(nStage == STAGE_SELECT_SPELL)
|
||
{
|
||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
|
||
// class spellbook (one array for each spell level)
|
||
object oToken_Class = GetSpellsOfClass_Token(nClass, nSpellLevel);
|
||
string sSpellBook_Class = GetSpellsOfClass_Array();
|
||
|
||
// get the total nr of spells in the class spellbook at the given spell level
|
||
int nSpells_Total = persistant_array_get_size(oToken_Class, sSpellBook_Class);
|
||
|
||
// now determine storage location of the spellbook of oPC (all spell levels stored in one array)
|
||
string sSpellBook = GetSpellsKnown_Array(nClass, nSpellLevel);
|
||
//object oToken = GetHideToken(oPC);
|
||
|
||
// Create spells known array if it is missing
|
||
if(!persistant_array_exists(oPC, sSpellBook)) persistant_array_create(oPC, sSpellBook);
|
||
|
||
// Determine how many spells the character knows and how many
|
||
// he is maximally allowed to know (at the given nClass, nCasterLevel and nSpellLevel)
|
||
int nSpells_Max;
|
||
int nSpells_ToSelect;
|
||
if (GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS)
|
||
{
|
||
int nSpells_Known = GetSpellsKnown(nClass, nSpellLevel, oPC);
|
||
nSpells_Max = GetSpellsKnown_MaxCount(nCasterLevel, nClass, nSpellLevel, oPC);
|
||
|
||
// cannot learn more spells than there are in the class spellbook
|
||
if (nSpells_Max > nSpells_Total) nSpells_Max = nSpells_Total;
|
||
|
||
nSpells_ToSelect = nSpells_Max - nSpells_Known;
|
||
}
|
||
else
|
||
{
|
||
nSpells_ToSelect = GetLocalInt(oPC, SPELLGAIN_CONV_LEARN_LEVELUP);
|
||
}
|
||
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
// Set up header
|
||
// "You have <selectcount> level <spelllevel> spells remaining to select."
|
||
SetHeader(ReplaceChars(ReplaceChars(GetStringByStrRef(16828404),
|
||
"<selectcount>", IntToString(nSpells_ToSelect)),
|
||
"<spelllevel>", IntToString(nSpellLevel))
|
||
);
|
||
|
||
// 2009-9-20: Add a "learn all" option if he can do so. -N-S
|
||
if (nSpells_Max >= nSpells_Total)
|
||
// "[Learn all available spells]"
|
||
// Use the constant -1 to indicate all spells are desired.
|
||
AddChoice(StringToRGBString(GetStringByStrRef(16847627), STRING_COLOR_GREEN), -1, oPC);
|
||
|
||
// List all spells not yet selected of this level
|
||
int i;
|
||
for(i = 0; i < nSpells_Total; i++)
|
||
{
|
||
// get the nSpellbookID (= row nr in the cls_spell_* file) out of the class spellbook and determine the associated feat
|
||
int nSpellbookID = persistant_array_get_int(oToken_Class, sSpellBook_Class, i);
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
if (GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS)
|
||
{
|
||
// only if oPC doesn't have the feat, she doesn have the spell
|
||
if (!GetHasFeat(nFeatID, oPC))
|
||
{
|
||
// get the real spellID, get the spell name from the real spellID and add a choice
|
||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||
AddChoice(sName, nSpellbookID, oPC);
|
||
|
||
if(DEBUG) DoDebug("prc_s_spellgain: Adding spell selection choice:\n"
|
||
+ "spell ID = " + IntToString(nSpellID) + "\n"
|
||
+ "spellbook ID = " + IntToString(nSpellbookID) + "\n"
|
||
);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//check if oPC doesn't have the spell and can learn it
|
||
if (array_has_int(oPC, sSpellBook, nSpellbookID) == -1 && StringToInt(Get2DACache(sFile, "AL", nSpellbookID)) != 1)
|
||
{
|
||
// get the real spellID, get the spell name from the real spellID and add a choice
|
||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||
AddChoice(sName, nSpellbookID, oPC);
|
||
|
||
if(DEBUG) DoDebug("prc_s_spellgain: Adding spell selection choice:\n"
|
||
+ "spell ID = " + IntToString(nSpellID) + "\n"
|
||
+ "spellbook ID = " + IntToString(nSpellbookID) + "\n"
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (DEBUG)
|
||
{
|
||
DoDebug("Spellbook nCasterLevel: "+IntToString(nCasterLevel));
|
||
DoDebug("Spellbook nSpellLevel: "+IntToString(nSpellLevel));
|
||
DoDebug("Spellbook nSpells_ToSelect: "+IntToString(nSpells_ToSelect));
|
||
DoDebug("Spellbook sFile: "+sFile);
|
||
}
|
||
|
||
SetDefaultTokens();
|
||
MarkStageSetUp(nStage, oPC);
|
||
}
|
||
else if(nStage == STAGE_CONFIRM)
|
||
{
|
||
// get the spellbookID and the feat ID for the new spell to be learned
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
int nSpellbookID = GetLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// get the full description according from the feat ID
|
||
string sToken = GetStringByStrRef(16824209) + "\n\n"; // "You have selected:"
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nFeatID))) + "\n";
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "DESCRIPTION", nFeatID))) + "\n\n";
|
||
sToken += GetStringByStrRef(16824210); // "Is this correct?"
|
||
|
||
SetHeader(sToken);
|
||
|
||
AddChoice(GetStringByStrRef(STRREF_YES), TRUE);
|
||
AddChoice(GetStringByStrRef(STRREF_NO), FALSE);
|
||
|
||
MarkStageSetUp(nStage, oPC);
|
||
SetDefaultTokens();
|
||
}
|
||
// 2009-9-20: Add a "learn all" stage. -N-S
|
||
else if(nStage == STAGE_CONFIRM_ALL)
|
||
{
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
|
||
// class spellbook (one array for each spell level)
|
||
object oToken_Class = GetSpellsOfClass_Token(nClass, nSpellLevel);
|
||
string sSpellBook_Class = GetSpellsOfClass_Array();
|
||
|
||
// get the total nr of spells in the class spellbook at the given spell level
|
||
int nSpells_Total = persistant_array_get_size(oToken_Class, sSpellBook_Class);
|
||
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
string sToken = GetStringByStrRef(16847628) + "\n\n"; // "You have selected the following spells:"
|
||
int i;
|
||
for(i = 0; i < nSpells_Total; i++)
|
||
{
|
||
// get the nSpellbookID (= row nr in the cls_spell_* file) out of the class spellbook and determine the associated feat
|
||
int nSpellbookID = persistant_array_get_int(oToken_Class, sSpellBook_Class, i);
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// only if oPC doesn't have the feat, she doesn have the spell
|
||
if (!GetHasFeat(nFeatID, oPC))
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nFeatID))) + "\n";
|
||
}
|
||
sToken += "\n" + GetStringByStrRef(16824210); // "Is this correct?"
|
||
|
||
SetHeader(sToken);
|
||
|
||
AddChoice(GetStringByStrRef(STRREF_YES), TRUE);
|
||
AddChoice(GetStringByStrRef(STRREF_NO), FALSE);
|
||
|
||
MarkStageSetUp(nStage, oPC);
|
||
SetDefaultTokens();
|
||
}
|
||
else if(nStage == STAGE_ADVLEARN_LEVEL)
|
||
{
|
||
int nAL = GetLocalInt(oPC, "AdvancedLearning");
|
||
|
||
if(nAL)
|
||
{
|
||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||
int nSpellLevelMin = GetLocalInt(oPC, "SpellbookMinSpelllevel");
|
||
int nSpellLevelMax = GetMaxSpellLevelForCasterLevel(nClass, nCasterLevel);
|
||
|
||
int nSpellLevel;
|
||
// go through all spell levels that are available for nClass up to the maximum spell level that oPC can cast
|
||
for(nSpellLevel = nSpellLevelMin; nSpellLevel <= nSpellLevelMax; nSpellLevel++)
|
||
{
|
||
AddChoice(GetStringByStrRef(7544)/*"Spell Level"*/ + " " + IntToString(nSpellLevel), nSpellLevel);
|
||
}
|
||
|
||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||
// "<classname> spellbook.\nSelect a spell level to gain spells from."
|
||
SetHeader(ReplaceChars(GetStringByStrRef(16828405), "<classname>", GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClass)))));
|
||
}
|
||
// if we couldn't add a single level from which to learn spells, we are finished, so allow exit
|
||
else
|
||
{
|
||
SetHeaderStrRef(16828406); // "You can select more spells when you next gain a level."
|
||
AllowExit(DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, oPC);
|
||
SetCustomToken(DYNCONV_TOKEN_EXIT, GetStringByStrRef(STRREF_END_CONVO_SELECT));
|
||
}
|
||
|
||
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
|
||
}
|
||
else if(nStage == STAGE_ADVLEARN_SPELL)
|
||
{
|
||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
|
||
// class spellbook (one array for each spell level)
|
||
object oToken_Class = GetSpellsOfClass_Token(nClass, nSpellLevel);
|
||
string sSpellBook_Class = GetSpellsOfClass_Array();
|
||
|
||
// get the total nr of spells in the class spellbook at the given spell level
|
||
int nSpells_Total = persistant_array_get_size(oToken_Class, sSpellBook_Class);
|
||
|
||
// now determine storage location of the spellbook of oPC (all spell levels stored in one array)
|
||
string sSpellBook = GetSpellsKnown_Array(nClass);
|
||
//object oToken = GetHideToken(oPC);
|
||
|
||
// Create spells known array if it is missing
|
||
if(!persistant_array_exists(oPC, sSpellBook)) persistant_array_create(oPC, sSpellBook);
|
||
|
||
// Only one AL spell at a time
|
||
int nSpells_ToSelect = 1;
|
||
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
// Set up header
|
||
// "You have <selectcount> spells remaining to select."
|
||
SetHeader(ReplaceChars(ReplaceChars(GetStringByStrRef(16828404),
|
||
"<selectcount>", IntToString(nSpells_ToSelect)),
|
||
"<spelllevel>", IntToString(nSpellLevel))
|
||
);
|
||
|
||
AddChoice(StringToRGBString(GetStringByStrRef(16847645), STRING_COLOR_GREEN), CHOICE_RETURN_TO_PREVIOUS);
|
||
// List all spells not yet selected of this level
|
||
int i;
|
||
for(i = 0; i < nSpells_Total; i++)
|
||
{
|
||
// get the nSpellbookID (= row nr in the cls_spell_* file) out of the class spellbook and determine the associated feat
|
||
int nSpellbookID = persistant_array_get_int(oToken_Class, sSpellBook_Class, i);
|
||
//select only spells marked for Advanced Learning
|
||
if(Get2DACache(sFile, "AL", nSpellbookID) == "1")
|
||
{
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// only if oPC doesn't have the feat, she doesn have the spell
|
||
if (!GetHasFeat(nFeatID, oPC))
|
||
{
|
||
// get the real spellID, get the spell name from the real spellID and add a choice
|
||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||
AddChoice(sName, nSpellbookID, oPC);
|
||
|
||
if(DEBUG) DoDebug("prc_s_spellgain: Adding spell selection choice:\n"
|
||
+ "spell ID = " + IntToString(nSpellID) + "\n"
|
||
+ "spellbook ID = " + IntToString(nSpellbookID) + "\n"
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
SetDefaultTokens();
|
||
MarkStageSetUp(nStage, oPC);
|
||
}
|
||
else if(nStage == STAGE_ADVLEARN_CONFIRM)
|
||
{
|
||
// get the spellbookID and the feat ID for the new spell to be learned
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
int nSpellbookID = GetLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// get the full description according from the feat ID
|
||
string sToken = GetStringByStrRef(16824209) + "\n\n"; // "You have selected:"
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nFeatID))) + "\n";
|
||
sToken += GetStringByStrRef(StringToInt(Get2DACache("feat", "DESCRIPTION", nFeatID))) + "\n\n";
|
||
sToken += GetStringByStrRef(16824210); // "Is this correct?"
|
||
|
||
SetHeader(sToken);
|
||
|
||
AddChoice(GetStringByStrRef(STRREF_YES), TRUE);
|
||
AddChoice(GetStringByStrRef(STRREF_NO), FALSE);
|
||
|
||
MarkStageSetUp(nStage, oPC);
|
||
SetDefaultTokens();
|
||
}
|
||
//add more stages for more nodes with Else If clauses
|
||
}
|
||
|
||
// Do token setup
|
||
SetupTokens();
|
||
}
|
||
// Abort or exit conversation cleanup.
|
||
// NOTE: This section is only run when the conversation is aborted
|
||
// while aborting is allowed. When it isn't, the dynconvo infrastructure
|
||
// handles restoring the conversation in a transparent manner
|
||
else if(nValue == DYNCONV_EXITED ||
|
||
nValue == DYNCONV_ABORTED )
|
||
{
|
||
// Add any locals set through this conversation
|
||
DeleteLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
DeleteLocalInt(oPC, SPELLGAIN_CONV_CLASS);
|
||
DeleteLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
DeleteLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_LEVEL);
|
||
DeleteLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT);
|
||
DeleteLocalInt(oPC, SPELLGAIN_CONV_LEARN_LEVELUP);
|
||
DeleteLocalInt(oPC, "AdvancedLearning");
|
||
|
||
DeleteSKCCCache(oPC);
|
||
|
||
DelayCommand(1.0, EvalPRCFeats(oPC));
|
||
}
|
||
// Handle PC responses
|
||
else
|
||
{
|
||
// variable named nChoice is the value of the player's choice as stored when building the choice list
|
||
// variable named nStage determines the current conversation node
|
||
int nChoice = GetChoice(oPC);
|
||
if(nStage == STAGE_UNLEARN_CHOICE)
|
||
{
|
||
// if spells can be unlearned and oPC wants to unlearn them, proceed to node that selects the level of the spell to be unlearned
|
||
if( GetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT) > 0
|
||
&& nChoice == TRUE)
|
||
{
|
||
nStage = STAGE_SELECT_UNLEARN_LEVEL;
|
||
}
|
||
//check if it's Advanced Learning dialog
|
||
else if(GetLocalInt(oPC, "AdvancedLearning"))
|
||
{
|
||
nStage = STAGE_ADVLEARN_LEVEL;
|
||
}
|
||
// otherwise proceed to first node of the "learn new spells" section (= select level)
|
||
else
|
||
{
|
||
nStage = STAGE_SELECT_LEVEL;
|
||
}
|
||
}
|
||
else if(nStage == STAGE_SELECT_UNLEARN_LEVEL)
|
||
{
|
||
// if the nr of spells that can be unlearned is zero (or less), proceed to first node of the "learn new spells" section (= select level)
|
||
if(GetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT) <= 0)
|
||
nStage = STAGE_SELECT_LEVEL;
|
||
else
|
||
{
|
||
// otherwise remember the spell level at which to unlearn the spell and proceed to unlearn spell selection stage
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_LEVEL, nChoice);
|
||
nStage = STAGE_SELECT_UNLEARN_SPELL;
|
||
}
|
||
}
|
||
else if(nStage == STAGE_SELECT_UNLEARN_SPELL)
|
||
{
|
||
// record the spell that oPC selected as her unlearn choice and proceed to confirmation stage
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_SPELL, nChoice);
|
||
nStage = STAGE_CONFIRM_UNLEARN;
|
||
}
|
||
else if(nStage == STAGE_CONFIRM_UNLEARN)
|
||
{
|
||
// we really want to unlearn the spell?
|
||
if (nChoice == TRUE)
|
||
{
|
||
int nSpellbookID = GetLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
|
||
// extract the spell from oPCs spellbook
|
||
string sSpellBook = GetSpellsKnown_Array(nClass);
|
||
//object oToken = GetHideToken(oPC);
|
||
array_extract_int(oPC, sSpellBook, nSpellbookID);
|
||
|
||
// get the associated IPFeatID and remove it from the hide
|
||
// we dont remove the metamagic versions here, they will be removed by the hide cleaner at next rest
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||
WipeSpellFromHide(nIPFeatID, oPC);
|
||
|
||
// decrement the spells known value in the cache
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
string sCache = SPELLS_KNOWN_CACHE + IntToString(nSpellLevel);
|
||
int nKnown = GetLocalInt(oPC, sCache);
|
||
if (nKnown) SetLocalInt(oPC, sCache, --nKnown);
|
||
|
||
// decrement the nr of spells that can be unlearned
|
||
int nUnlearnCount = GetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT);
|
||
nUnlearnCount--;
|
||
if (nUnlearnCount == 0)
|
||
{
|
||
// make it -1, so that no new setup occurs (with more spells unlearned, than allowed)
|
||
nUnlearnCount--;
|
||
nStage = STAGE_SELECT_LEVEL;
|
||
}
|
||
else
|
||
nStage = STAGE_UNLEARN_CHOICE;
|
||
|
||
// remember the new nr of spells that can (still) be unlearned
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_UNLEARN_COUNT, nUnlearnCount);
|
||
}
|
||
else
|
||
{
|
||
// this was not the spell oPC wanted to unlearn? Then give oPC a new choice
|
||
nStage = STAGE_UNLEARN_CHOICE;
|
||
}
|
||
}
|
||
// BEGIN OF LEARN NEW SPELLS SECTION
|
||
else if(nStage == STAGE_SELECT_LEVEL)
|
||
{
|
||
// remember the spell level at which to learn the new spell and proceed to the spell selection phase
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_LEVEL, nChoice);
|
||
nStage = STAGE_SELECT_SPELL;
|
||
}
|
||
else if(nStage == STAGE_SELECT_SPELL)
|
||
{
|
||
// 2009-9-20: Add a "learn all" stage. -N-S
|
||
if (nChoice != -1)
|
||
{
|
||
// remember the new spell to learn and proceed to the confirmation phase
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_SPELL, nChoice);
|
||
nStage = STAGE_CONFIRM;
|
||
}
|
||
else
|
||
nStage = STAGE_CONFIRM_ALL;
|
||
}
|
||
else if(nStage == STAGE_CONFIRM)
|
||
{
|
||
// If this really is the new spell we want to learn:
|
||
if(nChoice == TRUE)
|
||
{
|
||
// get the new spell's nSpellbookID and nSpellLevel
|
||
int nSpellbookID = GetLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
|
||
LearnSpecificSpell(nClass, nSpellLevel, nSpellbookID, oPC);
|
||
|
||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED)
|
||
{
|
||
int nSpellsToLearn = GetLocalInt(oPC, "LrnLvlUp");
|
||
--nSpellsToLearn;
|
||
SetLocalInt(oPC, "LrnLvlUp", nSpellsToLearn);
|
||
|
||
if(nClass == CLASS_TYPE_ARCHIVIST)
|
||
{
|
||
int nLvl = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
|
||
SetPersistantLocalInt(oPC, "LastSpellGainLevel", nLvl);
|
||
}
|
||
}
|
||
}
|
||
|
||
nStage = STAGE_SELECT_LEVEL;
|
||
}
|
||
// 2009-9-20: Add a "learn all" stage handler. -N-S
|
||
else if(nStage == STAGE_CONFIRM_ALL)
|
||
{
|
||
if (nChoice == TRUE)
|
||
{
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
|
||
// class spellbook (one array for each spell level)
|
||
|
||
object oToken_Class = GetSpellsOfClass_Token(nClass, nSpellLevel);
|
||
string sSpellBook_Class = GetSpellsOfClass_Array();
|
||
|
||
// get the total nr of spells in the class spellbook at the given spell level
|
||
int nSpells_Total = persistant_array_get_size(oToken_Class, sSpellBook_Class);
|
||
|
||
string sFile = GetNSBDefinitionFileName(nClass);
|
||
|
||
int i;
|
||
for(i = 0; i < nSpells_Total; i++)
|
||
{
|
||
// get the nSpellbookID (= row nr in the cls_spell_* file) out of the class spellbook and determine the associated feat
|
||
int nSpellbookID = persistant_array_get_int(oToken_Class, sSpellBook_Class, i);
|
||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||
|
||
// only if oPC doesn't have the feat, she doesn have the spell
|
||
if (!GetHasFeat(nFeatID, oPC))
|
||
LearnSpecificSpell(nClass, nSpellLevel, nSpellbookID, oPC);
|
||
}
|
||
}
|
||
|
||
nStage = STAGE_SELECT_LEVEL;
|
||
}
|
||
else if(nStage == STAGE_ADVLEARN_LEVEL)
|
||
{
|
||
// remember the spell level at which to learn the new spell and proceed to the spell selection phase
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_LEVEL, nChoice);
|
||
nStage = STAGE_ADVLEARN_SPELL;
|
||
}
|
||
else if(nStage == STAGE_ADVLEARN_SPELL)
|
||
{
|
||
if(nChoice == CHOICE_RETURN_TO_PREVIOUS)
|
||
nStage = STAGE_ADVLEARN_LEVEL;
|
||
else
|
||
{
|
||
SetLocalInt(oPC, SPELLGAIN_CONV_SPELL, nChoice);
|
||
nStage = STAGE_ADVLEARN_CONFIRM;
|
||
}
|
||
}
|
||
else if(nStage == STAGE_ADVLEARN_CONFIRM)
|
||
{
|
||
// If this really is the new spell we want to learn:
|
||
if(nChoice == TRUE)
|
||
{
|
||
// get the new spell's nSpellbookID and nSpellLevel
|
||
int nSpellbookID = GetLocalInt(oPC, SPELLGAIN_CONV_SPELL);
|
||
int nSpellLevel = GetLocalInt(oPC, SPELLGAIN_CONV_LEVEL);
|
||
|
||
LearnSpecificSpell(nClass, nSpellLevel, nSpellbookID, oPC);
|
||
|
||
DeleteLocalInt(oPC, "AdvancedLearning");
|
||
int nAdvLearn = GetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass));
|
||
nAdvLearn++;
|
||
SetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass), nAdvLearn);
|
||
}
|
||
|
||
nStage = STAGE_ADVLEARN_LEVEL;
|
||
}
|
||
|
||
MarkStageNotSetUp(nStage, oPC);
|
||
// Store the stage value. If it has been changed, this clears out the choices
|
||
SetStage(nStage, oPC);
|
||
}
|
||
}
|