Added nwnds_scripts hakfile

Added nwnds_scripts hakfile for PRC scripts that need to be overridden.
This commit is contained in:
Jaysyn904 2021-08-24 21:02:02 -04:00
parent 0f6ae7f57d
commit 1409bd7a97
29 changed files with 5460 additions and 1 deletions

View File

@ -103,9 +103,14 @@
"CompileModels": false
},
{
"Name": tmd19a_deepcave",
"Name": "tmd19a_deepcave",
"Path": "./tmd19a_deepcave/",
"CompileModels": false
},
{
"Name": "nwnds_scripts",
"Path": "./nwnds_scripts/",
"CompileModels": false
},
]
}

Binary file not shown.

View File

@ -0,0 +1,313 @@
//:://////////////////////////////////////////////
//:: prc_et_grblast.nss
//:://////////////////////////////////////////////
/** @file
Spell selection for eldritch theurge's greatreach blast ability
Handles the dynamic convo *and* the quickselects
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_sp_func"
#include "inc_dynconv"
#include "inv_inc_invfunc"
//#include "inc_newspellbook"
/* Constant defintions */
const int STAGE_ENTRY = 0;
const int STAGE_SLOT = 1;
const int STAGE_LVL0 = 10;
const int STAGE_LVL9 = 20;
/* Aid functions */
void PopulateList(object oPC, int nLevel, int nClass)
{
int i = 0, MaxValue = 0, nSpellID, nChoice = 1;
if(nClass == CLASS_TYPE_WIZARD
|| nClass == CLASS_TYPE_DEFILER //NWN Dark Sun Class
|| (nClass == CLASS_TYPE_SORCERER && GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK)))
{
string sFile = "cls_spell_sorc";
object oToken = GetObjectByTag("SpellLvl_9_Level_" + IntToString(nLevel));
MaxValue = array_get_size(oToken, "Lkup");
//DoDebug("ET PopulateList: nClass = "+IntToString(nClass));
//DoDebug("ET PopulateList: nLevel = "+IntToString(nLevel));
//DoDebug("ET PopulateList: MaxValue = "+IntToString(MaxValue));
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", array_get_int(oToken, "Lkup", i)));
if(GetHasSpell(nSpellID, oPC))
{
if(IsTouchSpell(nSpellID))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
}
i++;
}
}
else if(nClass == CLASS_TYPE_BARD && GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK))
{
string sFile = "cls_spell_bard";
object oToken = GetObjectByTag("SpellLvl_1_Level_" + IntToString(nLevel));
MaxValue = array_get_size(oToken, "Lkup");
//DoDebug("ET PopulateList: MaxValue = "+IntToString(MaxValue));
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", array_get_int(oToken, "Lkup", i)));
if(GetHasSpell(nSpellID, oPC))
{
if(IsTouchSpell(nSpellID))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
}
i++;
}
}
else
{
string sFile = GetFileForClass(nClass);
string sArray = "NewSpellbookMem_" + IntToString(nClass);
// if we ever add another arcane caster with prepared spellbook
// uncomment all following lines
//int nSpellbookType = GetSpellbookTypeForClass(nClass);
//if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
int nCount = persistant_array_get_int(oPC, sArray, nLevel);
//DoDebug("ET PopulateList: nCount = "+IntToString(nCount));
if(nCount)
{
MaxValue = persistant_array_get_size(oPC, "Spellbook"+IntToString(nClass));
while(i < MaxValue)
{
int nNewSpellbookID = persistant_array_get_int(oPC, "Spellbook"+IntToString(nClass), i);
if(nLevel == StringToInt(Get2DACache(sFile, "Level", nNewSpellbookID))
&& GetHasFeat(StringToInt(Get2DACache(sFile, "FeatID", nNewSpellbookID)), oPC))
{
int nRealSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nNewSpellbookID));
if(IsTouchSpell(nRealSpell))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice), nLevel);
SetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
}
i++;
}
}
}
/*else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
{
string sArrayIDX = "SpellbookIDX" + IntToString(nLevel) + "_" + IntToString(nClass);
MaxValue = persistant_array_get_size(oPC, sArrayIDX);
while(i < MaxValue)
{
int nNewSpellbookID = persistant_array_get_int(oPC, sArrayIDX, i);
int nCount = persistant_array_get_int(oPC, sArray, nNewSpellbookID);
if(nCount)
{
int nRealSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nNewSpellbookID));
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice), nNewSpellbookID);
SetLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "EF_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
i++;
}
}*/
}
SetDefaultTokens();
DeleteLocalInt(oPC, "DynConv_Waiting");
FloatingTextStringOnCreature("*Done*", oPC, FALSE);
}
void main()
{
object oPC = OBJECT_SELF;
int nID = GetSpellId();
int nValue = GetLocalInt(GetPCSpeaker(), DYNCONV_VARIABLE);
//SendMessageToPC(oPC, "inv_et_grblst.nss:" + IntToString(nID) + " nVal:"+ IntToString(nValue));
if (nValue != 0) {
// do conversation
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
*/
// The stage is used to determine the active conversation node.
// 0 is the entry node.
int nStage = GetStage(oPC);
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 show in order added
if(nStage == STAGE_ENTRY)
{
SetHeader("Select Spell Level:");
if(!GetLocalInt(oPC, "PRC_ArcSpell1")) AddChoice(GetStringByStrRef(690), 1, oPC);//"Level 1"
if(!GetLocalInt(oPC, "PRC_ArcSpell2")) AddChoice(GetStringByStrRef(725), 2, oPC);//"Level 2"
if(!GetLocalInt(oPC, "PRC_ArcSpell3")) AddChoice(GetStringByStrRef(687), 3, oPC);//"Level 3"
if(!GetLocalInt(oPC, "PRC_ArcSpell4")) AddChoice(GetStringByStrRef(684), 4, oPC);//"Level 4"
if(!GetLocalInt(oPC, "PRC_ArcSpell5")) AddChoice(GetStringByStrRef(1026), 5, oPC);//"Level 5"
if(!GetLocalInt(oPC, "PRC_ArcSpell6")) AddChoice(GetStringByStrRef(1014), 6, oPC);//"Level 6"
if(!GetLocalInt(oPC, "PRC_ArcSpell7")) AddChoice(GetStringByStrRef(2214), 7, oPC);//"Level 7"
if(!GetLocalInt(oPC, "PRC_ArcSpell8")) AddChoice(GetStringByStrRef(2215), 8, oPC);//"Level 8"
if(!GetLocalInt(oPC, "PRC_ArcSpell9")) AddChoice(GetStringByStrRef(2216), 9, oPC);//"Level 9"
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
else if (nStage >= STAGE_LVL0 && nStage <= STAGE_LVL9)
{
// Set the header
SetHeader("Select Spell:");
int nLevel = nStage - STAGE_LVL0;
SetLocalInt(oPC, "DynConv_Waiting", TRUE);
PopulateList(oPC, nLevel, GetETArcaneClass(oPC));
MarkStageSetUp(nStage, oPC);
}
else if (nStage = STAGE_SLOT)
{
SetHeader("Select QuickSlot:");
AddChoice("Slot 1", 1, oPC);
AddChoice("Slot 2", 2, oPC);
AddChoice("Slot 3", 3, oPC);
AddChoice("Slot 4", 4, oPC);
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
//add more stages for more nodes with Else If clauses
}
// Do token setup
SetupTokens();
}
// End of conversation cleanup
// Abort conversation cleanup.
else if(nValue == DYNCONV_EXITED
|| nValue == DYNCONV_ABORTED)
{
int nChoice = 1;
while(GetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice)))
{
DeleteLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice));
nChoice++;
}
DeleteLocalInt(oPC, "ET_SPELL_ID");
DeleteLocalInt(oPC, "ET_REAL_SPELL_ID");
DeleteLocalString(oPC, "ET_CLASS_ARRAY_ID");
DeleteLocalInt(oPC, "ET_SPELL_LEVEL_CHOICE");
}
// 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_ENTRY)
{
int nLevel = nChoice;
SetLocalInt(oPC, "ET_SPELL_LEVEL_CHOICE", nLevel);
nStage = STAGE_LVL0 + nChoice;
// Move to another stage based on response, for example
//nStage = STAGE_QUUX;
}
else if (nStage >= STAGE_LVL0 && nStage <= STAGE_LVL9)
{
MarkStageNotSetUp(nStage, oPC);
int nSpell = GetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice));
int nRealSpell = GetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice));
string sArray = GetLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice));
SetLocalInt(oPC, "ET_SPELL_ID", nSpell);
SetLocalInt(oPC, "ET_REAL_SPELL_ID", nRealSpell);
SetLocalString(oPC, "ET_CLASS_ARRAY_ID", sArray);
nStage = STAGE_SLOT;
}
else if (nStage = STAGE_SLOT)
{
int nSpell = GetLocalInt(oPC, "ET_SPELL_ID");
int nRealSpell = GetLocalInt(oPC, "ET_REAL_SPELL_ID");
string sArray = GetLocalString(oPC, "ET_CLASS_ARRAY_ID");
int nLevel = GetLocalInt(oPC, "ET_SPELL_LEVEL_CHOICE");
SetLocalInt(oPC, "ET_GR_SPELL_QUICK" + IntToString(nChoice), nSpell);
SetLocalInt(oPC, "ET_GR_REAL_SPELL_QUICK" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "ET_GR_SPELL_QUICK" + IntToString(nChoice), sArray);
SetLocalInt(oPC, "ET_GR_SPELL_QUICK" + IntToString(nChoice) + "LVL", nLevel);
nStage = STAGE_ENTRY;
}
// Store the stage value. If it has been changed, this clears out the choices
SetStage(nStage, oPC);
}
}
else if(nID == INVOKE_GR_SPELL_SELECT_CONVO)
{
DelayCommand(0.5, StartDynamicConversation("inv_et_grblst", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, FALSE, oPC));
}
else
{
string sSlotNo;
switch(nID)
{
case INVOKE_GR_SPELL_SELECT_QUICK1: sSlotNo = "1"; break;
case INVOKE_GR_SPELL_SELECT_QUICK2: sSlotNo = "2"; break;
case INVOKE_GR_SPELL_SELECT_QUICK3: sSlotNo = "3"; break;
case INVOKE_GR_SPELL_SELECT_QUICK4: sSlotNo = "4"; break;
}
if(sSlotNo == "")
return;
int nSpell = GetLocalInt(oPC, "ET_GR_SPELL_QUICK"+sSlotNo);
int nLevel = GetLocalInt(oPC, "ET_GR_SPELL_QUICK"+sSlotNo+"LVL");
int nRealSpell = GetLocalInt(oPC, "ET_GR_REAL_SPELL_QUICK"+sSlotNo);
if(nRealSpell == -1) nRealSpell = nSpell;
string sArray = GetLocalString(oPC, "ET_GR_SPELL_QUICK"+sSlotNo);
int nUses = sArray == "" ? GetHasSpell(nSpell, oPC) : persistant_array_get_int(oPC, sArray, nSpell);
if(nUses)
{
SetLocalInt(oPC, "ET_SPELL_CURRENT", (nSpell+1));
SetLocalInt(oPC, "ET_SPELL_CURRENT_LVL", nLevel);
SetLocalInt(oPC, "ET_REAL_SPELL_CURRENT", nRealSpell);
SetLocalString(oPC, "ET_SPELL_CURRENT", sArray);
FloatingTextStringOnCreature("*Greatreach Blast: " + GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell))) + "*", oPC, FALSE);
FloatingTextStringOnCreature("*You have " + IntToString(nUses) + " uses left*", oPC, FALSE);
}
else
{
FloatingTextStringOnCreature("No uses or preperations left for selected spell!", oPC, FALSE);
}
}
}

Binary file not shown.

View File

@ -0,0 +1,247 @@
//:://////////////////////////////////////////////
//:: inv_et_spellblst.nss
//:://////////////////////////////////////////////
/** @file
Spell selection for eldritch theurge's spellblast ability
Handles the dynamic convo *and* the quickselects
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "inv_invoc_const"
#include "inc_dynconv"
#include "inv_inc_invfunc"
/* Constant defintions */
const int STAGE_ENTRY = 0;
const int STAGE_SLOT = 1;
/* Aid functions */
void PopulateList(object oPC, int nClass)
{
string sFile = "et_spellblast";
int MaxValue = StringToInt(Get2DACache(sFile, "Label", 0));
int i = 1, nSpellID, nChoice = 1;
if(nClass == CLASS_TYPE_WIZARD
|| nClass == CLASS_TYPE_DEFILER
|| (nClass == CLASS_TYPE_SORCERER && GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
|| (nClass == CLASS_TYPE_BARD && GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK)))
{
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "SpellID", i));
if(GetHasSpell(nSpellID, oPC))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
i++;
}
}
else
{
string sClassFile = GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED ? "":
GetFileForClass(nClass);
string sArray = "NewSpellbookMem_" + IntToString(nClass);
int nSpellbookID, nLevel, nCount;
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "SpellID", i));
nSpellbookID = RealSpellToSpellbookID(nClass, nSpellID);
DoDebug(Get2DACache(sFile, "Label", i)+" = "+IntToString(nSpellbookID));
if(nSpellbookID != -1)
{
/* // if we ever add another arcane caster with prepared spellbook
// uncomment all following lines
if(sClassFile == "")
{
nCount = persistant_array_get_int(oPC, sArray, nSpellbookID);
if(nCount)
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice), nSpellbookID);
SetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
}
else*/
{
if(GetHasFeat(StringToInt(Get2DACache(sClassFile, "FeatID", nSpellbookID)), oPC))
{
nLevel = StringToInt(Get2DACache(sClassFile, "Level", nSpellbookID));
nCount = persistant_array_get_int(oPC, sArray, nLevel);
if(nCount)
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice), nLevel);
SetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
}
}
}
i++;
}
}
SetDefaultTokens();
DeleteLocalInt(oPC, "DynConv_Waiting");
FloatingTextStringOnCreature("*Done*", oPC, FALSE);
}
void main()
{
object oPC = OBJECT_SELF;
int nID = GetSpellId();
int nValue = GetLocalInt(GetPCSpeaker(), DYNCONV_VARIABLE);
//SendMessageToPC(oPC, "inv_et_spellblst:" + IntToString(nID) + " nVal:"+ IntToString(nValue));
if (nValue != 0) {
// do conversation
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
*/
// The stage is used to determine the active conversation node.
// 0 is the entry node.
int nStage = GetStage(oPC);
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 show in order added
if(nStage == STAGE_ENTRY)
{
// Set the header
SetHeader("Select Spell:");
SetLocalInt(oPC, "DynConv_Waiting", TRUE);
PopulateList(oPC, GetETArcaneClass(oPC));
MarkStageSetUp(nStage, oPC);
}
else if (nStage = STAGE_SLOT)
{
SetHeader("Select QuickSlot:");
AddChoice("Slot 1", 1, oPC);
AddChoice("Slot 2", 2, oPC);
AddChoice("Slot 3", 3, oPC);
AddChoice("Slot 4", 4, oPC);
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
//add more stages for more nodes with Else If clauses
}
// Do token setup
SetupTokens();
}
// Abort 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_ABORTED
|| nValue == DYNCONV_EXITED)
{
int nChoice = 1;
while(GetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice)))
{
DeleteLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice));
nChoice++;
}
DeleteLocalInt(oPC, "ET_SPELL_ID");
DeleteLocalInt(oPC, "ET_REAL_SPELL_ID");
DeleteLocalString(oPC, "ET_CLASS_ARRAY_ID");
DeleteLocalInt(oPC, "ET_SPELL_LEVEL_CHOICE");
}
// 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_ENTRY)
{
MarkStageNotSetUp(nStage, oPC);
int nSpell = GetLocalInt(oPC, "ET_SPELL_CHOICE_" + IntToString(nChoice));
int nRealSpell = GetLocalInt(oPC, "ET_REAL_SPELL_CHOICE_" + IntToString(nChoice));
string sArray = GetLocalString(oPC, "ET_CLASS_ARRAY_" + IntToString(nChoice));
SetLocalInt(oPC, "ET_SPELL_ID", nSpell);
SetLocalInt(oPC, "ET_REAL_SPELL_ID", nRealSpell);
SetLocalString(oPC, "ET_CLASS_ARRAY_ID", sArray);
nStage = STAGE_SLOT;
}
else if (nStage = STAGE_SLOT)
{
MarkStageNotSetUp(nStage, oPC);
int nSpell = GetLocalInt(oPC, "ET_SPELL_ID");
int nRealSpell = GetLocalInt(oPC, "ET_REAL_SPELL_ID");
string sArray = GetLocalString(oPC, "ET_CLASS_ARRAY_ID");
int nLevel = GetLocalInt(oPC, "ET_SPELL_LEVEL_CHOICE");
SetLocalInt(oPC, "ET_SPELL_QUICK" + IntToString(nChoice), nSpell);
SetLocalInt(oPC, "ET_REAL_SPELL_QUICK" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "ET_SPELL_QUICK" + IntToString(nChoice), sArray);
SetLocalInt(oPC, "ET_SPELL_QUICK" + IntToString(nChoice) + "LVL", nLevel);
nStage = STAGE_ENTRY;
}
// Store the stage value. If it has been changed, this clears out the choices
SetStage(nStage, oPC);
}
}
else if(nID == INVOKE_SB_SPELL_SELECT_CONVO)
{
DelayCommand(0.5, StartDynamicConversation("inv_et_spellblst", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, FALSE, oPC));
}
else
{
string sSlotNo;
switch(nID)
{
case INVOKE_SB_SPELL_SELECT_QUICK1: sSlotNo = "1"; break;
case INVOKE_SB_SPELL_SELECT_QUICK2: sSlotNo = "2"; break;
case INVOKE_SB_SPELL_SELECT_QUICK3: sSlotNo = "3"; break;
case INVOKE_SB_SPELL_SELECT_QUICK4: sSlotNo = "4"; break;
}
if(sSlotNo == "")
return;
int nSpell = GetLocalInt(oPC, "ET_SPELL_QUICK"+sSlotNo);
int nLevel = GetLocalInt(oPC, "ET_SPELL_QUICK"+sSlotNo+"LVL");
int nRealSpell = GetLocalInt(oPC, "ET_REAL_SPELL_QUICK"+sSlotNo);
if(nRealSpell == -1) nRealSpell = nSpell;
string sArray = GetLocalString(oPC, "ET_SPELL_QUICK"+sSlotNo);
SetLocalInt(oPC, "ET_SPELL_CURRENT", (nSpell+1));
SetLocalInt(oPC, "ET_SPELL_CURRENT_LVL", nLevel);
SetLocalInt(oPC, "ET_REAL_SPELL_CURRENT", nRealSpell);
SetLocalString(oPC, "ET_SPELL_CURRENT", sArray);
int nUses = sArray == "" ? GetHasSpell(nSpell, oPC) : persistant_array_get_int(oPC, sArray, nSpell);
FloatingTextStringOnCreature("*Spellblast: " + GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell))) + "*", oPC, FALSE);
FloatingTextStringOnCreature("*You have " + IntToString(nUses) + " uses left*", oPC, FALSE);
}
}

