PRC8/trunk/scripts/PRC_S_spellb.nss
Jaysyn904 6585d40a0f Major script update for 8 class support
Major script update for 8 class support.

prc_wipeNSB.nss

PRC_S_spellb.nss

prc_amagsys_gain.nss	- AMSCompatibilityCheck()

prc_prereq.nss			- Dragonheart(), KnightWeave()

prc_onenter.nss			- OnEnter_AMSCompatibilityCheck()

prc_metamagic.nss		- GetHasSpontaneousNSBClass()

prc_feats.nss

prc_dracactive.nss

prc_debug_hfeatm.nss

prc_cbtmed_spnhl.nss

psi_powconv.nss

psi_pow_bstpwr.nss

x2_pc_umdcheck.nss
2023-03-11 12:04:30 -05:00

624 lines
27 KiB
Plaintext

//:://////////////////////////////////////////////
//:: PRC New Spellbooks use conversation
//:: prc_s_spellb
//:://////////////////////////////////////////////
/** @file
@todo Primo: Could you write a blurb on what
this does and TLKify it?
@author Primogenitor
@date Created - yyyy.mm.dd
last changed by motu99, April 29, 2008:
Conversation script for setting up spells to be memorized by prepared casters
This conversation script sets up a persistent array of the spells to be memorized
(at the end of the next rest) for any newspellbook prepared caster class.
It uses the persistent array name prefix "Spellbook", then appends the spell level
(converted to a string) to the prefix and lastly appends the class-nr (converted to a string)
The thus appended prefix is a persistent array name, in which the nSpellbookIDs of the
spells to be memorized at the end of the next rest are stored
the conversation is called by activating the prc_spellbook feat (#1999 in feats.2da)
which fires the spellscript prc_spellbook (#1792 in spells.2da), which then calls this
conversation script
*/
//:://////////////////////////////////////////////
//:: Updated for .35 by Jaysyn 2023/03/11
//:://////////////////////////////////////////////
// persistant storage format on hide
/**
MEMORIZED SPELLS FOR PREP CASTERS:
All spell levels are all stored in one single array (motu99: very unfortunate, should be changed):
sArrayName = "NewSpellbookMem_"+IntToString(nClass)
The array is indexed by the spellbookID; the value is the number of spells with that spellbookID still in memory:
nNrOfSpellsStillInMemory = sArrayName[nSpellbookID]
SPELLS TO BE MEMORIZED BY PREP CASTERS
They are stored in up to ten arrays, one array for each spell level (or rather spell slot level)
sArrayName = "Spellbook"+IntToString(nSpellLevel)+"_"+IntToString(nClass)
The array is indexed by the slot number, starting at #0; the value contains the nSpelllbookID of the spell to be memorized
nSpellbookID = sArrayName[nSlotNr]
SPELLS MEMORIZED BY PREP CASTERS - INDEX
Array created from "spells to be memorized" in OnRest event. Only unique spellids are stored.
sArrayName = "SpellbookIDX"+IntToString(nSpellLevel)+"_"+IntToString(nClass)
Serves as "NewSpellbookMem_" index for fast search and delete - allows looping only through memorized SpellbookIDs
(archivist - max 56 + bonus slots from high WIS) instead of all SpellbookIDs (archivist - 2400+)
Should help reduce instruction count sagnificantly.
SPELLS KNOWN BY PREP CASTERS:
so far prep NSB casters know all spells in their class spellbook; they need not learn spells
motu99: This might change, if for instance wizards use the NSB system to gain higher spell slot levels (10+)
//for archivist:
They are stored in up to ten arrays, one array for each spell level (or rather spell slot level)
sArrayName = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(nSpellLevel)
SPELLS KNOWN BY SPONT CASTERS:
The spells known are stored in one single array (the array contains only the non-metamagic versions and only master spells)
sArrayName = "Spellbook" + IntToString(nClass);
The array is indexed by a counter (the i-th spell learned); the value contains the nSpellbookID of the (non-metamagic master) spell known
nSpellbookID = sArrayName[i]
AVAILABLE SPELL SLOTS FOR SPONT CASTERS:
The nr of still available spell slots for a prep caster are all stored in one single array
sArrayName = "NewSpellbookMem_" + IntToString(nClass)
The array is indexed by the spell (slot) level, the value contains the nr of still available slots at that spell (slot) level
nNrOfSpellSlotsAvailable = sArrayName[nSpellSlotLevel]
*/
// spells in the class spellbook of nClass (a spont caster generally will not know all of these spells)
/**
SPELLS IN THE CLASS SPELLBOOK OF PREP OR SPONT CASTERS:
The spells that are potentially learnable by nClass are stored on the prc cache object in up to 10 different tokens.
The class spell book ONLY stores the masterspells and ONLY the non-metamagicked version!
There is one storage token for every spell level (and class); it has the tag name:
sTag = "SpellLvl_"+IntToString(nClass)+"_Level_"+IntToString(nSpellLevel);
The spells are stored on the token object oToken (defined by the unique sTag) in an array with name sArrayName
oToken = GetObjectByTag(sTag)
sArrayName = "Lkup"
The array is indexed by a counter (the i-th spell of a given level in the class spellbook); the value is the spellbookID
nSpellbookID = sArrayName[i]
*/
#include "x2_inc_spellhook"
#include "inc_dynconv"
#include "inc_sp_gain_mem"
//////////////////////////////////////////////////
/* Constant defintions */
//////////////////////////////////////////////////
const int STAGE_SELECT_CLASS = 0;
const int STAGE_SELECT_SPELL_LEVEL = 1;
const int STAGE_SELECT_SPELL_SLOT = 2;
const int STAGE_SELECT_METAMAGIC = 3;
const int STAGE_SELECT_SPELL = 4;
const int CHOICE_RETURN_TO_PREVIOUS = 0xEFFFFFFF;
const string CONV_SPELLB_CLASS = "SpellClass";
const string CONV_SPELLB_LEVEL = "SpellLevel";
const string CONV_SPELLB_META = "MetaMagic";
const string CONV_SPELLB_SLOT = "SpellSlot";
const int DYNCONV_NEXT_STAGE = -4;
//////////////////////////////////////////////////
/* Aid functions */
//////////////////////////////////////////////////
const string SPELLS_MEMORIZED_CACHE = "SMCCCache";
void DeleteSpellsMemorizedCache(object oPC)
{
int i;
for (i=1; i <= MAX_CLASSES; i++)
{
int nClass = GetClassByPosition(i, oPC);
if (nClass == CLASS_TYPE_INVALID) break;
if(GetLocalInt(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass)))
{
DeleteLocalInt(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass));
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "0");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "1");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "2");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "3");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "4");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "5");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "6");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "7");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "8");
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "9");
}
}
}
// now build the cache
void GenerateSpellsMemorizedCache(int nClass, object oPC)
{
// get the object on the hide of oPC where the persistant data are stored
//object oToken = GetHideToken(oPC);
string sSpellsMemorized = GetSpellsMemorized_Array(nClass);
// if the persistant array with the remaining memorized spells does not exist, abort
if(!persistant_array_exists(oPC, sSpellsMemorized))
{
if(DEBUG) DoDebug("Error: " +sSpellsMemorized+ " array does not exist");
}
else
{
string sFile = GetNSBDefinitionFileName(nClass);
string sArrayIDX, sSpellbookID, sMessage, sMess, sClass = IntToString(nClass);
// remember the class (because this might change during the conversation)
SetLocalInt(oPC, SPELLS_MEMORIZED_CACHE + sClass, TRUE);
int nSpellLevel, nSlot, nSlots, nSpellbookID;
for(nSpellLevel = 0; nSpellLevel <= 9; nSpellLevel++)
{
sArrayIDX = "SpellbookIDX" + IntToString(nSpellLevel) + "_" + sClass;
sMessage = "";
nSlots = persistant_array_get_size(oPC, sArrayIDX);
for(nSlot = 0; nSlot < nSlots; nSlot++)
{
nSpellbookID = persistant_array_get_int(oPC, sArrayIDX, nSlot);
int nCount = nSpellbookID ? persistant_array_get_int(oPC, sSpellsMemorized, nSpellbookID) : 0;
if(nCount)
{
// determine spell name from spellID by reference
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
sMess = PRC_TEXT_WHITE + GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
// add the metamagic [ext emp]
int nMetaMagicFeat = StringToInt(Get2DACache(sFile, "ReqFeat", nSpellbookID));
if(nMetaMagicFeat)
{
int nMetaMagic = GetMetaMagicFromFeat(nMetaMagicFeat);
sMess += " - " +GetMetaMagicString(nMetaMagic);
}
// add the nr of spells in memory
sMess += PRC_TEXT_BLUE + " [" +IntToString(nCount)+ "]\n";
sMessage += sMess;
}
}
// now store the values for later retrieval
if (sMessage != "") SetLocalString(oPC, SPELLS_MEMORIZED_CACHE + sClass + "_" + IntToString(nSpellLevel), sMessage);
}
}
// we delete the cached values on exit from the conversation, so no need to do it now
// DelayCommand(6.0, DeleteSpellsMemorizedCache(oPC));
}
// creates a string with a list of memorized spells of the given nClass and nSpellSlotLevel
// each spell has an extra line, which denotes the spell's name
string ListMemorizedSpells(int nClass, int nSpellSlotLevel, object oPC)
{
// try to get the list from cache; but only if cache is for the correct nClass
//if (GetLocalInt(oPC, SPELLS_MEMORIZED_CACHE) == nClass)
//{
return GetLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + IntToString(nSpellSlotLevel));
//}
}
//////////////////////////////////////////////////
/* Main function */
//////////////////////////////////////////////////
void main()
{
object oPC = GetPCSpeaker();
/* Get the value of the local variable set by the conversation script calling
* this script. Values:
* DYNCONV_ABORTED Conversation aborted
* DYNCONV_EXITED Conversation exited via the exit node
* DYNCONV_SETUP_STAGE System's reply turn
* 0 Error - something else called the script
* Other The user made a choice
*/
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
// The stage is used to determine the active conversation node.
// 0 is the entry node.
int nStage = GetStage(oPC);
// 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;
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))
{
if(nStage == STAGE_SELECT_CLASS)
{
//select spell class
SetHeader("Select a spell book:");
int i;
for (i=1; i <= MAX_CLASSES; i++)
{
int nClass = GetClassByPosition(i, oPC);
if (nClass == CLASS_TYPE_INVALID) break;
if(GetIsNSBClass(nClass) && // must be a new spellbook class
GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED) // must be a prepared caster
{
// must have levels in the prepared class and at least level 1 spell slots
int nAbilityScore = GetAbilityScoreForClass(nClass, oPC);
int nClassLevel = GetLevelByPosition(i, oPC);
if(nClassLevel
&& (GetSlotCount(nClassLevel, 0, nAbilityScore, nClass)
|| GetSlotCount(nClassLevel, 1, nAbilityScore, nClass)))
{
string sClassName = GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClass)));
GenerateSpellsMemorizedCache(nClass, oPC);
AddChoice(sClassName, nClass, oPC);
}
}
}
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
MarkStageSetUp(nStage, oPC);
}
else if(nStage == STAGE_SELECT_SPELL_LEVEL)
{
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
int nMaxSpellSlotLevel = GetMaxSpellLevelForCasterLevel(nClass, nCasterLevel);
int nMinSpellSlotLevel = GetMinSpellLevelForCasterLevel(nClass, nCasterLevel);
int nChoiceAdded = FALSE;
if(nMaxSpellSlotLevel >= nMinSpellSlotLevel)
{
string sChoiceSpellLevel = "Spell slot level ";
int nAbilityScore = GetAbilityScoreForClass(nClass, oPC);
// List all spell slot levels available to the caster for this class
int nSpellSlotLevel;
for(nSpellSlotLevel = nMinSpellSlotLevel; nSpellSlotLevel <= nMaxSpellSlotLevel; nSpellSlotLevel++)
{
// for every spell level, determine the slot count, and if it is non-zero add a choice
// we do not break out of the loop on an empty slot count, because of bonus slot counts from items there might be gaps
if(GetSlotCount(nCasterLevel, nSpellSlotLevel, nAbilityScore, nClass))
{
AddChoice(sChoiceSpellLevel +IntToString(nSpellSlotLevel), nSpellSlotLevel, oPC);
nChoiceAdded = TRUE;
}
}
}
if (nChoiceAdded)
SetHeader("Select a spell slot level:");
else
SetHeader("You cannot memorize any spells at the moment - check your ability score");
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
MarkStageSetUp(nStage, oPC);
}
else if(nStage == STAGE_SELECT_SPELL_SLOT)
{
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
int nAbilityScore = GetAbilityScoreForClass(nClass, oPC);
// get the object on the hide of oPC where the persistant data are stored
//object oToken = GetHideToken(oPC);
// determine the name of the persistant array that holds the spells to be memorized for the given nClass and nSpellLevel
// (the index to the array is the nr of the slot of the given nClass and nSpellLevel)
string sSpellsToBeMemorized = GetSpellsToBeMemorized_Array(nClass, nSpellSlotLevel);
// unfortunatly, the spellsMemorized list has a different format (all spell levels in one huge sparse array, indexed by nSpellbookID)
string sSpellsMemorized = GetSpellsMemorized_Array(nClass);
// now check if the arrays "spells to be memorized" and "spells memorized" exist at the given spell slot level and create them, if not
if (persistant_array_get_size(oPC, sSpellsToBeMemorized) < 0) persistant_array_create(oPC, sSpellsToBeMemorized);
if (persistant_array_get_size(oPC, sSpellsMemorized) < 0) persistant_array_create(oPC, sSpellsMemorized);
string sHeader = "You have remaining:\n";
sHeader += ListMemorizedSpells(nClass, nSpellSlotLevel, oPC) + "\n";
// get the nr of spell slots for the given nClass and nSpellLevel
// (should be non-zero, because we only allow the PC to select spell slot levels with non-zero slot count)
int nSlots = GetSlotCount(nCasterLevel, nSpellSlotLevel, nAbilityScore, nClass, oPC);
if (nSlots > 0)
{
sHeader += "Select a spell slot:\n"+ PRC_TEXT_WHITE + "spell to be memorized " + PRC_TEXT_BLUE + "[# still in memory]";
// set the array size of "spells to be memorized" and "spells memorized" to the nr of slots
array_set_size(oPC, sSpellsToBeMemorized, nSlots);
string sFile = GetNSBDefinitionFileName(nClass);
string sChoice;
string sNameToBeMemorized;
// add a choice for every slot; show what is currently in the slot (if nothing, show "empty")
int nSlotNr;
for(nSlotNr = 0; nSlotNr < nSlots; nSlotNr++)
{
// get the spell associated with the i-th slot
int nSpellbookID = persistant_array_get_int(oPC, sSpellsToBeMemorized, nSlotNr);
int nMetaMagic = 0;
// nothing "to be memorized" for this slot?
if (nSpellbookID == 0)
{
sNameToBeMemorized = "Empty";
}
else
{
// get the spell name "to be memorized", including metamagic
// int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
// sNameToBeMemorized = GetStringByStrRef(StringToInt(Get2DACache("iprp_feats", "Name", nIPFeatID)));
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
sNameToBeMemorized = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
nMetaMagic = GetMetaMagicFromFeat(StringToInt(Get2DACache(sFile, "ReqFeat", nSpellbookID)));
if (nMetaMagic) sNameToBeMemorized += " - " + GetMetaMagicString(nMetaMagic);
}
//first we show what spell will "be memorized" at next rest from the given slot (this is in white)
sChoice = PRC_TEXT_WHITE + sNameToBeMemorized;
// now check if there are spells still in memory that are equal to the spell "to be memorized" at the given slot
if (nSpellbookID)
{
int nNrOfSpells_Mem = persistant_array_get_int(oPC, sSpellsMemorized, nSpellbookID);
// show in blue and in brackets
sChoice += PRC_TEXT_BLUE + " [" +IntToString(nNrOfSpells_Mem)+ "]";
}
// add the slot nr as choice
AddChoice(sChoice, nSlotNr, oPC);
}
}
else
{
sHeader += PRC_TEXT_WHITE + "there aren't any slots available at the chosen level - check your ability score";
}
SetHeader(sHeader);
AddChoice("Back", CHOICE_RETURN_TO_PREVIOUS);
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
MarkStageSetUp(nStage, oPC);
}
else if (nStage == STAGE_SELECT_METAMAGIC)
{
// get the metamagic feats oPC possesses
int nMetaMagicCaster = GetMetaMagicOfCaster(oPC);
int bChoiceAdded;
// only need to do this, if the caster has at least one metamagic feat
if (nMetaMagicCaster)
{
// get the currently selected spell slot level
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
int nMinSpellSlotLevel = GetMinSpellLevelForCasterLevel(nClass, nCasterLevel);
// metamagics only for slot levels higher than the lowest slot level
if (nSpellSlotLevel > nMinSpellSlotLevel)
{
// calculate the maximum metamagic adjustment that is possible at the given spell slot level
// note that the metamagic adjustment will generally result in spells to choose from, that are
// lower in level than the spell slot level. But we cannot reduce the level below the minimum spell level of the class
int nMaxMetaMagicAdj = nSpellSlotLevel - nMinSpellSlotLevel;
// go through all possible metamagics by shifting 1 to the left
// this will result in checking for some metamagics that are not implemented
// but the check against the metamagic feats possessed be oPC will get rid of all non-implemented
int nMetaMagic;
for (nMetaMagic = 1; nMetaMagic < 0x40; nMetaMagic <<= 1)
{
if ((nMetaMagicCaster & nMetaMagic) // caster must have the metamagic feat
// and the combined levels of the already chosen metamagic with the metamagic to choose must be
// less or equal than the max metamagic adjustment allowed for nClass at the given nSpellSlotLevel
&& GetMetaMagicSpellLevelAdjustment(nMetaMagic) <= nMaxMetaMagicAdj)
{
AddChoice(GetMetaMagicString(nMetaMagic), nMetaMagic, oPC);
bChoiceAdded = TRUE;
}
}
if (bChoiceAdded)
{
SetHeader("Select a metamagic adjustment:");
AddChoice("No metamagic", 0, oPC);
AddChoice("Back", CHOICE_RETURN_TO_PREVIOUS);
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
}
}
// no metamagics available at the spell slot level?
if (!bChoiceAdded)
{
// then advance to next stage and clear metamagic
SetStage(++nStage, oPC);
DeleteLocalInt(oPC, CONV_SPELLB_META);
}
MarkStageSetUp(STAGE_SELECT_METAMAGIC, oPC);
}
// if-clause is intentional; DONT change to else-if
if(nStage == STAGE_SELECT_SPELL)
{
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
int nMetaMagic = GetLocalInt(oPC, CONV_SPELLB_META);
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
int nSpellLevel = nSpellSlotLevel - GetMetaMagicSpellLevelAdjustment(nMetaMagic);
// determine from where to get the spells known (for nClass at the given level)
// so far this is the class spellbook, eg. all spells are available (divine casters)
string sFile = GetNSBDefinitionFileName(nClass);
object oToken;
string sSpellBook;
if(bKnowsAllClassSpells(nClass))
{
oToken = GetSpellsOfClass_Token(nClass, nSpellLevel);
sSpellBook = GetSpellsOfClass_Array();
}
else
{
oToken = oPC;
sSpellBook = GetSpellsKnown_Array(nClass, nSpellLevel);
}
// go through all spells that oPC has in his spellbook at the given nSpellLevel ( for divine casters this might be all)
// motu99: This array does NOT include the metamagicked versions of the spells or subradial versions!
int nSpellsKnown = persistant_array_get_size(oToken, sSpellBook);
int bSpellSelected = FALSE;
int i;
for(i = 0; i < nSpellsKnown; i++)
{
// this is the cls_spell_* row nr for the UNMETAMAGICKED version of the spell
int nSpellbookID = persistant_array_get_int(oToken, sSpellBook, i);
// get the real spellID
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
// if we choose a metamagic, find the nSpellbookID for the metamagic version of the spell
// all metamagic versions of the master spell lie in a consecutive block after the non-metamagic version
if (nMetaMagic)
{
// get the next row in cls_spell_* and test if it belongs to the same real spellID
while (StringToInt(Get2DACache(sFile, "RealSpellID", ++nSpellbookID)) == nSpellID)
{
// do the metamagics match?
if (nMetaMagic == GetMetaMagicFromFeat(StringToInt(Get2DACache(sFile, "ReqFeat", nSpellbookID))))
{
// indicate success by negative nr
nSpellbookID = -nSpellbookID;
break;
}
}
// success? then redo the negation
if (nSpellbookID < 0)
nSpellbookID = -nSpellbookID;
// otherwise indicate failure by setting nSpellbookID to zero
else
nSpellbookID = 0;
}
// did we find an appropriate spellbook ID for the given spell slot evel and metamagic?
// then add it to the list
if (nSpellbookID)
{
// int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
// string sName = GetStringByStrRef(StringToInt(Get2DACache("iprp_feats", "Name", nIPFeatID)));
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
if (nMetaMagic) sName + " - " +GetMetaMagicString(nMetaMagic);
AddChoice(sName, nSpellbookID, oPC);
bSpellSelected = TRUE;
}
}
if (bSpellSelected)
SetHeader("Select a spell:");
else
SetHeader("No spells to select at spell level " + IntToString (nSpellLevel));
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
MarkStageSetUp(nStage, oPC);
}
}
// Do token setup
SetupTokens();
}
else if(nValue == DYNCONV_EXITED ||
nValue == DYNCONV_ABORTED )
{
//end of conversation cleanup
DeleteLocalInt(oPC, CONV_SPELLB_CLASS);
DeleteLocalInt(oPC, CONV_SPELLB_LEVEL);
DeleteLocalInt(oPC, CONV_SPELLB_SLOT);
DeleteLocalInt(oPC, CONV_SPELLB_META);
DeleteSpellsMemorizedCache(oPC);
}
else
{
int nChoice = GetChoice(oPC);
if(nStage == STAGE_SELECT_CLASS)
{
//store nClass and proceed to slot level selection
SetLocalInt(oPC, CONV_SPELLB_CLASS, nChoice);
nStage = STAGE_SELECT_SPELL_LEVEL;
MarkStageNotSetUp(nStage, oPC);
}
else if(nStage == STAGE_SELECT_SPELL_LEVEL)
{
//store slot level and proceed to spell slot selection
SetLocalInt(oPC, CONV_SPELLB_LEVEL, nChoice);
nStage = STAGE_SELECT_SPELL_SLOT;
MarkStageNotSetUp(nStage, oPC);
}
else if(nStage == STAGE_SELECT_SPELL_SLOT)
{
if(nChoice == CHOICE_RETURN_TO_PREVIOUS)
nStage = STAGE_SELECT_SPELL_LEVEL;
else
{
// store the spell slot nr and go to metamagic selection phase
SetLocalInt(oPC, CONV_SPELLB_SLOT, nChoice);
nStage = STAGE_SELECT_METAMAGIC;
}
MarkStageNotSetUp(nStage, oPC);
}
else if(nStage == STAGE_SELECT_METAMAGIC)
{
if(nChoice == CHOICE_RETURN_TO_PREVIOUS)
nStage = STAGE_SELECT_SPELL_SLOT;
else
{
// store the metamagic and proceed to spell selection phase
SetLocalInt(oPC, CONV_SPELLB_META, nChoice);
nStage = STAGE_SELECT_SPELL;
}
MarkStageNotSetUp(nStage, oPC);
}
else if(nStage == STAGE_SELECT_SPELL)
{
// our choice is the nSpellbookID
// get the other vital information
int nSpellSlot = GetLocalInt(oPC, CONV_SPELLB_SLOT);
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
int nMetaMagic = GetLocalInt(oPC, CONV_SPELLB_META);
// get the object on the hide of oPC where the persistant data are stored
//object oToken = GetHideToken(oPC);
// determine the name of the persistant array that holds the spells to be memorized for the given nClass and nSpellLevel
// (the index to the array is the nr of the slot of the given nClass and nSpellLevel)
string sSpellsToBeMemorized = GetSpellsToBeMemorized_Array(nClass, nSpellSlotLevel);
// store the chosen nSpellbookID (row nr in the newspellbook file cls_spells_*) in the spells to be memorized array
persistant_array_set_int(oPC, sSpellsToBeMemorized, nSpellSlot, nChoice);
// let oPC select a new spell (starting with the spell level)
nStage = STAGE_SELECT_SPELL_LEVEL;
MarkStageNotSetUp(nStage, oPC);
}
// Store the stage value. If it has been changed, this clears out the choices
SetStage(nStage, oPC);
}
}