PRC8/nwn/nwnprc/trunk/newspellbook/moi_midnightcnv.nss
Jaysyn904 e641b42f84 Exalted update
Updated Vow of Poverty. Added Sanctify Ki Strike, Holy Strike, Fist of Heavens, Vow of Abstinence, Vow of Chastity & Gift of Faith.  (@fenac).  Turned off the Taunt & Parry skills.  Re-disabled AC & save bonuses from Tumble & Spellcraft.   Updated min() & max() to PRCmin() & PRCmax() to not conflict with similarly named NUI adjacent functions.  Set Point Blank Shot to 30' per PnP.  Added icon for Chosen of Evil.  Started work on Hidden Talent.  Created Psionics function cheatsheet.  Updated release archive.
2025-01-29 22:46:38 -05:00

271 lines
11 KiB
Plaintext

//:://////////////////////////////////////////////
//:: Meldshaper Invest Essentia choice script
//:: moi_midnightcnv
//:://////////////////////////////////////////////
/*
@author Stratovarius - 2019.12.29
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "moi_inc_moifunc"
#include "inc_dynconv"
//////////////////////////////////////////////////
/* Constant definitions */
//////////////////////////////////////////////////
const int STAGE_SELECT_POWER = 0;
const int STAGE_SELECT_ESSENTIA_POWER = 6;
const int STAGE_CONFIRM_SELECTION_POWER = 7;
const int CHOICE_BACK_TO_LSELECT = -1;
const int STRREF_SELECTED_HEADER1 = 16824209; // "You have selected:"
const int STRREF_SELECTED_HEADER2 = 16824210; // "Is this correct?"
const int STRREF_YES = 4752; // "Yes"
const int STRREF_NO = 4753; // "No"
const int SORT = TRUE; // If the sorting takes too much CPU, set to FALSE
const int DEBUG_LIST = FALSE;
//////////////////////////////////////////////////
/* Function defintions */
//////////////////////////////////////////////////
void PrintList(object oMeldshaper)
{
string tp = "Printing list:\n";
string s = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Head");
if(s == ""){
tp += "Empty\n";
}
else{
tp += s + "\n";
s = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + s);
while(s != ""){
tp += "=> " + s + "\n";
s = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + s);
}
}
DoDebug(tp);
}
/**
* Creates a linked list of entries that is sorted into alphabetical order
* as it is built.
* Assumption: mystery names are unique.
*
* @param oMeldshaper The storage object aka whomever is gaining powers in this conversation
* @param sChoice The choice string
* @param nChoice The choice value
*/
void AddToTempList(object oMeldshaper, string sChoice, int nChoice)
{
if(DEBUG_LIST) DoDebug("\nAdding to temp list: '" + sChoice + "' - " + IntToString(nChoice));
if(DEBUG_LIST) PrintList(oMeldshaper);
// If there is nothing yet
if(!GetLocalInt(oMeldshaper, "PRC_MidnightConvo_ListInited"))
{
SetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Head", sChoice);
SetLocalInt(oMeldshaper, "PRC_MidnightConvo_List_" + sChoice, nChoice);
SetLocalInt(oMeldshaper, "PRC_MidnightConvo_ListInited", TRUE);
}
else
{
// Find the location to instert into
string sPrev = "", sNext = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Head");
while(sNext != "" && StringCompare(sChoice, sNext) >= 0)
{
if(DEBUG_LIST) DoDebug("Comparison between '" + sChoice + "' and '" + sNext + "' = " + IntToString(StringCompare(sChoice, sNext)));
sPrev = sNext;
sNext = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + sNext);
}
// Insert the new entry
// Does it replace the head?
if(sPrev == "")
{
if(DEBUG_LIST) DoDebug("New head");
SetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Head", sChoice);
}
else
{
if(DEBUG_LIST) DoDebug("Inserting into position between '" + sPrev + "' and '" + sNext + "'");
SetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + sPrev, sChoice);
}
SetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + sChoice, sNext);
SetLocalInt(oMeldshaper, "PRC_MidnightConvo_List_" + sChoice, nChoice);
}
}
/**
* Reads the linked list built with AddToTempList() to AddChoice() and
* deletes it.
*
* @param oMeldshaper A PC gaining powers at the moment
*/
void TransferTempList(object oMeldshaper)
{
string sChoice = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Head");
int nChoice = GetLocalInt (oMeldshaper, "PRC_MidnightConvo_List_" + sChoice);
DeleteLocalString(oMeldshaper, "PRC_MidnightConvo_List_Head");
string sPrev;
if(DEBUG_LIST) DoDebug("Head is: '" + sChoice + "' - " + IntToString(nChoice));
while(sChoice != "")
{
// Add the choice
AddChoice(sChoice, nChoice, oMeldshaper);
// Get next
sChoice = GetLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + (sPrev = sChoice));
nChoice = GetLocalInt (oMeldshaper, "PRC_MidnightConvo_List_" + sChoice);
if(DEBUG_LIST) DoDebug("Next is: '" + sChoice + "' - " + IntToString(nChoice) + "; previous = '" + sPrev + "'");
// Delete the already handled data
DeleteLocalString(oMeldshaper, "PRC_MidnightConvo_List_Next_" + sPrev);
DeleteLocalInt (oMeldshaper, "PRC_MidnightConvo_List_" + sPrev);
}
DeleteLocalInt(oMeldshaper, "PRC_MidnightConvo_ListInited");
}
void main()
{
object oMeldshaper = GetPCSpeaker();
int nValue = GetLocalInt(oMeldshaper, DYNCONV_VARIABLE);
int nStage = GetStage(oMeldshaper);
int nClass = GetMeldshapingClass(oMeldshaper);
string sMeldFile = GetMeldFile();
// 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)
{
if(DEBUG) DoDebug("moi_midnightcnv: Running setup stage for stage " + IntToString(nStage));
// Check if this stage is marked as already set up
// This stops list duplication when scrolling
if(!GetIsStageSetUp(nStage, oMeldshaper))
{
if(DEBUG) DoDebug("moi_midnightcnv: Stage was not set up already");
if(nStage == STAGE_SELECT_POWER)
{
if(DEBUG) DoDebug("moi_midnightcnv: Building power selection");
int i, nPowerLevel;
int nMaxLevel = GetMaxEssentiaCapacityFeat(oMeldshaper);
string sFeatID;
for(i = 14001; i < 14260 ; i++)
{
nPowerLevel = StringToInt(Get2DACache("spells", "Innate", i));
//Due to the way the 2das are structured, we know that once
//the level of a read evocation is greater than the maximum castable
//it'll never be lower again. Therefore, we can skip reading the
//evocations that wouldn't be shown anyway.
if(nPowerLevel > nMaxLevel)
break;
if(GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", i))) != "") // Non-blank row
{
if(SORT) AddToTempList(oMeldshaper, GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", i))), i);
else AddChoice(GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", i))), i, oMeldshaper);
}
}
}
else if(nStage == STAGE_SELECT_ESSENTIA_POWER)
{
if(DEBUG) DoDebug("moi_midnightcnv: Building essentia selection");
// Build the confirmation query
int nPower = GetLocalInt(oMeldshaper, "nPower");
SetHeader("How much do you want to invest into "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nPower)))+"?");
int i;
int nMin = PRCMin(GetMaxEssentiaCapacityFeat(oMeldshaper), StringToInt(Get2DACache("spells", "Innate", nPower)));
for(i = 1; i <= nMin; i++)
{
AddChoice(IntToString(i), i, oMeldshaper);
}
}
else if(nStage == STAGE_CONFIRM_SELECTION_POWER)
{
if(DEBUG) DoDebug("moi_midnightcnv: Building selection confirmation");
// Build the confirmation query
int nPower = GetLocalInt(oMeldshaper, "nPower");
string sToken = "You have chosen to invest "+IntToString(GetLocalInt(oMeldshaper, "nEssentia"))+" essentia into "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nPower)))+"."+ "\n\n";
sToken += GetStringByStrRef(STRREF_SELECTED_HEADER2); // "Is this correct?"
SetHeader(sToken);
AddChoice(GetStringByStrRef(STRREF_YES), TRUE, oMeldshaper); // "Yes"
AddChoice(GetStringByStrRef(STRREF_NO), FALSE, oMeldshaper); // "No"
}
}
// Do token setup
SetupTokens();
}
else if(nValue == DYNCONV_EXITED)
{
if(DEBUG) DoDebug("moi_midnightcnv: Running exit handler");
// End of conversation cleanup
DeleteLocalInt(oMeldshaper, "nPower");
DeleteLocalInt(oMeldshaper, "nEssentia");
}
else if(nValue == DYNCONV_ABORTED)
{
// This section should never be run, since aborting this conversation should
// always be forbidden and as such, any attempts to abort the conversation
// should be handled transparently by the system
}
// Handle PC response
else
{
int nChoice = GetChoice(oMeldshaper);
if(DEBUG) DoDebug("moi_midnightcnv: Handling PC response, stage = " + IntToString(nStage) + "; nChoice = " + IntToString(nChoice) + "; choice text = '" + GetChoiceText(oMeldshaper) + "'");
if(nStage == STAGE_SELECT_POWER)
{
if(DEBUG) DoDebug("moi_midnightcnv: Type selected");
SetLocalInt(oMeldshaper, "nPower", nChoice);
MarkStageNotSetUp(STAGE_SELECT_POWER, oMeldshaper);
}
else if(nStage == STAGE_SELECT_ESSENTIA_POWER)
{
if(DEBUG) DoDebug("moi_midnightcnv: Feat Essentia selected");
SetLocalInt(oMeldshaper, "nEssentia", nChoice);
nStage = STAGE_CONFIRM_SELECTION_POWER;
MarkStageNotSetUp(STAGE_SELECT_ESSENTIA_POWER, oMeldshaper);
}
else if(nStage == STAGE_CONFIRM_SELECTION_POWER)
{
if (nChoice)
{
SetLocalInt(oMeldshaper, "MidnightAugPower", GetLocalInt(oMeldshaper, "nPower"));
InvestEssentiaFeat(oMeldshaper, FEAT_MIDNIGHT_AUGMENTATION, GetLocalInt(oMeldshaper, "nEssentia"));
DeleteLocalInt(oMeldshaper, "nPower");
DeleteLocalInt(oMeldshaper, "nEssentia");
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
}
else
{
nStage = STAGE_SELECT_POWER;
}
MarkStageNotSetUp(STAGE_CONFIRM_SELECTION_POWER, oMeldshaper);
}
if(DEBUG) DoDebug("moi_midnightcnv: New stage: " + IntToString(nStage));
// Store the stage value. If it has been changed, this clears out the choices
SetStage(nStage, oMeldshaper);
}
}