Binary file not shown.

View File

@ -0,0 +1,343 @@
//::///////////////////////////////////////////////
//:: Summon Familiar
//:: NW_S2_Familiar
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
This spell summons an Arcane casters familiar
*/
//:://////////////////////////////////////////////
//:: Created By: Preston Watamaniuk
//:: Created On: Sept 27, 2001
//:://////////////////////////////////////////////
#include "prc_class_const"
#include "inc_dynconv"
//#include "inc_dispel"
#include "prc_inc_assoc"
#include "prc_inc_template"
const int PACKAGE_ELEMENTAL_STR = PACKAGE_ELEMENTAL;
const int PACKAGE_ELEMENTAL_DEX = PACKAGE_FEY;
void BondedSummoner(object oPC);
void SummonPnPFamiliar(object oPC, int nType);
void SummonPRCFamiliar(object oPC);
void DreadNecro(object oPC);
void MasterShadow(object oPC);
void main()
{
object oPC = OBJECT_SELF;
if(GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC))
{
//handles summoning of shadow familiar
MasterShadow(oPC);
}
else if(GetLevelByClass(CLASS_TYPE_BONDED_SUMMONNER, oPC))
{
//handles summoning of elemental familiar
BondedSummoner(oPC);
}
else if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC) > 6)
{
//handles dread necromancer familiar
DreadNecro(oPC);
}
else if(GetLevelByClass(CLASS_TYPE_CELEBRANT_SHARESS, oPC))
{
//It's a PnP Cat familiar
SummonPnPFamiliar(oPC, 6);
}
else if(GetPRCSwitch(PRC_PNP_FAMILIARS))
{
//handles summoning of pnp familiar
SummonPnPFamiliar(oPC, -1);
}
else if(GetPRCSwitch(PRC_FAMILIARS)//the switch is set
|| (!GetLevelByClass(CLASS_TYPE_WIZARD, oPC) || !GetLevelByClass(CLASS_TYPE_DEFILER, oPC)
&& !GetLevelByClass(CLASS_TYPE_SORCERER, oPC)))//or no bio-ware familiar
{
//handles summoning of familiars for PRC classes (witch, hexblade)
SummonPRCFamiliar(oPC);
}
else
//summon bio-ware familiar
SummonFamiliar();
object oFam;
int i;
int bDiabol = GetLevelByClass(CLASS_TYPE_DIABOLIST, oPC) >= 2;
int bPseudonat = GetHasFeat(FEAT_PSEUDONATURAL_FAMILIAR, oPC);
for(i = 1; i <= 5; i++)
{
oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, i);
if(bDiabol && GetAppearanceType(oFam) != APPEARANCE_TYPE_IMP)
DestroyAssociate(oFam);
if(bPseudonat)
{
object oFamSkin = GetPCSkin(oFam);
ApplyPseudonatural(oFam, oFamSkin);
}
}
}
void BondedSummoner(object oPC)
{
object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_BONDED_FAMILIAR);
//remove previously summoned familiar
if(GetIsObjectValid(oFam))
DestroyAssociate(oFam);
string sResRef, sElem;
int nPackage;
if(GetHasFeat(FEAT_BONDED_AIR, oPC))
{
sElem = "air";
nPackage = PACKAGE_ELEMENTAL_DEX;
}
else if(GetHasFeat(FEAT_BONDED_EARTH, oPC))
{
sElem = "earth";
nPackage = PACKAGE_ELEMENTAL_STR;
}
else if(GetHasFeat(FEAT_BONDED_FIRE, oPC))
{
sElem = "fire";
nPackage = PACKAGE_ELEMENTAL_DEX;
}
else if(GetHasFeat(FEAT_BONDED_WATER, oPC))
{
sElem = "water";
nPackage = PACKAGE_ELEMENTAL_STR;
}
int nLevel = GetLevelByClass(CLASS_TYPE_BONDED_SUMMONNER, oPC);
switch(nLevel)
{
case 1:
case 2: sResRef = "x1_s_"+sElem+"small"; break;//this is the 4HD version in the SRD, which is medium
case 3:
case 4: sResRef = "prc_s_"+sElem+"large"; break;
case 5:
case 6: sResRef = "nw_s_"+sElem+"huge"; break;
case 7:
case 8: sResRef = "nw_s_"+sElem+"great"; break;
case 9:
case 10: sResRef = "nw_s_"+sElem+"elder"; break;
}
oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_BONDED_FAMILIAR);
AddAssociate(oPC, oFam);
//set its name
string sName = GetFamiliarName(oPC);
if(sName == "")
sName = GetName(oPC)+ "'s Familiar";
SetName(oFam, sName);
//apply bonus based on level
int nArcaneLevel = GetPrCAdjustedCasterLevelByType(TYPE_ARCANE) + nLevel/2;
object oSkin = GetPCSkin(oFam);
//in all cases
IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(ITEM_PROPERTY_IMPROVED_EVASION));
//9+ levels
if(nArcaneLevel >= 9)
IPSafeAddItemProperty(oSkin, ItemPropertyBonusSpellResistance(GetSRByValue(nArcaneLevel+5)));
//11+ levels
if(nArcaneLevel >= 11)
ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectMovementSpeedIncrease(30)), oFam);
//add their ondeath special
AddEventScript(oFam, EVENT_NPC_ONDEATH, "prc_bond_death");
/*int nAdjustLevel = nArcaneLevel - GetHitDice(oFam);
int n;
for(n = 1; nAdjustLevel >= n; n++)
LevelUpHenchman(oFam, CLASS_TYPE_INVALID, TRUE, nPackage);*/
//set it so the spell-share detects it
SetLocalObject(oPC, "Familiar", oFam);
}
void DreadNecro(object oPC)
{
object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_DN_FAMILIAR);
//remove previously summoned familiar
if(GetIsObjectValid(oFam))
DestroyAssociate(oFam);
int bPnP = GetPRCSwitch(PRC_PNP_FAMILIARS);
int nAlign = GetAlignmentLawChaos(oPC);
string sResRef;
if(bPnP)
{
sResRef = nAlign == ALIGNMENT_LAWFUL ? "prc_pnpfam_imp" : nAlign == ALIGNMENT_CHAOTIC ? "prc_pnpfam_qust" : "prc_pnpfam_varg";
}
else
{
int nDNLevel = GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oPC);
string sTemp = nDNLevel < 10 ? "0"+IntToString(nDNLevel) : IntToString(nDNLevel);
sResRef = nAlign == ALIGNMENT_LAWFUL ? "NW_FM_IMP"+sTemp : nAlign == ALIGNMENT_CHAOTIC ? "NW_FM_QUAS"+sTemp : "X2_FM_EYE0"+sTemp;
}
oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_DN_FAMILIAR);
//add the familiar as a henchman
AddAssociate(oPC, oFam);
//set its name
string sName = GetFamiliarName(oPC);
if(sName == "")
sName = GetName(oPC)+ "'s Familiar";
SetName(oFam, sName);
if(bPnP) ApplyPnPFamiliarProperties(oPC, oFam);
}
void SummonPnPFamiliar(object oPC, int nType)
{
IncrementRemainingFeatUses(oPC, FEAT_SUMMON_FAMILIAR);
//check if already has a familiar
object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_PNP_FAMILIAR);
object oFamToken = GetItemPossessedBy(oPC, "prc_pnp_familiar");
int nFamiliarType;
if (nType > 0)
nFamiliarType = nType;
else
nFamiliarType = GetPersistantLocalInt(oPC, "PnPFamiliarType");
if(!nFamiliarType)
{
StartDynamicConversation("prc_pnp_fam_conv", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, TRUE, oPC);
return;
}
if(GetIsObjectValid(oFam))
{
//reapply familiar bonuses
PRCRemoveEffectsFromSpell(oFam, 318);//318 = summon familiar
}
else
{
if(GetIsObjectValid(oFamToken))
{
DestroyObject(oFamToken, 0.1f);
}
//spawn the familiar
string sResRef = Get2DACache("prc_familiar", "BASERESREF", nFamiliarType);
oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_PNP_FAMILIAR);
//set its name
string sName = GetFamiliarName(oPC);
if(sName == "")
sName = GetName(oPC)+ "'s Familiar";
SetName(oFam, sName);
//add the familiar as a henchman
AddAssociate(oPC, oFam);
}
//this is the masters bonus
effect eBonus = GetMasterBonus(nFamiliarType);
eBonus = SupernaturalEffect(eBonus);
if(!GetHasFeatEffect(FEAT_SUMMON_FAMILIAR, oPC))
{
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eBonus, oPC);
CheckIsValidFamiliar(oPC, eBonus);
}
ApplyPnPFamiliarProperties(oPC, oFam);
if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) ApplyTemplateToObject(TEMPLATE_DARK, oFam);
}
void SummonPRCFamiliar(object oPC)
{
object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_HENCHMAN_COMPANION);
//remove previously summoned familiar
if(GetIsObjectValid(oFam))
DestroyAssociate(oFam);
int nFamiliarType = GetPersistantLocalInt(oPC, "FamiliarType");
if(!nFamiliarType)
{
StartDynamicConversation("prc_pnp_fam_conv", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, TRUE, oPC);
IncrementRemainingFeatUses(oPC, FEAT_SUMMON_FAMILIAR);
return;
}
else
nFamiliarType--;
int nFamLevel = GetLevelByClass(CLASS_TYPE_WIZARD);
nFamLevel = max(nFamLevel, GetLevelByClass(CLASS_TYPE_DEFILER)); // NWN Dark Sun class
nFamLevel = max(nFamLevel, GetLevelByClass(CLASS_TYPE_SORCERER));
nFamLevel = max(nFamLevel, GetLevelByClass(CLASS_TYPE_WITCH));
nFamLevel = max(nFamLevel, GetLevelByClass(CLASS_TYPE_HEXBLADE));
nFamLevel += GetLevelByClass(CLASS_TYPE_ALIENIST);
if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) nFamLevel = GetLevelByTypeArcane(oPC) + GetShadowcasterLevel(oPC); // For the purpose of determining familiar abilities that depend on your arcane caster level, your levels in all classes that allow you to cast mysteries or arcane spells stack
string sTemp = Get2DACache("hen_familiar", "BASERESREF", nFamiliarType);
string sResRef = nFamLevel < 10 ? sTemp+"0"+IntToString(nFamLevel) : sTemp+IntToString(nFamLevel);
//spawn the familiar
oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sResRef, PRCGetSpellTargetLocation(), NPC_HENCHMAN_COMPANION);
AddAssociate(oPC, oFam);
if (GetHasFeat(FEAT_SHADOW_FAMILIAR, oPC)) ApplyTemplateToObject(TEMPLATE_DARK, oFam);
//set its name
string sName = GetFamiliarName(oPC);
if(sName == "")
sName = GetName(oPC)+ "'s Familiar";
SetName(oFam, sName);
}
void MasterShadow(object oPC)
{
object oFam = GetAssociateNPC(ASSOCIATE_TYPE_FAMILIAR, oPC, NPC_MS_ELEMENTAL);
//remove previously summoned familiar
if(GetIsObjectValid(oFam))
DestroyAssociate(oFam);
int nLevel = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
string sShadow = "shd_shdelem_med";
if (nLevel >= 10)
sShadow = "shd_shdelem_med4";
else if (nLevel >= 7)
sShadow = "shd_shdelem_med3";
else if (nLevel >= 4)
sShadow = "shd_shdelem_med2";
oFam = CreateLocalNPC(oPC, ASSOCIATE_TYPE_FAMILIAR, sShadow, PRCGetSpellTargetLocation(), NPC_MS_ELEMENTAL);
AddAssociate(oPC, oFam);
//set its name
string sName = GetFamiliarName(oPC);
if(sName == "")
sName = GetName(oPC)+ "'s Shadow Elemental";
SetName(oFam, sName);
itemproperty ipIP;
object oSkin = GetPCSkin(oFam);
if (nLevel >= 10)
ipIP =ItemPropertyDamageImmunity(IP_CONST_DAMAGETYPE_COLD,IP_CONST_DAMAGEIMMUNITY_100_PERCENT);
else if (nLevel >= 6)
ipIP =ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_20);
else if (nLevel >= 4)
ipIP =ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_10);
else if (nLevel >= 2)
ipIP =ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGERESIST_5);
IPSafeAddItemProperty(oSkin, ipIP, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE);
if (nLevel >= 3) // Grow to size large
SetCreatureAppearanceType(oFam, APPEARANCE_TYPE_SHADOW_FIEND);
}

Binary file not shown.

View File

@ -0,0 +1,556 @@
//:://////////////////////////////////////////////
//:: 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
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#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 = array_get_size(oToken, sSpellbook);
if (nSize < 0)
{
array_create(oToken, sSpellbook);
nSize = 0;
}
//check for learnable spells
object oToken_Class = GetObjectByTag("SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nLevel));
int nSpells_Total = array_get_size(oToken_Class, "Lkup");
int i;
for(i = 0; i < nSpells_Total; i++)
{
int nSpellbookID = array_get_int(oToken_Class, "Lkup", i);
if(Get2DAString(sFile, "AL", nSpellbookID) != "1")
{
array_set_int(oToken, 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;
//Raks cast as sorcs
if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
nLevel = GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC);
// else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_BOZAK) //Bozaks cast as sorcs
// nLevel = GetLevelByClass(CLASS_TYPE_DRAGON, oPC);
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_DRIDER) //Driders cast as sorcs
nLevel = GetLevelByClass(CLASS_TYPE_ABERRATION, 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 oHideToken, 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 = array_get_int(oHideToken, 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(oHideToken, 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 = array_get_size(oHideToken, sSpellbook);
DelayCommand(0.0, CopyAMSArray(oHideToken, 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);
int i;
for(i = 1; i <= 3; i++)
{
int nClass = GetClassByPosition(i, oPC);
string sSpellbook;
int nSpellbookType = GetSpellbookTypeForClass(nClass);
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
sSpellbook = "Spellbook"+IntToString(nClass);
int nSize1 = array_get_size(oHideToken, 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 = array_get_size(oHideToken, sSpellbook);
int nSize2 = array_get_size(oAMSToken, sSpellbook);
if(nSize1 > nSize2)
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
}
}
}
}

Binary file not shown.

View File

@ -0,0 +1,116 @@
/* Combat Medic spontaneous heal ability
*
* Created July 17 2005
* Author: GaiaWerewolf
*/
#include "prc_inc_spells"
#include "prc_getbest_inc"
int GetSpontaneousHealBurnableSpell(object oCaster)
{
int nBurnableSpell = -1;
nBurnableSpell = GetBestL6Spell(oCaster, nBurnableSpell);
if(nBurnableSpell == -1)
nBurnableSpell = GetBestL7Spell(oCaster, nBurnableSpell);
if(nBurnableSpell == -1)
nBurnableSpell = GetBestL8Spell(oCaster, nBurnableSpell);
if(nBurnableSpell == -1)
nBurnableSpell = GetBestL9Spell(oCaster, nBurnableSpell);
return nBurnableSpell;
}
void main()
{
//Declare our standard variables
object oCaster = OBJECT_SELF;
int nCasterLvl = GetLevelByTypeDivineFeats(oCaster, SPELL_HEAL);//character is most likely divine caster
int nArcane = GetPrimaryArcaneClass(oCaster);
if(nArcane == CLASS_TYPE_BARD || nArcane == CLASS_TYPE_WITCH)//but we check arcane classes just in case
{
int nTest = GetLevelByTypeArcaneFeats(oCaster, SPELL_HEAL);
if(nTest > nCasterLvl)
nCasterLvl = nTest;
}
int nClass, nLevel, i;
int nBurnableSpell = -1;
int bBioCastersLoopDone = 0;//will prevent running 'GetBestSpell' loops twice
for(i = 1; i <= 3; i++)
{
nClass = GetClassByPosition(i, oCaster);
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS)
{
for(nLevel = 6; nLevel < 10; nLevel++)
{
nBurnableSpell = persistant_array_get_int(oCaster, "NewSpellbookMem_" + IntToString(nClass), nLevel);
if(nBurnableSpell > 0)
break;
}
if(nBurnableSpell > 0)
{
SetLocalInt(oCaster, "DomainCast", -1);
SetLocalInt(oCaster, "NSB_Class", nClass);
SetLocalInt(oCaster, "NSB_SpellLevel", nLevel);
ActionCastSpell(SPELL_HEAL, nCasterLvl, 16 + GetAbilityModifier(ABILITY_WISDOM, oCaster), 0, METAMAGIC_NONE, CLASS_TYPE_INVALID, 0, 0, OBJECT_INVALID, FALSE);
return;
}
}
else if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED)
{
string sFile = GetFileForClass(nClass);
string sArrayIDX, sArray = "NewSpellbookMem_" + IntToString(nClass);
int nSpellbookID, nSpellLevel, MaxValue;
for(nLevel = 6; nLevel < 10; nLevel++)
{
sArrayIDX = "SpellbookIDX" + IntToString(nLevel) + "_" + IntToString(nClass);
MaxValue = persistant_array_get_size(oCaster, sArrayIDX);
int j = 0;
while(j < MaxValue)
{
nSpellbookID = persistant_array_get_int(oCaster, sArrayIDX, j);
nSpellLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookID));
if(nSpellLevel > 5)
{
nBurnableSpell = persistant_array_get_int(oCaster, sArray, nSpellbookID);
if(nBurnableSpell > 0)//escape while loop
break;
}
j++;
}
if(nBurnableSpell > 0)//escape for loop
break;
}
if(nBurnableSpell > 0)
{
SetLocalInt(oCaster, "DomainCast", -1);
SetLocalInt(oCaster, "NSB_Class", nClass);
SetLocalInt(oCaster, "NSB_SpellbookID", nSpellbookID);
ActionCastSpell(SPELL_HEAL, nCasterLvl, 16 + GetAbilityModifier(ABILITY_WISDOM, oCaster), 0, METAMAGIC_NONE, CLASS_TYPE_INVALID, 0, 0, OBJECT_INVALID, FALSE);
return;
}
}
if(((nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER) && persistant_array_get_size(oCaster, "Spellbook" + IntToString(nClass)) != -1) ||//bard/sorcerer *not* using new spellbooks
nClass == CLASS_TYPE_CLERIC || nClass == CLASS_TYPE_DRUID || nClass == CLASS_TYPE_WIZARD || nClass == CLASS_TYPE_DEFILER)//other bioware casters with 6+ spell levels
{
nBurnableSpell = bBioCastersLoopDone ? -1: GetSpontaneousHealBurnableSpell(oCaster);
bBioCastersLoopDone = 1;
if(nBurnableSpell != -1)
{
SetLocalInt(oCaster, "DomainCast", -1);
SetLocalInt(oCaster, "Domain_BurnableSpell", nBurnableSpell + 1);
ActionCastSpell(SPELL_HEAL, nCasterLvl, 16 + GetAbilityModifier(ABILITY_WISDOM, oCaster), 0, METAMAGIC_NONE, CLASS_TYPE_INVALID, 0, 0, OBJECT_INVALID, FALSE);
return;
}
}
}
//if we got here - there's no burnable spells left
FloatingTextStringOnCreature("You have no spells left to trade for a spontaneous heal.", oCaster, FALSE);
}

Binary file not shown.

View File

@ -0,0 +1,252 @@
#include "prc_alterations"
#include "inc_letocommands"
#include "prc_racial_const"
#include "ccc_inc_convo"
// #include "inc_encrypt"
#include "prc_class_const"
void main()
{
//define some varaibles
object oPC = OBJECT_SELF;
int i;
//get some stored data
int nStr = GetLocalInt(oPC, "Str");
int nDex = GetLocalInt(oPC, "Dex");
int nCon = GetLocalInt(oPC, "Con");
int nInt = GetLocalInt(oPC, "Int");
int nWis = GetLocalInt(oPC, "Wis");
int nCha = GetLocalInt(oPC, "Cha");
int nRace = GetLocalInt(oPC, "Race");
int nClass = GetLocalInt(oPC, "Class");
int nHitPoints = GetLocalInt(oPC, "HitPoints");
int nSex = GetLocalInt(oPC, "Gender");
int nOrder = GetLocalInt(oPC, "LawfulChaotic");
int nMoral = GetLocalInt(oPC, "GoodEvil");
int nSkillPointsSaved= GetLocalInt(oPC, "SavedSkillPoints");
int nFamiliar = GetLocalInt(oPC, "Familiar");
int nAnimalCompanion = GetLocalInt(oPC, "Companion");
int nDomain1 = GetLocalInt(oPC, "Domain1");
int nDomain2 = GetLocalInt(oPC, "Domain2");
int nSchool = GetLocalInt(oPC, "School");
int nSpellsPerDay0 = GetLocalInt(oPC, "SpellsPerDay0");
int nSpellsPerDay1 = GetLocalInt(oPC, "SpellsPerDay1");
int nVoiceset = GetLocalInt(oPC, "Soundset");
int nSkin = GetLocalInt(oPC, "Skin");
int nHair = GetLocalInt(oPC, "Hair");
int nTattooColour1 = GetLocalInt(oPC, "TattooColour1");
int nTattooColour2 = GetLocalInt(oPC, "TattooColour2");
//clear existing stuff
string sScript;
sScript += LetoDelete("FeatList");
sScript += LetoDelete("ClassList");
sScript += LetoDelete("LvlStatList");
sScript += LetoDelete("SkillList");
sScript += LetoAdd("FeatList", "", "list");
sScript += LetoAdd("ClassList", "", "list");
sScript += LetoAdd("LvlStatList", "", "list");
sScript += LetoAdd("SkillList", "", "list");
//Sex
sScript += SetGender(nSex);
//Race
sScript += SetRace(nRace);
//Class
sScript += LetoAdd("ClassList/Class", IntToString(nClass), "int");
sScript += LetoAdd("ClassList/[0]/ClassLevel", "1", "short");
sScript += LetoAdd("LvlStatList/LvlStatClass", IntToString(nClass), "byte");
sScript += LetoAdd("LvlStatList/[0]/EpicLevel", "0", "byte");
sScript += LetoAdd("LvlStatList/[0]/LvlStatHitDie", IntToString(nHitPoints), "byte");
sScript += LetoAdd("LvlStatList/[0]/FeatList", "", "list");
sScript += LetoAdd("LvlStatList/[0]/SkillList", "", "list");
//Alignment
sScript += LetoSet("LawfulChaotic", IntToString(nOrder), "byte");
sScript += LetoSet("GoodEvil", IntToString(nMoral), "byte");
//Familiar
//has a random name
if((nClass == CLASS_TYPE_WIZARD ||
nClass == CLASS_TYPE_DEFILER ||
nClass == CLASS_TYPE_SORCERER)
&& !GetPRCSwitch(PRC_PNP_FAMILIARS))
{
sScript += LetoSet("FamiliarType", IntToString(nFamiliar), "int");
if(GetFamiliarName(oPC) == "")
sScript += LetoSet("FamiliarName", RandomName(NAME_FAMILIAR), "string");
}
//Animal Companion
//has a random name
if(nClass == CLASS_TYPE_DRUID)
{
sScript += LetoSet("CompanionType", IntToString(nAnimalCompanion), "int");
if(GetAnimalCompanionName(oPC) == "")
sScript += LetoSet("CompanionName", RandomName(NAME_ANIMAL), "string");
}
//Domains
if(nClass == CLASS_TYPE_CLERIC)
{
// fix for air domain being 0
if (nDomain1 == -1)
nDomain1 = 0;
if (nDomain2 == -1)
nDomain2 = 0;
sScript += LetoAdd("ClassList/[0]/Domain1", IntToString(nDomain1), "byte");
sScript += LetoAdd("ClassList/[0]/Domain2", IntToString(nDomain2), "byte");
}
//Ability Scores
sScript += SetAbility(ABILITY_STRENGTH, nStr);
sScript += SetAbility(ABILITY_DEXTERITY, nDex);
sScript += SetAbility(ABILITY_CONSTITUTION, nCon);
sScript += SetAbility(ABILITY_INTELLIGENCE, nInt);
sScript += SetAbility(ABILITY_WISDOM, nWis);
sScript += SetAbility(ABILITY_CHARISMA, nCha);
//Feats
//Make sure the list exists
//Populate the list from array
for(i=0;i<array_get_size(oPC, "Feats"); i++)
{
string si = IntToString(i);
int nFeatID =array_get_int(oPC, "Feats", i);
if(nFeatID != 0)
{
if(nFeatID == -1)//alertness fix
nFeatID = 0;
DoDebug("Feat array positon "+IntToString(i)+" is "+IntToString(nFeatID));
sScript += LetoAdd("FeatList/Feat", IntToString(nFeatID), "word");
sScript += LetoAdd("LvlStatList/[0]/FeatList/Feat", IntToString(nFeatID), "word");
}
}
//Skills
for (i=0;i<=GetPRCSwitch(FILE_END_SKILLS);i++)
{
sScript += LetoAdd("SkillList/Rank", IntToString(array_get_int(oPC, "Skills", i)), "byte");
sScript += LetoAdd("LvlStatList/[_]/SkillList/Rank", IntToString(array_get_int(oPC, "Skills", i)), "byte");
}
sScript += LetoAdd("SkillPoints", IntToString(nSkillPointsSaved), "word");
sScript += LetoAdd("LvlStatList/[_]/SkillPoints", IntToString(nSkillPointsSaved), "word");
// saved skill points - this is set regardless to stop the skill point exploit
sScript += LetoSet("SkillPoints", IntToString(nSkillPointsSaved), "word");
//Spells
if(nClass == CLASS_TYPE_WIZARD || nClass == CLASS_TYPE_DEFILER) // NWN Dark Sun class
{
sScript += LetoAdd("ClassList/[_]/KnownList0", "", "list");
sScript += LetoAdd("ClassList/[_]/KnownList1", "", "list");
sScript += LetoAdd("LvlStatList/[_]/KnownList0", "", "list");
sScript += LetoAdd("LvlStatList/[_]/KnownList1", "", "list");
for (i=0;i<array_get_size(oPC, "SpellLvl0");i++)
{
sScript += LetoAdd("ClassList/[_]/KnownList0/Spell", IntToString(array_get_int(oPC, "SpellLvl0", i)), "word");
sScript += LetoAdd("LvlStatList/[_]/KnownList0/Spell", IntToString(array_get_int(oPC, "SpellLvl0", i)), "word");
}
for (i=0;i<array_get_size(oPC, "SpellLvl1");i++)
{
sScript += LetoAdd("ClassList/[_]/KnownList1/Spell", IntToString(array_get_int(oPC, "SpellLvl1", i)), "word");
sScript += LetoAdd("LvlStatList/[_]/KnownList1/Spell", IntToString(array_get_int(oPC, "SpellLvl1", i)), "word");
}
//throw spellschoool in here too
if(GetPRCSwitch(PRC_PNP_SPELL_SCHOOLS))
sScript += LetoAdd("ClassList/[_]/School", IntToString(9), "byte");
else
sScript += LetoAdd("ClassList/[_]/School", IntToString(nSchool), "byte");
}
else if (nClass == CLASS_TYPE_BARD)
{
sScript += LetoAdd("ClassList/[_]/KnownList0", "", "list");
sScript += LetoAdd("ClassList/[_]/SpellsPerDayList", "", "list");
sScript += LetoAdd("LvlStatList/[_]/KnownList0", "", "list");
for (i=0;i<array_get_size(oPC, "SpellLvl0");i++)
{
sScript += LetoAdd("ClassList/[_]/KnownList0/Spell", IntToString(array_get_int(oPC, "SpellLvl0", i)), "word");
sScript += LetoAdd("LvlStatList/[_]/KnownList0/Spell", IntToString(array_get_int(oPC, "SpellLvl0", i)), "word");
}
//spells per day
sScript += LetoAdd("ClassList/[_]/SpellsPerDayList/NumSpellsLeft", IntToString(nSpellsPerDay0), "word");
}
else if (nClass == CLASS_TYPE_SORCERER)
{
sScript += LetoAdd("ClassList/[_]/KnownList0", "", "list");
sScript += LetoAdd("ClassList/[_]/KnownList1", "", "list");
sScript += LetoAdd("ClassList/[_]/SpellsPerDayList", "", "list");
sScript += LetoAdd("LvlStatList/[_]/KnownList0", "", "list");
sScript += LetoAdd("LvlStatList/[_]/KnownList1", "", "list");
for (i=0;i<array_get_size(oPC, "SpellLvl0");i++)
{
sScript += LetoAdd("ClassList/[_]/KnownList0/Spell", IntToString(array_get_int(oPC, "SpellLvl0", i)), "word");
sScript += LetoAdd("LvlStatList/[_]/KnownList0/Spell", IntToString(array_get_int(oPC, "SpellLvl0", i)), "word");
}
for (i=0;i<array_get_size(oPC, "SpellLvl1");i++)
{
sScript += LetoAdd("ClassList/[_]/KnownList1/Spell", IntToString(array_get_int(oPC, "SpellLvl1", i)), "word");
sScript += LetoAdd("LvlStatList/[_]/KnownList1/Spell", IntToString(array_get_int(oPC, "SpellLvl1", i)), "word");
}
//spells per day
sScript += LetoAdd("ClassList/[_]/SpellsPerDayList/NumSpellsLeft", IntToString(nSpellsPerDay0), "word");
sScript += LetoAdd("ClassList/[_]/SpellsPerDayList/NumSpellsLeft", IntToString(nSpellsPerDay1), "word");
}
//Appearance stuff
if(nVoiceset != -1) //keep existing voiceset
sScript += LetoSet("SoundSetFile", IntToString(nVoiceset), "word");
if(nSkin != -1) // keep existing skin colour
sScript += SetSkinColor(nSkin);
if(nHair != -1) // keep existing hair colour
sScript += SetHairColor(nHair);
if (nTattooColour1 != -1)
sScript += SetTattooColor(nTattooColour1, 1);
if (nTattooColour2 != -1)
sScript += SetTattooColor(nTattooColour2, 2);
sScript += LetoSet("Tag", Encrypt(oPC), "string");
//give an XP so the XP switch works
SetXP(oPC, 1);
SetLocalInt(oPC, "StopRotatingCamera", TRUE);
SetCutsceneMode(oPC, FALSE);
// clean up local variables
DoCleanup();
object oClone = GetLocalObject(oPC, "Clone");
AssignCommand(oClone, SetIsDestroyable(TRUE));
DestroyObject(oClone);
//do anti-hacker stuff
SetPlotFlag(oPC, FALSE);
SetImmortal(oPC, FALSE);
AssignCommand(oPC, SetIsDestroyable(TRUE));
// removes the cutscene paralysis and invisibility
ForceRest(oPC);
// let the convoCC be used by someone else
DeleteLocalObject(GetModule(), "ccc_active_pc");
// Here's where the custom PW script is run if the switch is set
if(GetPRCSwitch(PRC_CONVOCC_CUSTOM_EXIT_SCRIPT))
{
ExecuteScript("ccc_custom_exit", oPC);
}
StackedLetoScript(sScript);
RunStackedLetoScriptOnObject(oPC, "OBJECT", "SPAWN");
}

Binary file not shown.

View File

@ -0,0 +1,331 @@
//:://////////////////////////////////////////////
//:: Spell selection for enleightened fist's arcane fist/rejuvenation abilities
//:: prc_ef_spell.nss
//:://////////////////////////////////////////////
/** @file
Spell selection for enleightened fist's arcane fist/rejuvenation abilities
Handles the dynamic convo *and* the quickselects
@author HackyKid
@date Created - yyyy.mm.dd
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_spell_const"
#include "inc_dynconv"
#include "inc_newspellbook"
/* Constant defintions */
const int STAGE_ENTRY = 0;
const int STAGE_SLOT = 1;
const int STAGE_LVL0 = 10;
const int STAGE_LVL9 = 20;
/* Aid functions */
void PopulateList(object oPC, int nLevel, int iClass, int nChoice)
{
if(!GetLocalInt(oPC, "DynConv_Waiting"))
return;
int nClass = GetClassByPosition(iClass);
if(GetIsArcaneClass(nClass))
{
int i = 0, MaxValue = 0, nSpellID;
if(nClass == CLASS_TYPE_WIZARD
|| nClass == CLASS_TYPE_DEFILER // NWN Dark Sun class
|| (nClass == CLASS_TYPE_SORCERER && GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK)))
{
string sFile = "cls_spell_sorc";
object oToken = GetObjectByTag("SpellLvl_9_Level_" + IntToString(nLevel));
MaxValue = array_get_size(oToken, "Lkup");
//DoDebug("EF PopulateList: nClass = "+IntToString(nClass));
//DoDebug("EF PopulateList: nLevel = "+IntToString(nLevel));
//DoDebug("EF PopulateList: MaxValue = "+IntToString(MaxValue));
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", array_get_int(oToken, "Lkup", i)));
if(GetHasSpell(nSpellID, oPC))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
i++;
}
}
else if(nClass == CLASS_TYPE_BARD && GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK))
{
string sFile = "cls_spell_bard";
object oToken = GetObjectByTag("SpellLvl_1_Level_" + IntToString(nLevel));
MaxValue = array_get_size(oToken, "Lkup");
//DoDebug("EF PopulateList: MaxValue = "+IntToString(MaxValue));
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", array_get_int(oToken, "Lkup", i)));
if(GetHasSpell(nSpellID, oPC))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
i++;
}
}
else
{
string sFile = GetFileForClass(nClass);
string sArray = "NewSpellbookMem_" + IntToString(nClass);
// if we ever add another arcane caster with prepared spellbook
// uncomment all following lines
//int nSpellbookType = GetSpellbookTypeForClass(nClass);
//if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
int nCount = persistant_array_get_int(oPC, sArray, nLevel);
//DoDebug("EF PopulateList: nCount = "+IntToString(nCount));
if(nCount)
{
MaxValue = persistant_array_get_size(oPC, "Spellbook"+IntToString(nClass));
while(i < MaxValue)
{
int nNewSpellbookID = persistant_array_get_int(oPC, "Spellbook"+IntToString(nClass), i);
if(nLevel == StringToInt(Get2DACache(sFile, "Level", nNewSpellbookID))
&& GetHasFeat(StringToInt(Get2DACache(sFile, "FeatID", nNewSpellbookID)), oPC))
{
int nRealSpell = StringToInt(Get2DACache(sFile, "SpellID", nNewSpellbookID));
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice), nLevel);
SetLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "EF_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
i++;
}
}
}
/*else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
{
string sArrayIDX = "SpellbookIDX" + IntToString(nLevel) + "_" + IntToString(nClass);
MaxValue = persistant_array_get_size(oPC, sArrayIDX);
while(i < MaxValue)
{
int nNewSpellbookID = persistant_array_get_int(oPC, sArrayIDX, i);
int nCount = persistant_array_get_int(oPC, sArray, nNewSpellbookID);
if(nCount
&& GetHasFeat(StringToInt(Get2DACache(sFile, "FeatID", nNewSpellbookID)), oPC))
{
int nRealSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nNewSpellbookID));
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice), nNewSpellbookID);
SetLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "EF_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
i++;
}
}*/
}
}
if(iClass == 3)
{
SetDefaultTokens();
DeleteLocalInt(oPC, "DynConv_Waiting");
FloatingTextStringOnCreature("*Done*", oPC, FALSE);
return;
}
DelayCommand(0.01, PopulateList(oPC, nLevel, iClass + 1, nChoice));
}
void main()
{
object oPC = OBJECT_SELF;
int nID = GetSpellId();
int nValue = GetLocalInt(GetPCSpeaker(), DYNCONV_VARIABLE);
//SendMessageToPC(oPC, "prc_ef_spell:" + IntToString(nID) + " nVal:"+ IntToString(nValue));
if (nValue != 0) {
// do conversation
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
*/
// The stage is used to determine the active conversation node.
// 0 is the entry node.
int nStage = GetStage(oPC);
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 show in order added
if(nStage == STAGE_ENTRY)
{
SetHeader("Select Spell Level:");
AddChoice(GetStringByStrRef(690), 1, oPC);//"Level 1"
AddChoice(GetStringByStrRef(725), 2, oPC);//"Level 2"
AddChoice(GetStringByStrRef(687), 3, oPC);//"Level 3"
AddChoice(GetStringByStrRef(684), 4, oPC);//"Level 4"
AddChoice(GetStringByStrRef(1026), 5, oPC);//"Level 5"
AddChoice(GetStringByStrRef(1014), 6, oPC);//"Level 6"
AddChoice(GetStringByStrRef(2214), 7, oPC);//"Level 7"
AddChoice(GetStringByStrRef(2215), 8, oPC);//"Level 8"
AddChoice(GetStringByStrRef(2216), 9, oPC);//"Level 9"
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
else if (nStage >= STAGE_LVL0 && nStage <= STAGE_LVL9)
{
// Set the header
SetHeader("Select Spell:");
int nLevel = nStage - STAGE_LVL0;
SetLocalInt(oPC, "DynConv_Waiting", TRUE);
PopulateList(oPC, nLevel, 1, 1);
MarkStageSetUp(nStage, oPC);
}
else if (nStage = STAGE_SLOT)
{
SetHeader("Select QuickSlot:");
AddChoice("Slot 1", 1, oPC);
AddChoice("Slot 2", 2, oPC);
AddChoice("Slot 3", 3, oPC);
AddChoice("Slot 4", 4, oPC);
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
//add more stages for more nodes with Else If clauses
}
// Do token setup
SetupTokens();
}
// End of conversation cleanup
else if(nValue == DYNCONV_EXITED)
{
int nChoice = 1;
while(GetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice)))
{
DeleteLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalString(oPC, "EF_CLASS_ARRAY_" + IntToString(nChoice));
nChoice++;
}
DeleteLocalInt(oPC, "EF_SPELL_ID");
DeleteLocalInt(oPC, "EF_REAL_SPELL_ID");
DeleteLocalString(oPC, "EF_CLASS_ARRAY_ID");
DeleteLocalInt(oPC, "EF_SPELL_LEVEL_CHOICE");
}
// Abort 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_ABORTED)
{
int nChoice = 1;
while(GetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice)))
{
DeleteLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalString(oPC, "EF_CLASS_ARRAY_" + IntToString(nChoice));
nChoice++;
}
DeleteLocalInt(oPC, "EF_SPELL_ID");
DeleteLocalInt(oPC, "EF_REAL_SPELL_ID");
DeleteLocalString(oPC, "EF_CLASS_ARRAY_ID");
DeleteLocalInt(oPC, "EF_SPELL_LEVEL_CHOICE");
}
// 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_ENTRY)
{
int nLevel = nChoice;
SetLocalInt(oPC, "EF_SPELL_LEVEL_CHOICE", nLevel);
nStage = STAGE_LVL0 + nChoice;
// Move to another stage based on response, for example
//nStage = STAGE_QUUX;
}
else if (nStage >= STAGE_LVL0 && nStage <= STAGE_LVL9)
{
MarkStageNotSetUp(nStage, oPC);
int nSpell = GetLocalInt(oPC, "EF_SPELL_CHOICE_" + IntToString(nChoice));
int nRealSpell = GetLocalInt(oPC, "EF_REAL_SPELL_CHOICE_" + IntToString(nChoice));
string sArray = GetLocalString(oPC, "EF_CLASS_ARRAY_" + IntToString(nChoice));
SetLocalInt(oPC, "EF_SPELL_ID", nSpell);
SetLocalInt(oPC, "EF_REAL_SPELL_ID", nRealSpell);
SetLocalString(oPC, "EF_CLASS_ARRAY_ID", sArray);
nStage = STAGE_SLOT;
}
else if (nStage = STAGE_SLOT)
{
int nSpell = GetLocalInt(oPC, "EF_SPELL_ID");
int nRealSpell = GetLocalInt(oPC, "EF_REAL_SPELL_ID");
string sArray = GetLocalString(oPC, "EF_CLASS_ARRAY_ID");
int nLevel = GetLocalInt(oPC, "EF_SPELL_LEVEL_CHOICE");
SetLocalInt(oPC, "EF_SPELL_QUICK" + IntToString(nChoice), nSpell);
SetLocalInt(oPC, "EF_REAL_SPELL_QUICK" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "EF_SPELL_QUICK" + IntToString(nChoice), sArray);
SetLocalInt(oPC, "EF_SPELL_QUICK" + IntToString(nChoice) + "LVL", nLevel);
nStage = STAGE_ENTRY;
}
// Store the stage value. If it has been changed, this clears out the choices
SetStage(nStage, oPC);
}
}
else if (nID == SPELL_EF_SPELL_SELECT_CONVO)
{
DelayCommand(0.5, StartDynamicConversation("prc_ef_spell", oPC, DYNCONV_EXIT_ALLOWED_SHOW_CHOICE, TRUE, FALSE, oPC));
}
else
{
string sSlotNo;
switch(nID)
{
case SPELL_EF_SPELL_SELECT_QUICK1: sSlotNo = "1"; break;
case SPELL_EF_SPELL_SELECT_QUICK2: sSlotNo = "2"; break;
case SPELL_EF_SPELL_SELECT_QUICK3: sSlotNo = "3"; break;
case SPELL_EF_SPELL_SELECT_QUICK4: sSlotNo = "4"; break;
}
if(sSlotNo == "")
return;
int nSpell = GetLocalInt(oPC, "EF_SPELL_QUICK"+sSlotNo);
int nLevel = GetLocalInt(oPC, "EF_SPELL_QUICK"+sSlotNo+"LVL");
int nRealSpell = GetLocalInt(oPC, "EF_REAL_SPELL_QUICK"+sSlotNo);
if(nRealSpell == -1) nRealSpell = nSpell;
string sArray = GetLocalString(oPC, "EF_SPELL_QUICK"+sSlotNo);
SetLocalInt(oPC, "EF_SPELL_CURRENT", nSpell);
SetLocalInt(oPC, "EF_SPELL_CURRENT_LVL", nLevel);
SetLocalInt(oPC, "EF_REAL_SPELL_CURRENT", nRealSpell);
SetLocalString(oPC, "EF_SPELL_CURRENT", sArray);
int nUses = sArray == "" ? GetHasSpell(nSpell, oPC) : persistant_array_get_int(oPC, sArray, nSpell);
FloatingTextStringOnCreature("*Selected Spell: " + GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell))) + "*", oPC, FALSE);
FloatingTextStringOnCreature("*You have " + IntToString(nUses) + " uses left*", oPC, FALSE);
}
}

Binary file not shown.

View File

@ -0,0 +1,445 @@
//::///////////////////////////////////////////////
//:: Script for nwnx_funcs plugin
//:: prc_nwnx_funcs.nss
//:://////////////////////////////////////////////
//:: This script is executed only if PRC code detects
//:: nwnx_funcs plugin.
//::
//:: It will apply permanent stat modifications
//:: for PRC classes.
//:://////////////////////////////////////////////
//:: Created By: xwarren
//:: Created On: 12/05/2010
//:://////////////////////////////////////////////
#include "prc_inc_template"
#include "inc_nwnx_funcs"
void main()
{
object oPC = OBJECT_SELF;
int nBonus, nClassLvl, iTest, nDiff;
//Warchief
nClassLvl = GetLevelByClass(CLASS_TYPE_WARCHIEF, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_WarchiefCha");
if(nClassLvl || iTest)
{
if (nClassLvl > 1 && nClassLvl < 6) nBonus = 2;
else if(nClassLvl > 5 && nClassLvl < 10) nBonus = 4;
else if(nClassLvl > 9) nBonus = 6;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_WarchiefCha", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
//Mighty Contender of Kord
nClassLvl = GetLevelByClass(CLASS_TYPE_MIGHTY_CONTENDER_KORD, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_MightyContenderStr");
if(nClassLvl || iTest)
{
nBonus = 0;
if (nClassLvl >= 9) nBonus = 2;
else if (nClassLvl >= 5) nBonus = 1;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_MightyContenderStr", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_STRENGTH, nDiff);
}
}
//Heartwarder
nClassLvl = GetLevelByClass(CLASS_TYPE_HEARTWARDER, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_HeartWardCha");
if(nClassLvl || iTest)
{
nBonus = (nClassLvl + 1) / 2;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_HeartWardCha", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
/*iTest = GetPersistantLocalInt(oPC, "NWNX_HeartWardSkill");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_HEART_PASSION, oPC) ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_HeartWardSkill", nBonus);
PRC_Funcs_ModSkill(oPC, SKILL_ANIMAL_EMPATHY, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_PERFORM, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_PERSUADE, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_TAUNT, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_USE_MAGIC_DEVICE, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_BLUFF, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_INTIMIDATE, nDiff);
}
}*/
//Acolyte of the Skin
nClassLvl = GetLevelByClass(CLASS_TYPE_ACOLYTE, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_AcolyteDex");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_WEAR_FIEND, oPC) * 2;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_AcolyteDex", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_DEXTERITY, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_AcolyteInt");
if(nClassLvl || iTest)
{
nBonus = (GetHasFeat(FEAT_EPIC_INT_1, oPC)
+ GetHasFeat(FEAT_EPIC_INT_2, oPC)) * 2;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_AcolyteInt", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_INTELLIGENCE, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_AcolyteCon");
if(nClassLvl || iTest)
{
nBonus = (GetHasFeat(FEAT_SKIN_ADAPTION, oPC)
+ GetHasFeat(FEAT_EPIC_CON_1, oPC)
+ GetHasFeat(FEAT_EPIC_CON_2, oPC)
+ GetHasFeat(FEAT_EPIC_CON_3, oPC)) * 2;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_AcolyteCon", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, nDiff);
}
}
//Alienist
nClassLvl = GetLevelByClass(CLASS_TYPE_ALIENIST, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_AlienistWis");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_ALIEN_BLESSING, oPC) ? -2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_AlienistWis", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_WISDOM, nDiff);
}
}
//Diamond Dragon
nClassLvl = GetLevelByClass(CLASS_TYPE_DIAMOND_DRAGON, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_DiaDragStr");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_DRAGON_AUGMENT_STR_1, oPC)
+ GetHasFeat(FEAT_DRAGON_AUGMENT_STR_2, oPC)
+ GetHasFeat(FEAT_DRAGON_AUGMENT_STR_3, oPC);
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DiaDragStr", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_STRENGTH, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DiaDragDex");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_DRAGON_AUGMENT_DEX_1, oPC)
+ GetHasFeat(FEAT_DRAGON_AUGMENT_DEX_2, oPC)
+ GetHasFeat(FEAT_DRAGON_AUGMENT_DEX_3, oPC);
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DiaDragDex", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_DEXTERITY, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DiaDragCon");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_DRAGON_AUGMENT_CON_1, oPC)
+ GetHasFeat(FEAT_DRAGON_AUGMENT_CON_2, oPC)
+ GetHasFeat(FEAT_DRAGON_AUGMENT_CON_3, oPC);
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DiaDragCon", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, nDiff);
}
}
//Disciple of Baalzebul
nClassLvl = GetLevelByClass(CLASS_TYPE_DISC_BAALZEBUL, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_KingofLies");
if(nClassLvl || iTest)
{
nBonus = GetHasFeat(FEAT_KING_LIES, oPC) ? 4 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_KingofLies", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
//Oozemaster
nClassLvl = GetLevelByClass(CLASS_TYPE_OOZEMASTER, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_OozemasterCha");
if(nClassLvl || iTest)
{
nBonus = (nClassLvl / 2) * -1;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_OozemasterCha", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
//Swift Wing
iTest = GetPersistantLocalInt(oPC, "NWNX_DragonicSurgeStr");
nBonus = GetHasFeat(FEAT_DRACONIC_SURGE_STR, oPC);
if(nBonus || iTest)
{
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DragonicSurgeStr", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_STRENGTH, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DragonicSurgeDex");
nBonus = GetHasFeat(FEAT_DRACONIC_SURGE_DEX, oPC);
if(nBonus || iTest)
{
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DragonicSurgeDex", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_DEXTERITY, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DragonicSurgeCon");
nBonus = GetHasFeat(FEAT_DRACONIC_SURGE_CON, oPC);
if(nBonus || iTest)
{
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DragonicSurgeCon", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DragonicSurgeInt");
nBonus = GetHasFeat(FEAT_DRACONIC_SURGE_INT, oPC);
if(nBonus || iTest)
{
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DragonicSurgeInt", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_INTELLIGENCE, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DragonicSurgeWis");
nBonus = GetHasFeat(FEAT_DRACONIC_SURGE_WIS, oPC);
if(nBonus || iTest)
{
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DragonicSurgeWis", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_WISDOM, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DragonicSurgeCha");
nBonus = GetHasFeat(FEAT_DRACONIC_SURGE_CHA, oPC);
if(nBonus || iTest)
{
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DragonicSurgeCha", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
//Dragon Devotee
nClassLvl = GetLevelByClass(CLASS_TYPE_DRAGON_DEVOTEE, oPC);
int nDragDisc = GetLevelByClass(CLASS_TYPE_DRAGON_DISCIPLE, oPC);
int nHalfDrag = GetHasTemplate(TEMPLATE_HALF_DRAGON);
iTest = GetPersistantLocalInt(oPC, "NWNX_DraDevCha");
if(nClassLvl || iTest)
{
nBonus = nDragDisc < 10 && !nHalfDrag ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DraDevCha", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DraDevCon");
if(nClassLvl || iTest)
{
nBonus = nClassLvl > 2 && nDragDisc < 7 && !nHalfDrag ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DraDevCon", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_DraDevStr");
if(nClassLvl || iTest)
{
nBonus = nClassLvl > 4 && nDragDisc < 2 && !nHalfDrag ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_DraDevStr", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_STRENGTH, nDiff);
}
}
//Baelnorn
nClassLvl = GetLevelByClass(CLASS_TYPE_BAELNORN, oPC);
iTest = GetPersistantLocalInt(oPC, "NWNX_BaelnornCha");
if(nClassLvl || iTest)
{
nBonus = nClassLvl >= 4 ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_BaelnornCha", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CHARISMA, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_BaelnornWis");
if(nClassLvl || iTest)
{
nBonus = nClassLvl >= 3 ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_BaelnornWis", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_WISDOM, nDiff);
}
}
iTest = GetPersistantLocalInt(oPC, "NWNX_BaelnornInt");
if(nClassLvl || iTest)
{
nBonus = nClassLvl >= 1 ? 2 : 0;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_BaelnornInt", nBonus);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_INTELLIGENCE, nDiff);
}
}
/*iTest = GetPersistantLocalInt(oPC, "NWNX_BaelnornSkill");
if(nClassLvl || iTest)
{
nBonus = nClassLvl * 2;
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_BaelnornSkill", nBonus);
PRC_Funcs_ModSkill(oPC, SKILL_SPOT, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_HIDE, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_LISTEN, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_MOVE_SILENTLY, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_SEARCH, nDiff);
PRC_Funcs_ModSkill(oPC, SKILL_PERSUADE, nDiff);
}
}*/
if(GetPersistantLocalInt(oPC, "EpicSpell_TransVital"))
{
if(!GetPersistantLocalInt(oPC, "NWNX_TransVital"))
{
SetPersistantLocalInt(oPC, "NWNX_TransVital", 1);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, 5);
}
}
if(GetAlignmentGoodEvil(oPC) == ALIGNMENT_EVIL)
{
if(GetHasFeat(FEAT_VILE_DEFORM_OBESE, oPC) && !GetHasFeat(FEAT_VILE_DEFORM_GAUNT, oPC))
{
if(!GetPersistantLocalInt(oPC, "NWNX_DeformObese"))
{
SetPersistantLocalInt(oPC, "NWNX_DeformObese", 1);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, 2);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_DEXTERITY, -2);
}
}
if(GetHasFeat(FEAT_VILE_DEFORM_GAUNT, oPC) && !GetHasFeat(FEAT_VILE_DEFORM_OBESE, oPC))
{
if(!GetPersistantLocalInt(oPC, "NWNX_DeformGaunt"))
{
SetPersistantLocalInt(oPC, "NWNX_DeformGaunt", 1);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_DEXTERITY, 2);
PRC_Funcs_ModAbilityScore(oPC, ABILITY_CONSTITUTION, -2);
}
}
}
//Mystics with Sun domain get Turn Undead feat
/*if(GetLevelByClass(CLASS_TYPE_MYSTIC, oPC) && GetHasFeat(FEAT_BONUS_DOMAIN_SUN, oPC))
{
if(!PRC_Funcs_GetFeatKnown(oPC, FEAT_TURN_UNDEAD))
PRC_Funcs_AddFeat(oPC, FEAT_TURN_UNDEAD);
}*/
//Inherent Bonuses to abilities
if(GetPersistantLocalInt(oPC, "PRC_InherentBonus"))
{
int i;
string sAbi;
for(i = 0; i < 6; i++)
{
sAbi = IntToString(i);
nBonus = GetPersistantLocalInt(oPC, "PRC_InherentBonus_"+sAbi);
iTest = GetPersistantLocalInt(oPC, "NWNX_InherentBonus_"+sAbi);
nDiff = nBonus - iTest;
if(nDiff != 0)
{
SetPersistantLocalInt(oPC, "NWNX_InherentBonus_"+sAbi, nBonus);
PRC_Funcs_ModAbilityScore(oPC, i, nDiff);
}
}
}
//PRC PnP Spell Schools
if(GetPRCSwitch(PRC_PNP_SPELL_SCHOOLS)
&& GetLevelByClass(CLASS_TYPE_WIZARD, oPC) || GetLevelByClass(CLASS_TYPE_DEFILER, oPC)) // NWN Dark Sun class
{
if(GetHasFeat(2274, oPC)
|| GetHasFeat(2276, oPC)
|| GetHasFeat(2277, oPC)
|| GetHasFeat(2278, oPC)
|| GetHasFeat(2279, oPC)
|| GetHasFeat(2280, oPC)
|| GetHasFeat(2281, oPC))
{
//set school to PnP school
PRC_Funcs_SetWizardSpecialization(oPC, 9);
}
else if(GetHasFeat(2273, oPC))
{
//set school to generalist
PRC_Funcs_SetWizardSpecialization(oPC, 0);
}
}
}

Binary file not shown.

View File

@ -0,0 +1,342 @@
//::///////////////////////////////////////////////
//:: OnAcquireItem eventscript
//:: prc_onaquire
//:://////////////////////////////////////////////
#include "prc_alterations"
#include "prc_craft_inc"
//#include "psi_inc_manifest"
void AntiMagicFieldCheck(object oItem, object oCreature)
{
int nIP = array_get_size(oItem, "PRC_NPF_ItemList");
if(GetHasSpellEffect(SPELL_ANTIMAGIC_FIELD, oCreature)
|| GetHasSpellEffect(POWER_NULL_PSIONICS_FIELD, oCreature))
{
if(nIP)
// itemproperty list already exists - do nothing
return;
//remove ips
string sIP;
int nIpCount;
persistant_array_create(oCreature, "PRC_NPF_ItemList"); //stores object strings
itemproperty ip = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ip))
{
if(GetItemPropertyDurationType(ip) == DURATION_TYPE_PERMANENT)
{ //only store the permanent ones as underscore delimited strings
sIP = IntToString(GetItemPropertyType(ip)) + "_" +
IntToString(GetItemPropertySubType(ip)) + "_" +
IntToString(GetItemPropertyCostTableValue(ip)) + "_" +
IntToString(GetItemPropertyParam1Value(ip));
if(DEBUG) DoDebug("StoreItemprops: " + GetName(oCreature) + ", " + ObjectToString(oItem) + ", " + sIP);
array_set_string(oCreature, "PRC_NPF_ItemList", nIpCount++, sIP);
}
RemoveItemProperty(oItem, ip);
ip = GetNextItemProperty(oItem);
}
}
else
{
if(!nIP)
// itemproperty list not found!
return;
//restore ips
struct ipstruct iptemp;
itemproperty ip;
string sIP;
int i;
for(i = 0; i < nIP; i++)
{
sIP = array_get_string(oItem, "PRC_NPF_ItemList", i);
iptemp = GetIpStructFromString(sIP);
ip = ConstructIP(iptemp.type, iptemp.subtype, iptemp.costtablevalue, iptemp.param1value);
IPSafeAddItemProperty(oItem, ip, 0.0, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
if(DEBUG) DoDebug("RetoreItemprops: " + GetName(GetItemPossessor(oItem)) + ", " + ObjectToString(oItem) + ", " + sIP);
}
array_delete(oItem, "PRC_NPF_ItemList");
}
}
void UpdateIPs(object oItem)
{
// Has lookup finished yet?
if(GetXP(GetObjectByTag("Bioware2DACache")) & 0x01)
{
int bAddRestrictions = FALSE;
int nSpellID;
//Set the AMS version of last update
SetLocalString(oItem, "sb_ver", AMS_VERSION);
//remove all class restrictions and mark the spell
itemproperty ipTest = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipTest))
{
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_USE_LIMITATION_CLASS)
{
//the scroll/wand had a use limitation
RemoveItemProperty(oItem, ipTest);
bAddRestrictions = TRUE;
}
else if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_CAST_SPELL)
{
nSpellID = StringToInt(Get2DACache("iprp_spells", "SpellIndex", GetItemPropertySubType(ipTest)));
}
ipTest = GetNextItemProperty(oItem);
}
if(bAddRestrictions)
{
int i, nClass, bAdd;
for(i = 0; i < 36; i++)
{
bAdd = FALSE;
switch(i)
{
case 0: nClass = CLASS_TYPE_BARD; break;
case 1: nClass = CLASS_TYPE_CLERIC; break;
case 2: nClass = CLASS_TYPE_DRUID; break;
case 3: nClass = CLASS_TYPE_PALADIN; break;
case 4: nClass = CLASS_TYPE_RANGER; break;
case 5: nClass = CLASS_TYPE_SORCERER; break;
case 6: nClass = CLASS_TYPE_WIZARD; break;
case 7: nClass = CLASS_TYPE_HARPER; break;
case 8: nClass = CLASS_TYPE_ASSASSIN; break;
case 9: nClass = CLASS_TYPE_BLACKGUARD; break;
case 10: nClass = CLASS_TYPE_OCULAR; break;
case 11: nClass = CLASS_TYPE_HEXBLADE; break;
case 12: nClass = CLASS_TYPE_DUSKBLADE; break;
case 13: nClass = CLASS_TYPE_HEALER; break;
case 14: nClass = CLASS_TYPE_BEGUILER; break;
case 15: nClass = CLASS_TYPE_KNIGHT_CHALICE; break;
case 16: nClass = CLASS_TYPE_VIGILANT; break;
case 17: nClass = CLASS_TYPE_VASSAL; break;
case 18: nClass = CLASS_TYPE_SUBLIME_CHORD; break;
case 19: nClass = CLASS_TYPE_ANTI_PALADIN; break;
case 20: nClass = CLASS_TYPE_SOLDIER_OF_LIGHT; break;
case 21: nClass = CLASS_TYPE_SHADOWLORD; break;
case 22: nClass = CLASS_TYPE_JUSTICEWW; break;
case 23: nClass = CLASS_TYPE_KNIGHT_MIDDLECIRCLE; break;
case 24: nClass = CLASS_TYPE_DREAD_NECROMANCER; break;
case 25: nClass = CLASS_TYPE_MYSTIC; break;
case 26: nClass = CLASS_TYPE_ARCHIVIST; break;
case 27: nClass = CLASS_TYPE_WITCH; break;
case 28: nClass = CLASS_TYPE_SHAMAN; break;
case 29: nClass = CLASS_TYPE_SLAYER_OF_DOMIEL; break;
case 30: nClass = CLASS_TYPE_SUEL_ARCHANAMACH; break;
case 31: nClass = CLASS_TYPE_FAVOURED_SOUL; break;
case 32: nClass = CLASS_TYPE_SHUGENJA; break;
case 33: nClass = CLASS_TYPE_SOHEI; break;
case 34: nClass = CLASS_TYPE_WARMAGE; break;
case 35: nClass = CLASS_TYPE_TEMPLAR; break;
case 36: nClass = CLASS_TYPE_DEFILER; break;
}
if(nClass == CLASS_TYPE_DRUID)
bAdd = Get2DACache("Spells", "Druid", nSpellID) == "" ? FALSE : TRUE;
else if(nClass == CLASS_TYPE_PALADIN)
bAdd = Get2DACache("Spells", "Paladin", nSpellID) == "" ? FALSE : TRUE;
else if(nClass == CLASS_TYPE_RANGER)
bAdd = Get2DACache("Spells", "Ranger", nSpellID) == "" ? FALSE : TRUE;
else if(nClass == CLASS_TYPE_WIZARD || nClass == CLASS_TYPE_SORCERER || nClass == CLASS_TYPE_DEFILER)
bAdd = RealSpellToSpellbookID(CLASS_TYPE_SORCERER, nSpellID) == -1 ? FALSE : TRUE;
else if(nClass == CLASS_TYPE_CLERIC)
bAdd = RealSpellToSpellbookID(CLASS_TYPE_MYSTIC, nSpellID) == -1 ? FALSE : TRUE;
else
bAdd = RealSpellToSpellbookID(nClass, nSpellID) == -1 ? FALSE : TRUE;
if(bAdd)
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyLimitUseByClass(nClass), oItem);
}
}
}
else // Nope, try again later
{
DelayCommand(0.2f, UpdateIPs(oItem));
}
}
void main()
{
// Find out the relevant objects
object oCreature = GetModuleItemAcquiredBy();
object oItem = GetModuleItemAcquired();
string sTag = GetTag(oItem);
// Do not run for some of the PRC special items
if(sTag == "PRC_MANIFTOKEN"
|| sTag == "HideToken"
|| GetResRef(oItem) == "base_prc_skin")
return;
//if(DEBUG) DoDebug("Running OnAcquireItem, creature = '" + GetName(oCreature) + "' is PC: " + DebugBool2String(GetIsPC(oCreature)) + "; Item = '" + GetName(oItem) + "' - '" + GetTag(oItem) + "'");
AntiMagicFieldCheck(oItem, oCreature);
int nItemType = GetBaseItemType(oItem);
//fix for all-beige 1.67 -> 1.68 cloaks
//gives them a random color
if(nItemType == BASE_ITEM_CLOAK)
{
if(!GetPRCSwitch(PRC_DYNAMIC_CLOAK_AUTOCOLOUR_DISABLE) && !GetLocalInt(oItem, "CloakDone"))
{
//&& GetItemAppearance(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0) == 1
if(GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH1) == 0
&& GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH2) == 0
&& GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER1) == 0
&& GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER2) == 0
&& GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL1) == 0
&& GetItemAppearance(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL2) == 0)
{
//pre-1.68 boring bland cloak, colorise it :)
//move it to temporary storage first
object oChest = GetObjectByTag("HEARTOFCHAOS");
DestroyObject(oItem);
oItem = CopyItem(oItem, oChest, TRUE);
//set appearance
//doesnt work yet should do for 1.69
//DestroyObject(oItem);
//oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_SIMPLE_MODEL, 0, Random(14)+1, TRUE);
//set colors
DestroyObject(oItem);
oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH1, Random(176), TRUE);
DestroyObject(oItem);
oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_CLOTH2, Random(176), TRUE);
DestroyObject(oItem);
oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER1, Random(176), TRUE);
DestroyObject(oItem);
oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER2, Random(176), TRUE);
DestroyObject(oItem);
oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL1, Random(176), TRUE);
DestroyObject(oItem);
oItem = CopyItemAndModify(oItem, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL2, Random(176), TRUE);
//move it back
DestroyObject(oItem);
oItem = CopyItem(oItem, oCreature, TRUE);
//mark it as set just to be sure
SetLocalInt(oItem, "CloakDone", TRUE);
}
}
}
// This is a resource hog. To work around, we assume that it's not going to cause noticeable issues if
// racial restrictions are only ever expanded when a PC is involved
if(GetIsPC(oCreature) || GetIsPC(GetMaster(oCreature)) || GetPRCSwitch(PRC_NPC_FORCE_RACE_ACQUIRE))
ExecuteScript("race_ev_aquire", OBJECT_SELF);
// Creatures not related to PCs skip this block, contents are irrelevant for them
if(GetIsPC(oCreature) || GetIsPC(GetMaster(oCreature)))
{
if(GetPRCSwitch(PRC_AUTO_IDENTIFY_ON_ACQUIRE))
{
if(!GetIdentified(oItem))
{
int nLore = GetSkillRank(SKILL_LORE, oCreature);
int nMax = StringToInt(Get2DACache("SkillVsItemCost", "DeviceCostMax", nLore));
if(nMax == 0)
nMax = 120000000;
// Check for the value of the item first.
SetIdentified(oItem, TRUE);
int nGP = GetGoldPieceValue(oItem);
// If oPC has enough Lore skill to ID the item, then do so.
if(nMax >= nGP)
{
string sName = GetName(oItem);
if(sName != "")
SendMessageToPC(oCreature, GetStringByStrRef(16826224) + " " + sName + " " + GetStringByStrRef(16826225));
}
else
SetIdentified(oItem, FALSE);
}
}
if(nItemType == BASE_ITEM_MAGICWAND
|| nItemType == BASE_ITEM_ENCHANTED_WAND
|| nItemType == BASE_ITEM_SCROLL
|| nItemType == BASE_ITEM_SPELLSCROLL
|| nItemType == BASE_ITEM_ENCHANTED_SCROLL)
{
if(!GetPRCSwitch(PRC_SCROLL_AUTOUPDATE_RESTR_DISABLE)
&& GetLocalString(oItem, "sb_ver") != AMS_VERSION //different Alternate Magic System versions - update IPs
&& !GetLocalInt(oItem, "ip_lock")) //IPs of wand/scroll were locked in toolset or by script
{
DelayCommand(1.0f, UpdateIPs(oItem));//delayed to reduce lag and prevent TMIs
}
}
//rest kits
if(GetPRCSwitch(PRC_SUPPLY_BASED_REST))
ExecuteScript("sbr_onaquire", OBJECT_SELF);
//PRC Companion
//DOA visible dyepot items
/*if(GetPRCSwitch(MARKER_PRC_COMPANION))
{
if(GetBaseItemType(oItem) == BASE_ITEM_MISCSMALL)
{
//x2_it_dyec23
string sTag = GetTag(oItem);
if(GetStringLeft(sTag, 9) == "x2_it_dye")
{
//get the color
//taken from x2_s3_dyearmour
// GZ@2006/03/26: Added new color palette support. Note: Will only work
// if craig updates the in engine functions as well.
int nColor = 0;
// See if we find a valid int between 0 and 127 in the last three letters
// of the tag, use it as color
int nTest = StringToInt(GetStringRight(sTag,3));
if (nTest > 0 &&
nTest < 175 )//magic number, bad!
nColor = nTest;
else //otherwise, use last two letters, as per legacy HotU
nColor = StringToInt(GetStringRight(sTag,2));
//use limbo for crafting in
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
//create the new one with the same tag as the old
object oDye = CreateItemOnObject("prccompdye", oLimbo, 1, sTag);
//ensure old one is cleaned up
DestroyObject(oItem);
//if its a metalic dye, modify it to use model 2
if(GetStringRight(GetStringLeft(sTag, 10), 1) == "m")
{
DestroyObject(oDye);
oDye = CopyItemAndModify(oDye, ITEM_APPR_TYPE_SIMPLE_MODEL, 0, 2);
//metal dye color
DestroyObject(oDye);
oDye = CopyItemAndModify(oDye, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_METAL1, nColor);
}
else
{
//standard dye
DestroyObject(oDye);
//cloth and leather use same palettee
oDye = CopyItemAndModify(oDye, ITEM_APPR_TYPE_ARMOR_COLOR, ITEM_APPR_ARMOR_COLOR_LEATHER1, nColor);
}
//copy the itemprops to cast the dye "spell"
itemproperty ipTest = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipTest))
{
AddItemProperty(DURATION_TYPE_PERMANENT, ipTest, oDye);
ipTest = GetNextItemProperty(oItem);
}
//move it back to the player
CopyItem(oDye, oCreature);
DestroyObject(oDye);
}
}
}*/
}// end if - PC or associate of PC
// Execute scripts hooked to this event for the creature and item triggering it
ExecuteAllScriptsHookedToEvent(oCreature, EVENT_ONACQUIREITEM);
ExecuteAllScriptsHookedToEvent(oItem, EVENT_ITEM_ONACQUIREITEM);
// Tag-based scripting hook for PRC items
SetUserDefinedItemEventNumber(X2_ITEM_EVENT_ACQUIRE);
ExecuteScript("is_"+sTag, OBJECT_SELF);
}

Binary file not shown.

1426
nwnds_scripts/prc_prereq.nss Normal file

File diff suppressed because it is too large Load Diff

BIN
nwnds_scripts/prc_rest.ncs Normal file

Binary file not shown.

395
nwnds_scripts/prc_rest.nss Normal file
View File

@ -0,0 +1,395 @@
//::///////////////////////////////////////////////
//:: OnPlayerRest eventscript
//:: prc_rest
//:://////////////////////////////////////////////
/*
Hooked NPC's into this via prc_npc_rested - 06.03.2004, Ornedan
*/
#include "prc_inc_function"
#include "psi_inc_psifunc"
#include "prc_sp_func"
#include "prc_inc_domain"
#include "true_inc_trufunc"
#include "inv_inc_invfunc"
#include "inc_epicspells"
#include "prc_inc_scry"
#include "prc_inc_dragsham"
#include "prc_inc_wpnrest"
#include "inc_dynconv"
#include "prc_inc_util"
#include "shd_inc_myst"
#include "prc_inc_template"
void PrcFeats(object oPC)
{
if(DEBUG) DoDebug("prc_rest: Evaluating PC feats for " + DebugObject2Str(oPC));
SetLocalInt(oPC,"ONREST",1);
object oSkin = GetPCSkin(oPC);
DelayCommand(0.0, ScrubPCSkin(oPC, oSkin));
DelayCommand(0.1, FeatSpecialUsePerDay(oPC));
DelayCommand(0.2, DeletePRCLocalInts(oSkin));
DelayCommand(0.3, DeletePRCLocalIntsT(oPC));
DelayCommand(0.4, EvalPRCFeats(oPC));
DelayCommand(0.4, DoWeaponsEquip(oPC));
DelayCommand(1.0, DeleteLocalInt(oPC,"ONREST"));
}
void RestCancelled(object oPC)
{
if(GetPRCSwitch(PRC_PNP_REST_HEALING))
{
int nHP = GetLocalInt(oPC, "PnP_Rest_InitialHP");
//cancelled, dont heal anything
//nHP += GetHitDice(oPC);
int nCurrentHP = GetCurrentHitPoints(oPC);
int nDamage = nCurrentHP-nHP;
//check its a positive number
if(nDamage > 0)
{
//DelayCommand(1.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_TWENTY), oPC));
SetCurrentHitPoints(oPC, nCurrentHP - nDamage);
}
}
if(DEBUG) DoDebug("prc_rest: Rest cancelled for " + DebugObject2Str(oPC));
DelayCommand(1.0,PrcFeats(oPC));
// Execute scripts hooked to this event for the player triggering it
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONPLAYERREST_CANCELLED);
}
void RestFinished(object oPC)
{
int nGeneration = PRC_NextGeneration(GetLocalInt(oPC, PRC_Rest_Generation));
if (DEBUG > 1) DoDebug("Rest Generation: " + IntToString(nGeneration));
SetLocalInt(oPC, PRC_Rest_Generation, nGeneration);
if(DEBUG) DoDebug("prc_rest: Rest finished for for " + DebugObject2Str(oPC));
//Restore Power Points for Psionics
ExecuteScript("prc_psi_ppoints", oPC);
ExecuteScript("tob_evnt_recover", oPC);
DelayCommand(0.0, BonusDomainRest(oPC));
DelayCommand(0.0, ClearLawLocalVars(oPC));
DelayCommand(0.0, ClearMystLocalVars(oPC));
DelayCommand(0.0, ClearLegacyUses(oPC));
DelayCommand(0.1, ClearInvocationLocalVars(oPC));
// To heal up enslaved creatures...
object oSlave = GetLocalObject(oPC, "EnslavedCreature");
if (GetIsObjectValid(oSlave) && !GetIsDead(oSlave) && !GetIsInCombat(oSlave))
AssignCommand(oSlave, ActionRest());
//ForceRest(oSlave);
if (GetIsEpicSpellcaster(oPC)) {
FloatingTextStringOnCreature("*You feel refreshed*", oPC, FALSE);
ReplenishSlots(oPC);
}
if (GetHasFeat(FEAT_SF_CODE,oPC))
DelayCommand(0.1, RemoveSpecificProperty(GetPCSkin(oPC),ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_SF_CODE));
// begin flurry of swords array
if (GetLevelByClass(CLASS_TYPE_ARCANE_DUELIST, oPC))
{
DeleteLocalInt(oPC, "FLURRY_TARGET_NUMBER");
int i;
for (i = 0 ; i < 10 ; i++)
{
string sName = "FLURRY_TARGET_" + IntToString(i);
SetLocalObject(oPC, sName, OBJECT_INVALID);
}
}
// end flurry or swords array
//Check for leftover Diamond Dragon appendages
if (GetLevelByClass(CLASS_TYPE_DIAMOND_DRAGON, oPC))
{
if(GetPersistantLocalInt(oPC, "ChannelingTail"))
{
SetPersistantLocalInt(oPC, "ChannelingTail", FALSE);
SetCreatureTailType(CREATURE_TAIL_TYPE_NONE, oPC);
}
if(GetPersistantLocalInt(oPC, "ChannelingWings"))
{
SetPersistantLocalInt(oPC, "ChannelingWings", FALSE);
SetCreatureWingType(CREATURE_WING_TYPE_NONE, oPC);
}
}
if(GetPRCSwitch(PRC_PNP_REST_HEALING))
{
int nHP = GetLocalInt(oPC, "PnP_Rest_InitialHP");
int nOldMax = GetLocalInt(oPC, "PnP_Rest_InitialMax");
if(DEBUG) DoDebug("prc_rest: Finished HPs for " + DebugObject2Str(oPC)+"n/n/"+" nCurrent: "+IntToString(nHP)+" nMax: "+IntToString(nOldMax));
//only heal HP if not undead and not a construct
if(MyPRCGetRacialType(oPC) != RACIAL_TYPE_UNDEAD && MyPRCGetRacialType(oPC) != RACIAL_TYPE_CONSTRUCT)
nHP = GetMaxHitPoints(oPC) - nOldMax + nHP + GetHitDice(oPC);
int nCurrentHP = GetCurrentHitPoints(oPC);
int nDamage = nCurrentHP-nHP;
//check its a positive number
if(nDamage > 0)
{
//DelayCommand(1.5, ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_TWENTY), oPC));
SetCurrentHitPoints(oPC, nCurrentHP - nDamage);
}
// We've finished rest, clean up
DeleteLocalInt(oPC, "PnP_Rest_InitialHP");
DeleteLocalInt(oPC, "PnP_Rest_InitialMax");
}
int nSpellCount = GetPRCSwitch(PRC_DISABLE_SPELL_COUNT);
int i;
string sMessage;
for(i=1;i<nSpellCount;i++)
{ //WARNING! WILL DO BAD THINGS TO SPONTANEOUS CASTERS AFFECTED
int nSpell = GetPRCSwitch(PRC_DISABLE_SPELL_+IntToString(i));
int nMessage;
while(PRCGetHasSpell(nSpell, oPC))
{
if(!nMessage)
{
sMessage += "You cannot use "+GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpell)))+" in this module.\n";
nMessage = TRUE;
}
PRCDecrementRemainingSpellUses(oPC, nSpell);
}
}
if(sMessage != "")
FloatingTextStringOnCreature(sMessage, oPC, TRUE);
//Clear Battle Fortitude lock
DeleteLocalInt(oPC, "BattleFortitude");
DeleteLocalInt(oPC, "ArmouredStealth");
//Clear Spelldancing
DeleteLocalInt(oPC, "SpelldanceFatigue");
DeleteLocalInt(oPC, "SpelldanceExhaust");
DeleteLocalInt(oPC, "SpelldanceRounds");
//Clear Killoren
DeleteLocalInt(oPC, "KillorenAncient");
DeleteLocalInt(oPC, "KillorenHunter");
//Clear Earth Smite
DeleteLocalInt(oPC, "EarthSmite");
//Clear Fatigue
DeleteLocalInt(oPC, "Fatigued");
DeleteLocalInt(oPC, "HeatstrokeCount");
// Allow Readying
DeleteLocalInt(oPC, "ReadyManeuverCru");
DeleteLocalInt(oPC, "ReadyManeuverSwd");
DeleteLocalInt(oPC, "ReadyManeuverWar");
// Rest Ranged Recall
DeleteLocalInt(oPC, "RangedRecall");
// Animal Affinity
DeleteLocalInt(oPC, "AnimalAffin"+IntToString(ABILITY_STRENGTH));
DeleteLocalInt(oPC, "AnimalAffin"+IntToString(ABILITY_DEXTERITY));
DeleteLocalInt(oPC, "AnimalAffin"+IntToString(ABILITY_CONSTITUTION));
DeleteLocalInt(oPC, "AnimalAffin"+IntToString(ABILITY_WISDOM));
DeleteLocalInt(oPC, "AnimalAffin"+IntToString(ABILITY_INTELLIGENCE));
DeleteLocalInt(oPC, "AnimalAffin"+IntToString(ABILITY_CHARISMA));
if(GetHasFeat(FEAT_WEAPON_APTITUDE, oPC))
{
FloatingTextStringOnCreature(GetStringByStrRef(16837723), oPC, FALSE);
SetLocalInt(oPC, "PRC_WEAPON_APTITUDE_APPLIED", 0);
}
//DelayCommand(1.0,PrcFeats(oPC));
PrcFeats(oPC);
//allow players to recruit a new cohort
DeleteLocalInt(oPC, "CohortRecruited");
//in large parties, sometimes people dont rest
//loop over all and forcerest when necessary
//assumes NPCs start and finish resting after the PC
/*if(!GetIsObjectValid(GetMaster(oPC)))
{*/
int nType;
for(nType = 1; nType < 6; nType++)
{
int i = 1;
object oOldTest;
object oTest = GetAssociate(nType, oPC, i);
while(GetIsObjectValid(oTest) && oTest != oOldTest)
{
if(GetCurrentAction(oTest) != ACTION_REST)
AssignCommand(oTest, DelayCommand(0.01, PRCForceRest(oTest)));
i++;
oOldTest = oTest;
oTest = GetAssociate(nType, oPC, i);
}
}
//}
// New Spellbooks
DelayCommand(0.3, CheckNewSpellbooks(oPC));
// PnP spellschools
if(GetPRCSwitch(PRC_PNP_SPELL_SCHOOLS)
&& GetLevelByClass(CLASS_TYPE_WIZARD, oPC)|| GetLevelByClass(CLASS_TYPE_DEFILER)) // NWN Dark Sun class
{
//need to put a check in to make sure the player
//memorized one spell of their specialized
//school for each spell level
//also need to remove spells of prohibited schools
}
//Reset potions brewed
DeleteLocalInt(oPC, "PRC_POTIONS_BREWED");
//Reset scry on familiar uses
DeleteLocalInt(oPC, "Scry_Familiar");
//for Touch of Vitality point resetting
ResetTouchOfVitality(oPC);
//Lahm's finger darts - recover lost fingers
SetPersistantLocalInt(oPC, "FINGERS_LEFT_HAND", 6);
SetPersistantLocalInt(oPC, "FINGERS_RIGHT_HAND", 6);
SetPersistantLocalInt(oPC, "LEFT_HAND_USELESS", FALSE);
SetPersistantLocalInt(oPC, "RIGHT_HAND_USELESS", FALSE);
//DelayCommand(6.0f, ExecuteScript("prc_trueappear", oPC));
//skip time forward if applicable
DelayCommand(0.4, AdvanceTimeForPlayer(oPC, HoursToSeconds(8)));
int nRest = GetPRCSwitch(PRC_PNP_REST_LIMIT);
if(nRest > 0 || nRest < 0)
{
int nDelay = nRest * GetHitDice(oPC);
if (nRest == -1) nDelay = 24;
else if (nRest == -2) nDelay = 16;
SetLocalInt(oPC, "RestTimer", TRUE);
DelayCommand(HoursToSeconds(nDelay), DeleteLocalInt(oPC, "RestTimer"));
DelayCommand(HoursToSeconds(nDelay), FloatingTextStringOnCreature("You may now rest again.", oPC, FALSE));
FloatingTextStringOnCreature("You may rest again in "+IntToString(nDelay)+" hours.", oPC, FALSE);
}
// Execute scripts hooked to this event for the player triggering it
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONPLAYERREST_FINISHED);
}
void RestStarted(object oPC)
{
if(DEBUG) DoDebug("prc_rest: Rest started for " + DebugObject2Str(oPC));
// Scrying cleanup
if (GetIsScrying(oPC))
{
object oCopy = GetLocalObject(oPC, "Scry_Copy");
DoScryEnd(oPC, oCopy);
}
int nRest = GetPRCSwitch(PRC_PNP_REST_LIMIT);
if(nRest > 0 || nRest < 0)
{
int nDelay = nRest * GetHitDice(oPC);
if (nRest == -1) nDelay = 24;
else if (nRest == -2) nDelay = 16;
if(GetLocalInt(oPC, "RestTimer"))
{
AssignCommand(oPC, ClearAllActions());
FloatingTextStringOnCreature("You may not rest yet. You may rest once every "+IntToString(nDelay)+" hours.", oPC, FALSE);
}
}
// Clean up Crown of Might
object oCrown = GetItemPossessedBy(oPC, "prc_crown_might");
if (GetIsObjectValid(oCrown)) DestroyObject(oCrown);
oCrown = GetItemPossessedBy(oPC, "prc_crown_prot");
if (GetIsObjectValid(oCrown)) DestroyObject(oCrown);
if (GetLevelByClass(CLASS_TYPE_DRUNKEN_MASTER, oPC)){
SetLocalInt(oPC, "DRUNKEN_MASTER_IS_IN_DRUNKEN_RAGE", 0);
SetLocalInt(oPC, "DRUNKEN_MASTER_IS_DRUNK_LIKE_A_DEMON", 0);
}
/* Left here in case the multisummon trick is ever broken. In that case, use this to make Astral Constructs get unsummoned properly
if(GetHasFeat(whatever feat determines if the PC can manifest Astral Construct here)){
int i = 1;
object oCheck = GetHenchman(oPC, i);
while(oCheck != OBJECT_INVALID){
if(GetStringLeft(GetTag(oCheck), 14) == "psi_astral_con")
DoDespawn(oCheck);
i++;
oCheck = GetHenchman(oPC, i);
}
}
*/
if (GetIsPC(oPC)) SetLocalInt(oPC, "PnP_Rest_InitialHP", GetCurrentHitPoints(oPC));
SetLocalInt(oPC, "PnP_Rest_InitialMax", GetMaxHitPoints(oPC));
if(DEBUG) DoDebug("prc_rest: HPs for " + DebugObject2Str(oPC)+"n/n/"+" nCurrent: "+IntToString(GetCurrentHitPoints(oPC))+" nMax: "+IntToString(GetMaxHitPoints(oPC)));
// Remove Psionic Focus
if(GetIsPsionicallyFocused(oPC))
{
LosePsionicFocus(oPC);
}
DeleteLocalInt(oPC, PRC_SPELL_CHARGE_COUNT);
DeleteLocalInt(oPC, PRC_SPELL_CHARGE_SPELLID);
DeleteLocalObject(oPC, PRC_SPELL_CONC_TARGET);
if(GetLocalInt(oPC, PRC_SPELL_HOLD)) FloatingTextStringOnCreature("*Normal Casting*", oPC);
DeleteLocalInt(oPC, PRC_SPELL_HOLD);
DeleteLocalInt(oPC, PRC_SPELL_METAMAGIC);
DeleteLocalManifestation(oPC, PRC_POWER_HOLD_MANIFESTATION);
DeleteLocalMystery(oPC, "MYST_HOLD_MYST");
// run the prereq check here
ExecuteScript("prc_prereq", oPC);
// Execute scripts hooked to this event for the player triggering it
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONPLAYERREST_STARTED);
}
void main()
{
object oPC = GetLastBeingRested();
if(DEBUG) DoDebug("prc_rest: Running for " + DebugObject2Str(oPC));
if(DEBUG) DoDebug("prc_rest Void Main: HPs for " + DebugObject2Str(oPC) +" nCurrent: "+IntToString(GetCurrentHitPoints(oPC)));
// return here for DMs as they don't need all this stuff
if(GetIsDM(oPC))
return;
//rest kits
if(GetPRCSwitch(PRC_SUPPLY_BASED_REST))
ExecuteScript("sbr_onrest", OBJECT_SELF);
// Handle the PRCForceRest() wrapper
if(GetLocalInt(oPC, "PRC_ForceRested"))
{
if(DEBUG) DoDebug("prc_rest: Handling forced rest");
RestStarted(oPC);
// A minor delay to break the script association and to lessen TMI chances
DelayCommand(0.1f, RestFinished(oPC));
// Clear the flag
DeleteLocalInt(oPC, "PRC_ForceRested");
}
else
{
switch(MyGetLastRestEventType()){
case REST_EVENTTYPE_REST_CANCELLED:{
RestCancelled(oPC);
break;
}
case REST_EVENTTYPE_REST_STARTED:{
RestStarted(oPC);
break;
}
case REST_EVENTTYPE_REST_FINISHED:{
RestFinished(oPC);
break;
}
case REST_EVENTTYPE_REST_INVALID:{
break;
}
}
}
}

Binary file not shown.

View File

@ -0,0 +1,305 @@
//:://////////////////////////////////////////////
//:: Spell selection conversation for the Jade Phoenix Mage's abilities
//:: tob_jpm_spellconv.nss
//:://////////////////////////////////////////////
/** @file
Spell selection for Jade Phoenix Mage's abilities
Handles the dynamic convo *and* the quickselects
@author Stratovaris
@date Created - yyyy.mm.dd
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_spell_const"
#include "inc_dynconv"
#include "inc_newspellbook"
////#include "prc_alterations"
#include "prc_inc_castlvl"
/* Constant defintions */
const int STAGE_ENTRY = 0;
const int STAGE_SLOT = 1;
const int STAGE_LVL0 = 10;
const int STAGE_LVL9 = 20;
void PopulateList(object oPC, int nLevel, int iClass, int nChoice)
{
if(!GetLocalInt(oPC, "DynConv_Waiting"))
return;
//SendMessageToPC(oPC, "*Tick* *" + IntToString(iClass) + "*");
int nClass = GetClassByPosition(iClass);
if(GetIsArcaneClass(nClass))
{
int i = 0, MaxValue = 0, nSpellID;
if(nClass == CLASS_TYPE_WIZARD
|| nClass == CLASS_TYPE_DEFILER
|| (nClass == CLASS_TYPE_SORCERER && GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK)))
{
string sFile = "cls_spell_sorc";
object oToken = GetObjectByTag("SpellLvl_9_Level_" + IntToString(nLevel));
MaxValue = array_get_size(oToken, "Lkup");
//DoDebug("JPM PopulateList: nClass = "+IntToString(nClass));
//DoDebug("JPM PopulateList: nLevel = "+IntToString(nLevel));
//DoDebug("JPM PopulateList: MaxValue = "+IntToString(MaxValue));
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", array_get_int(oToken, "Lkup", i)));
if(GetHasSpell(nSpellID, oPC))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
i++;
}
}
else if(nClass == CLASS_TYPE_BARD && GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK))
{
string sFile = "cls_spell_bard";
object oToken = GetObjectByTag("SpellLvl_1_Level_" + IntToString(nLevel));
MaxValue = array_get_size(oToken, "Lkup");
//DoDebug("JPM PopulateList: MaxValue = "+IntToString(MaxValue));
while(i < MaxValue)
{
nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", array_get_int(oToken, "Lkup", i)));
if(GetHasSpell(nSpellID, oPC))
{
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice), nSpellID);
SetLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice), -1);
nChoice++;
}
i++;
}
}
else
{
string sFile = GetFileForClass(nClass);
string sArray = "NewSpellbookMem_" + IntToString(nClass);
// if we ever add another arcane caster with prepared spellbook
// uncomment all following lines
//int nSpellbookType = GetSpellbookTypeForClass(nClass);
//if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
int nCount = persistant_array_get_int(oPC, sArray, nLevel);
//DoDebug("JPM PopulateList: nCount = "+IntToString(nCount));
if(nCount)
{
MaxValue = persistant_array_get_size(oPC, "Spellbook"+IntToString(nClass));
while(i < MaxValue)
{
int nNewSpellbookID = persistant_array_get_int(oPC, "Spellbook"+IntToString(nClass), i);
if(nLevel == StringToInt(Get2DACache(sFile, "Level", nNewSpellbookID))
&& GetHasFeat(StringToInt(Get2DACache(sFile, "FeatID", nNewSpellbookID)), oPC))
{
int nRealSpell = StringToInt(Get2DACache(sFile, "SpellID", nNewSpellbookID));
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice), nLevel);
SetLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "JPM_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
i++;
}
}
}
/*else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
{
string sArrayIDX = "SpellbookIDX" + IntToString(nLevel) + "_" + IntToString(nClass);
MaxValue = persistant_array_get_size(oPC, sArrayIDX);
while(i < MaxValue)
{
int nNewSpellbookID = persistant_array_get_int(oPC, sArrayIDX, i);
int nCount = persistant_array_get_int(oPC, sArray, nNewSpellbookID);
if(nCount
&& GetHasFeat(StringToInt(Get2DACache(sFile, "FeatID", nNewSpellbookID)), oPC))
{
int nRealSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nNewSpellbookID));
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nRealSpell)));
AddChoice(sName, nChoice, oPC);
SetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice), nNewSpellbookID);
SetLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "JPM_CLASS_ARRAY_" + IntToString(nChoice), sArray);
nChoice++;
}
i++;
}
}*/
}
}
if(iClass == 3)
{
SetDefaultTokens();
DeleteLocalInt(oPC, "DynConv_Waiting");
FloatingTextStringOnCreature("*Done*", oPC, FALSE);
return;
}
DelayCommand(0.01, PopulateList(oPC, nLevel, iClass + 1, nChoice));
}
void main()
{
object oPC = GetPCSpeaker();
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
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;
// Check if this stage is marked as already set up
// This stops list duplication when scrolling
//SendMessageToPC(OBJECT_SELF, "prc_jpm_spellconv:" + IntToString(nID) + " nVal:"+ IntToString(nValue));
/* 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
*/
// The stage is used to determine the active conversation node.
// 0 is the entry node.
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 show in order added
if(nStage == STAGE_ENTRY)
{
SetHeader("Select Spell Level:");
AddChoice(GetStringByStrRef(690), 1, oPC);//"Level 1"
AddChoice(GetStringByStrRef(725), 2, oPC);//"Level 2"
AddChoice(GetStringByStrRef(687), 3, oPC);//"Level 3"
AddChoice(GetStringByStrRef(684), 4, oPC);//"Level 4"
AddChoice(GetStringByStrRef(1026), 5, oPC);//"Level 5"
AddChoice(GetStringByStrRef(1014), 6, oPC);//"Level 6"
AddChoice(GetStringByStrRef(2214), 7, oPC);//"Level 7"
AddChoice(GetStringByStrRef(2215), 8, oPC);//"Level 8"
AddChoice(GetStringByStrRef(2216), 9, oPC);//"Level 9"
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
else if (nStage >= STAGE_LVL0 && nStage <= STAGE_LVL9)
{
// Set the header
SetHeader("Select Spell:");
int nLevel = nStage - STAGE_LVL0;
SetLocalInt(oPC, "DynConv_Waiting", TRUE);
PopulateList(oPC, nLevel, 1, 1);
MarkStageSetUp(nStage, oPC);
}
else if (nStage = STAGE_SLOT)
{
SetHeader("Select QuickSlot:");
AddChoice("Slot 1", 1, oPC);
AddChoice("Slot 2", 2, oPC);
AddChoice("Slot 3", 3, oPC);
AddChoice("Slot 4", 4, oPC);
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
}
//add more stages for more nodes with Else If clauses
}
// Do token setup
SetupTokens();
}
// End of conversation cleanup
else if(nValue == DYNCONV_EXITED)
{
int nChoice = 1;
while(GetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice)))
{
DeleteLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalString(oPC, "JPM_CLASS_ARRAY_" + IntToString(nChoice));
nChoice++;
}
DeleteLocalInt(oPC, "JPM_SPELL_ID");
DeleteLocalInt(oPC, "JPM_REAL_SPELL_ID");
DeleteLocalString(oPC, "JPM_CLASS_ARRAY_ID");
DeleteLocalInt(oPC, "JPM_SPELL_LEVEL_CHOICE");
}
// Abort 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_ABORTED)
{
int nChoice = 1;
while (GetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice)))
{
DeleteLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice));
DeleteLocalString(oPC, "JPM_CLASS_ARRAY_" + IntToString(nChoice));
nChoice++;
}
DeleteLocalInt(oPC, "JPM_SPELL_ID");
DeleteLocalInt(oPC, "JPM_REAL_SPELL_ID");
DeleteLocalString(oPC, "JPM_CLASS_ARRAY_ID");
DeleteLocalInt(oPC, "JPM_SPELL_LEVEL_CHOICE");
}
// 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_ENTRY)
{
int nLevel = nChoice;
SetLocalInt(oPC, "JPM_SPELL_LEVEL_CHOICE", nLevel);
nStage = STAGE_LVL0 + nLevel;
// Move to another stage based on response, for example
//nStage = STAGE_QUUX;
}
else if (nStage >= STAGE_LVL0 && nStage <= STAGE_LVL9)
{
MarkStageNotSetUp(nStage, oPC);
int nSpell = GetLocalInt(oPC, "JPM_SPELL_CHOICE_" + IntToString(nChoice));
int nRealSpell = GetLocalInt(oPC, "JPM_REAL_SPELL_CHOICE_" + IntToString(nChoice));
string sArray = GetLocalString(oPC, "JPM_CLASS_ARRAY_" + IntToString(nChoice));
SetLocalInt(oPC, "JPM_SPELL_ID", nSpell);
SetLocalInt(oPC, "JPM_REAL_SPELL_ID", nRealSpell);
SetLocalString(oPC, "JPM_CLASS_ARRAY_ID", sArray);
nStage = STAGE_SLOT;
}
else if (nStage = STAGE_SLOT)
{
int nSpell = GetLocalInt(oPC, "JPM_SPELL_ID");
int nRealSpell = GetLocalInt(oPC, "JPM_REAL_SPELL_ID");
string sArray = GetLocalString(oPC, "JPM_CLASS_ARRAY_ID");
int nLevel = GetLocalInt(oPC, "JPM_SPELL_LEVEL_CHOICE");
if(DEBUG) DoDebug("tob_jpm_spellconv: nSpell value = " + IntToString(nSpell));
SetLocalInt(oPC, "JPM_SPELL_QUICK" + IntToString(nChoice), nSpell);
SetLocalInt(oPC, "JPM_REAL_SPELL_QUICK" + IntToString(nChoice), nRealSpell);
SetLocalString(oPC, "JPM_SPELL_QUICK" + IntToString(nChoice), sArray);
SetLocalInt(oPC, "JPM_SPELL_QUICK" + IntToString(nChoice) + "LVL", nLevel);
nStage = STAGE_ENTRY;
}
// Store the stage value. If it has been changed, this clears out the choices
SetStage(nStage, oPC);
}
}

Binary file not shown.

View File

@ -0,0 +1,163 @@
//------------------------------------------------------------------------------
/*
Use Magic Device Check.
Simple use magic device check to prevent abuse of
the engine level implementation of use magic device
This function is not supposed to mirror the 3E use
magic device mechanics.
Returns TRUE if the Spell is allowed to be
cast, either because the character is allowed
to cast it or he has won the required UMD check
returns TRUE if
... spell not cast by an item
... item is not a scroll (may be extended)
... caster has levels in wiz, bard, sorc
... caster is no rogue and has no UMD skill
... caster has memorized this spell
... the property corresponding to the spell does not exist (2da inconsistency)
... a UMD check against 25+InnateLevel of the spell is won
Note: I am not using the effective level of the spell for DC calculation but
instead the lowest possible effective level. This is by design to allow
rogues to use most low level scrolls in the game (i.e. light scrolls have
an effective level 5 but a lowest effective level of 1 and we want low level
rogues to cast these spells..)
Setting a Local Interger called X2_SWITCH_CLASSIC_UMD (TRUE) on the Module
will result in this function to return TRUE all the time
User's can change this default implementation by modifing this file
*/
//------------------------------------------------------------------------------
#include "prc_inc_spells"
int DoCastingClassCheck(object oCaster, int nSpellID, int nClass)
{
string sClass;
switch(nClass)
{
case CLASS_TYPE_CLERIC: sClass = "Cleric"; break;
case CLASS_TYPE_DRUID: sClass = "Druid"; break;
case CLASS_TYPE_PALADIN: sClass = "Paladin"; break;
case CLASS_TYPE_RANGER: sClass = "Ranger"; break;
case CLASS_TYPE_WIZARD: sClass = "Wiz_Sorc"; break;
case CLASS_TYPE_DEFILER: sClass = "Wiz_Sorc"; break;
}
if(sClass == "")
return RealSpellToSpellbookID(nClass, nSpellID) != -1;
else
return Get2DACache("Spells", sClass, nSpellID) != "";
}
int UMD_CheckCastingClass(object oCaster, int nSpellID)
{
int i;
for(i = 1; i < 4; i++)
{
if(DoCastingClassCheck(oCaster, nSpellID, GetClassByPosition(i, oCaster)))
return TRUE;
}
return FALSE;
}
int X2_UMD()
{
if(!GetModuleSwitchValue(MODULE_SWITCH_ENABLE_UMD_SCROLLS))
return TRUE;
object oItem = PRCGetSpellCastItem();
if(!GetIsObjectValid(oItem))
return TRUE; // Spell not cast by item, UMD not required
// -------------------------------------------------------------------------
// Only Scrolls are subject to our default UMD Check
// -------------------------------------------------------------------------
if(GetBaseItemType(oItem) != BASE_ITEM_SPELLSCROLL)
return TRUE; // spell not cast from a scroll
// -------------------------------------------------------------------------
// Ignore scrolls that have no use limitations (i.e. raise dead)
// -------------------------------------------------------------------------
if(!IPGetHasUseLimitation(oItem))
return TRUE;
object oCaster = OBJECT_SELF;
int nSpellID = PRCGetSpellId();
// -------------------------------------------------------------------------
// Check if caster has levels in class that can cast given spell
// -------------------------------------------------------------------------
if(UMD_CheckCastingClass(oCaster, nSpellID))
return TRUE;
// -------------------------------------------------------------------------
// If the caster used the item and has no UMD Skill and is not a rogue
// thus we assume he must be allowed to use it because the engine
// prevents people that are not capable of using an item from using it....
// -------------------------------------------------------------------------
if(!GetHasSkill(SKILL_USE_MAGIC_DEVICE, oCaster)
&& !GetLevelByClass(CLASS_TYPE_ROGUE, oCaster)
&& !GetLevelByClass(CLASS_TYPE_ASSASSIN, oCaster)
&& !GetLevelByClass(CLASS_TYPE_SHADOWDANCER, oCaster))
{
// ---------------------------------------------------------------------
//SpeakString("I have no UMD, thus I can cast the spell... ");
// ---------------------------------------------------------------------
return TRUE;
}
if(Get2DACache("des_crft_spells", "IPRP_SpellIndex", nSpellID) == "")
{
WriteTimestampedLogEntry("***X2UseMagicDevice (Warning): Found no property matching SpellID "+ IntToString(nSpellID));
return TRUE;
}
// -------------------------------------------------------------------------
//I am using des_crft_spells.2da Innate Level column here, not (as would be correct)
//the IPPR_Spells.2da InnateLvl column, because some of the scrolls in
//the game (i.e. light) would not be useable (DC 30+)
// -------------------------------------------------------------------------
int nInnateLevel = StringToInt(Get2DACache("des_crft_spells","Level",nSpellID));
int nSkill = SKILL_USE_MAGIC_DEVICE;
//int nSkillRanks = GetSkillRank(SKILL_USE_MAGIC_DEVICE, oCaster);
if(GetLevelByClass(CLASS_TYPE_ARTIFICER, oCaster))
nInnateLevel -= 2; //only scrolls are being checked, and arti gets scribe scroll at level 1, this instead of +2 to skill
// -------------------------------------------------------------------------
// Base DC for casting a spell from a scroll is 25+SpellLevel
// We do not have a way to check for misshaps here but GetIsSkillSuccessful
// does not return the required information
// -------------------------------------------------------------------------
if(GetPRCIsSkillSuccessful(oCaster, nSkill, 25+ nInnateLevel, (GetHasFeat(FEAT_DECEIVE_ITEM, oCaster) || GetHasFeat(FEAT_SKILL_MASTERY_ARTIFICER, oCaster)) ? 10 : -1))
{
return TRUE;
}
else
{
effect ePuff = EffectVisualEffect(VFX_IMP_MAGIC_RESISTANCE_USE);
ApplyEffectToObject(DURATION_TYPE_INSTANT,ePuff,oCaster);
return FALSE;
}
}
void main()
{
//--------------------------------------------------------------------------
// Reset
//--------------------------------------------------------------------------
if(GetLocalInt(GetModule(),"X2_L_STOP_EXPERTISE_ABUSE"))
{
SetActionMode(OBJECT_SELF, ACTION_MODE_EXPERTISE, FALSE);
SetActionMode(OBJECT_SELF, ACTION_MODE_IMPROVED_EXPERTISE, FALSE);
}
//--------------------------------------------------------------------------
// Do use magic device check
//--------------------------------------------------------------------------
int nRet = X2_UMD();
SetExecutedScriptReturnValue(nRet);
}

Binary file not shown.

View File

@ -0,0 +1,220 @@
//::///////////////////////////////////////////////
//:: Black Blade of Disaster
//:: X2_S0_BlckBlde
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Summons a greatsword to battle for the caster
*/
//:://////////////////////////////////////////////
//:: Created By: Andrew Nobbs
//:: Created On: Nov 26, 2002
//:://////////////////////////////////////////////
//:: Last Updated By: Georg Zoeller, July 28 - 2003
//:: modified by mr_bumpkin Dec 4, 2003 for prc stuff
#include "inc_utility"
#include "prc_inc_spells"
#include "prc_inc_sp_tch"
#include "prc_add_spell_dc"
void DoPnPAttack(object oSummon)
{
object oTarget = GetAttackTarget(oSummon);
if(GetIsObjectValid(oTarget)
&& GetDistanceBetween(oTarget, oSummon) < 5.0)
{
int nAttackResult = PRCDoMeleeTouchAttack(oTarget);;
if(nAttackResult)
{
//hit or critical hit
//touch attacks are only crit on 20
//BBoD is crit on 18-20
//so 2/20ths of attacks that hit, but not crit, will be turned into crits
if(nAttackResult == 1 & d20(1)>=19)
nAttackResult = 2;
int nDamage = d12(2);
if(nAttackResult == 2)
nDamage *=2; //critical doubles damage
//its magical damage because the description is unclear
AssignCommand(oSummon, ApplyEffectToObject(
DURATION_TYPE_INSTANT, PRCEffectDamage(oTarget, nDamage,
DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_FIVE), oTarget));
}
if(nAttackResult == 2)
{
//critical hit
//cast disintegrate
int nLevel = GetLocalInt(oSummon, "BBoD_Level");
SetLocalInt(oSummon, PRC_CASTERLEVEL_OVERRIDE, nLevel);
// Make sure this variable gets deleted as quickly as possible in case it's added in error.
AssignCommand(oSummon, DelayCommand(1.0, DeleteLocalInt(oSummon, PRC_CASTERLEVEL_OVERRIDE)));
// Make SR check
if (!PRCDoResistSpell(OBJECT_SELF, oTarget))
{
// Generate the RTA beam.
AssignCommand(oSummon, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY,
EffectBeam(VFX_BEAM_DISINTEGRATE, OBJECT_SELF, BODY_NODE_HAND), oTarget, 1.0,FALSE));
// Fort save or die time, but we implement death by doing massive damage
// since disintegrate works on constructs, undead, etc. At some point EffectDie()
// should be tested to see if it works on non-living targets, and if it does it should
// be used instead.
// Test done. Result: It does kill them.
int nDamage = 9999;
if (PRCMySavingThrow(SAVING_THROW_FORT, oTarget, PRCGetSaveDC(oTarget,OBJECT_SELF), SAVING_THROW_TYPE_SPELL))
{
nDamage = PRCGetMetaMagicDamage(DAMAGE_TYPE_MAGICAL, 1 == nAttackResult ? 5 : 10, 6);
}
else
{
// If FB passes saving throw it survives, else it dies
//DeathlessFrenzyCheck(oTarget);
// For targets with > 9999 HP. Uncomment if you have such in your module and would like Disintegrate
// to be sure to blast them
//DelayCommand(0.30, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oTarget));
}
// Apply damage effect and VFX impact, and if the target is dead then apply
// the fancy rune circle too.
if (nDamage >= GetCurrentHitPoints (oTarget))
DelayCommand(0.25, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_2), oTarget));
//DelayCommand(0.25, SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectDamage(oTarget, nDamage, DAMAGE_TYPE_MAGICAL), oTarget));
DelayCommand(0.25, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_MAGBLUE), oTarget));
ApplyTouchAttackDamage(OBJECT_SELF, oTarget, nAttackResult, nDamage, DAMAGE_TYPE_MAGICAL);
}
}
}
if(GetIsObjectValid(oSummon))
DelayCommand(6.0, DoPnPAttack(oSummon));
}
//Creates the weapon that the creature will be using.
void spellsCreateItemForSummoned()
{
//Declare major variables
int nStat;
// cast from scroll, we just assume +5 ability modifier
if (GetSpellCastItem() != OBJECT_INVALID)
{
nStat = 5;
}
else
{
int nClass = PRCGetLastSpellCastClass();
int nLevel = GetLevelByClass(nClass);
int nStat;
int nCha = GetAbilityModifier(ABILITY_CHARISMA,OBJECT_SELF);
int nInt = GetAbilityModifier(ABILITY_INTELLIGENCE,OBJECT_SELF);
if (nClass == CLASS_TYPE_WIZARD || nClass == CLASS_TYPE_DEFILER)
{
nStat = nInt;
}
else
{
nStat = nCha;
}
if (nStat >20)
{
nStat =20;
}
if (nStat <1)
{
nStat = 0;
}
}
int i = 1;
object oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
while(GetIsObjectValid(oSummon))
{
oSummon = GetAssociate(ASSOCIATE_TYPE_SUMMONED, OBJECT_SELF, i);
i++;
}
// Make the blade require concentration
SetLocalInt(oSummon,"X2_L_CREATURE_NEEDS_CONCENTRATION",TRUE);
object oWeapon;
//Create item on the creature, epuip it and add properties.
oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND,oSummon);
if (nStat > 0 && !GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
{
IPSetWeaponEnhancementBonus(oWeapon, nStat);
}
SetDroppableFlag(oWeapon, FALSE);
SetPlotFlag (oSummon,TRUE);
if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
{
itemproperty ipTest = GetFirstItemProperty(oWeapon);
while(GetIsItemPropertyValid(ipTest))
{
ipTest = GetNextItemProperty(oWeapon);
}
itemproperty ipNoDam = ItemPropertyNoDamage();
AddItemProperty(DURATION_TYPE_PERMANENT, ipNoDam, oWeapon);
itemproperty ipVFX = ItemPropertyVisualEffect(ITEM_VISUAL_ELECTRICAL);
AddItemProperty(DURATION_TYPE_PERMANENT, ipVFX, oWeapon);
//store the level on the summon
SetLocalInt(oSummon, "BBoD_Level", GetLocalInt(OBJECT_SELF, "BBoD_Level"));
DeleteLocalInt(OBJECT_SELF, "BBoD_Level");
//attacks are handled through a pseudoHB
DoPnPAttack(oSummon);
}
}
void main()
{
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION);
/*
Spellcast Hook Code
Added 2003-07-07 by Georg Zoeller
If you want to make changes to all spells,
check x2_inc_spellhook.nss to find out more
*/
if (!X2PreSpellCastCode())
{
// If code within the PreSpellCastHook (i.e. UMD) reports FALSE, do not run this spell
return;
}
// End of Spell Cast Hook
//Declare major variables
int nMetaMagic = PRCGetMetaMagicFeat();
int nDuration = PRCGetCasterLevel(OBJECT_SELF);
effect eSummon = EffectSummonCreature("x2_s_bblade");
effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_MONSTER_3);
//Make metamagic check for extend
if ((nMetaMagic & METAMAGIC_EXTEND))
nDuration = nDuration *2;//Duration is +100%
//Apply the VFX impact and summon effect
MultisummonPreSummon();
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eVis, PRCGetSpellTargetLocation());
float fDuration = RoundsToSeconds(nDuration);
if(GetPRCSwitch(PRC_SUMMON_ROUND_PER_LEVEL))
fDuration = RoundsToSeconds(nDuration*GetPRCSwitch(PRC_SUMMON_ROUND_PER_LEVEL));
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon, PRCGetSpellTargetLocation(), fDuration);
DelayCommand(1.5, spellsCreateItemForSummoned());
if(GetPRCSwitch(PRC_PNP_BLACK_BLADE_OF_DISASTER))
{
SetLocalInt(OBJECT_SELF, "BBoD_Level", PRCGetCasterLevel(OBJECT_SELF));
}
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
// Erasing the variable used to store the spell's spell school
}