Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80070703b4 |
12
Notes/Class Expansion/Epic Swashbuckler.txt
Normal file
12
Notes/Class Expansion/Epic Swashbuckler.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
You have become the embodiment of panache and daring. You are an epic Swashbuckler.
|
||||||
|
|
||||||
|
Hit Die: d10
|
||||||
|
Skill Points at Each Additional Level: 4+ Int Modifier
|
||||||
|
Bonus Feats: The epic swashbuckler gains a bonus feat every three levels.
|
||||||
|
|
||||||
|
Special:
|
||||||
|
Swashbuckler Dodge: This bonus continues to increase by +1 at every five levels after 20th.
|
||||||
|
Grace: An epic swashbuckler gains another +1 bonus on Reflex saves at 29th and 39th level. A swashbuckler loses this bonus when wearing medium or heavy armor or when encumbered.
|
||||||
|
|
||||||
|
Epic Swashbuckler Bonus Feat List:
|
||||||
|
Armor Skin, Blinding Speed, Devastating Critical, Epic Damage Reduction, Epic Prowess, Epic Toughness, Epic Weapon Focus, Improved Stunning Fist, Improved Whirlwind Attack, Overwhelming Critical, Superior Initiative
|
||||||
BIN
Notes/MartialStudyNotes.pdf
Normal file
BIN
Notes/MartialStudyNotes.pdf
Normal file
Binary file not shown.
682
Notes/prc_amagsys_gain.nss.bak
Normal file
682
Notes/prc_amagsys_gain.nss.bak
Normal file
@@ -0,0 +1,682 @@
|
|||||||
|
//:://////////////////////////////////////////////
|
||||||
|
//:: Alternate magic system gain evaluation script
|
||||||
|
//:: prc_amagsys_gain
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
/** @file
|
||||||
|
This file determines if the given character
|
||||||
|
has gained new spells / powers / utterances /
|
||||||
|
whathaveyou since the last time it was run.
|
||||||
|
If so, it starts the relevant selection
|
||||||
|
conversations.
|
||||||
|
|
||||||
|
Add new classes to their respective magic
|
||||||
|
user type block, or if such doesn't exist
|
||||||
|
yet for the system the class belongs to,
|
||||||
|
make a new block for them at the end of main().
|
||||||
|
|
||||||
|
|
||||||
|
@author Ornedan
|
||||||
|
@date Created - 2006.12.14
|
||||||
|
*/
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
|
||||||
|
//:: Updated for .35 by Jaysyn 2023/03/11
|
||||||
|
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "inc_dynconv"
|
||||||
|
#include "psi_inc_psifunc"
|
||||||
|
#include "inc_newspellbook"
|
||||||
|
#include "true_inc_trufunc"
|
||||||
|
#include "tob_inc_tobfunc"
|
||||||
|
#include "shd_inc_shdfunc"
|
||||||
|
#include "inv_inc_invfunc"
|
||||||
|
#include "prc_nui_lv_inc"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
/* 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(GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oPC) > 0)
|
||||||
|
{
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_SUBLIME_CHORD, 4, 9);
|
||||||
|
|
||||||
|
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_BARD, oPC))
|
||||||
|
{
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 3);
|
||||||
|
}
|
||||||
|
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_SORCERER))
|
||||||
|
{
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 3);
|
||||||
|
}
|
||||||
|
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_WARMAGE, oPC))
|
||||||
|
{
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 3);
|
||||||
|
}
|
||||||
|
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_DUSKBLADE, oPC))
|
||||||
|
{
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 3);
|
||||||
|
}
|
||||||
|
if(GetHasFeat(FEAT_SUBLIME_CHORD_SPELLCASTING_BEGUILER, oPC))
|
||||||
|
{
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check all classes that might need a spellbook update
|
||||||
|
if(GetIsRHDSorcerer(oPC)) CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9);
|
||||||
|
if(GetIsRHDBard(oPC)) CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6);
|
||||||
|
|
||||||
|
if(!GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK))
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6);
|
||||||
|
if(!GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9);
|
||||||
|
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_SUEL_ARCHANAMACH, 1, 5);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_FAVOURED_SOUL, 0, 9);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 9);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_DREAD_NECROMANCER, 1, 9);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_HEXBLADE, 1, 4);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 5);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_JUSTICEWW, 1, 4);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_KNIGHT_WEAVE, 1, 6);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_ARCHIVIST, 0, 9);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 9);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_HARPER, 1, 3);
|
||||||
|
CheckMissingSpells(oPC, CLASS_TYPE_CELEBRANT_SHARESS, 1, 4);
|
||||||
|
//CheckMissingSpells(oPC, CLASS_TYPE_ASSASSIN, 1, 4);
|
||||||
|
|
||||||
|
// Check psionics
|
||||||
|
DelayCommand(0.0f, CheckPsionics(oPC));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* void CheckSpellbooks(object oPC)
|
||||||
|
{
|
||||||
|
if(GetIsRHDSorcerer(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
|
||||||
|
return;
|
||||||
|
if(GetIsRHDBard(oPC) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
|
||||||
|
return;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (nClass <= 0)
|
||||||
|
nClass = GetPrimaryPsionicClass(oPC);
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (nClass == CLASS_TYPE_INVALID || nClass == -2)
|
||||||
|
nClass = GetPrimaryInvocationClass(oPC);
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// Mark the class for which the PC is to gain invocations and start the conversation
|
||||||
|
SetLocalInt(oPC, "nClass", nClass);
|
||||||
|
StartDynamicConversation("inv_invokeconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSpellsForLevel(int nClass, int nLevel)
|
||||||
|
{
|
||||||
|
object oPC = OBJECT_SELF;
|
||||||
|
object oSkin = GetPCSkin(oPC);
|
||||||
|
//object oToken = GetHideToken(oPC);
|
||||||
|
string sFile = GetFileForClass(nClass);
|
||||||
|
string sSpellbook;
|
||||||
|
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
||||||
|
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||||
|
sSpellbook = "Spellbook"+IntToString(nClass);
|
||||||
|
else
|
||||||
|
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(nLevel);
|
||||||
|
|
||||||
|
// Create spells known persistant array if it is missing
|
||||||
|
int nSize = persistant_array_get_size(oPC, sSpellbook);
|
||||||
|
if (nSize < 0)
|
||||||
|
{
|
||||||
|
persistant_array_create(oPC, sSpellbook);
|
||||||
|
nSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for learnable spells
|
||||||
|
object oToken_Class = GetObjectByTag("SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nLevel));
|
||||||
|
int nSpells_Total = persistant_array_get_size(oToken_Class, "Lkup");
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < nSpells_Total; i++)
|
||||||
|
{
|
||||||
|
int nSpellbookID = persistant_array_get_int(oToken_Class, "Lkup", i);
|
||||||
|
if(Get2DAString(sFile, "AL", nSpellbookID) != "1")
|
||||||
|
{
|
||||||
|
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
||||||
|
nSize++;
|
||||||
|
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||||
|
{
|
||||||
|
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||||
|
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||||||
|
AddSpellUse(oPC, nSpellbookID, nClass, sFile, "NewSpellbookMem_" + IntToString(nClass), nSpellbookType, oSkin, nFeatID, nIPFeatID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||||
|
{
|
||||||
|
int nLevel;
|
||||||
|
|
||||||
|
//:: Rakshasa cast as sorcerers
|
||||||
|
if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC);
|
||||||
|
|
||||||
|
//:: Aranea cast as sorcerers
|
||||||
|
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_SHAPECHANGER, oPC);
|
||||||
|
|
||||||
|
//::Arkamoi cast as sorcerers
|
||||||
|
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
||||||
|
|
||||||
|
//::Hobgoblin Warsouls cast as sorcerers
|
||||||
|
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
||||||
|
|
||||||
|
//:: Driders cast as sorcerers
|
||||||
|
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_ABERRATION, oPC);
|
||||||
|
|
||||||
|
//:: Marrutact cast as 6/7 sorcerers
|
||||||
|
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
||||||
|
|
||||||
|
//:: Redspawn Arcaniss cast as 3/4 sorcerers
|
||||||
|
else if(nClass == CLASS_TYPE_SORCERER && !GetLevelByClass(CLASS_TYPE_SORCERER, oPC) && GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
||||||
|
|
||||||
|
//:: Gloura cast as bards
|
||||||
|
else if(nClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oPC) && GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
|
||||||
|
nLevel = GetSpellslotLevel(nClass, oPC); //GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
||||||
|
|
||||||
|
else
|
||||||
|
nLevel = nClass == CLASS_TYPE_SUBLIME_CHORD ? GetLevelByClass(nClass, oPC) : GetSpellslotLevel(nClass, oPC);
|
||||||
|
|
||||||
|
if (DEBUG) DoDebug("CheckMissingSpells 1 Class: " + IntToString(nClass));
|
||||||
|
if (DEBUG) DoDebug("CheckMissingSpells 1 Level: " + IntToString(nLevel));
|
||||||
|
|
||||||
|
if(!nLevel)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if(nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER)
|
||||||
|
{
|
||||||
|
if((GetLevelByClass(nClass, oPC) == nLevel) //no PrC
|
||||||
|
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oPC) || GetHasFeat(FEAT_DRACONIC_BREATH, oPC))) //no Draconic feats that apply
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else if(nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
int nLastGainLevel = GetPersistantLocalInt(oPC, "LastSpellGainLevel");
|
||||||
|
nLevel = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
|
||||||
|
|
||||||
|
|
||||||
|
//add cleric spells known for level 0
|
||||||
|
if(persistant_array_get_size(oPC, "Spellbook_Known_"+IntToString(CLASS_TYPE_ARCHIVIST)+"_0") < 5) // TODO: replace with GetSpellKnownCurrentCount
|
||||||
|
{
|
||||||
|
ActionDoCommand(AddSpellsForLevel(CLASS_TYPE_ARCHIVIST, 0));
|
||||||
|
}
|
||||||
|
if(nLastGainLevel < nLevel)
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_ARCHIVIST);
|
||||||
|
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||||
|
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, TRUE, FALSE, oPC);
|
||||||
|
*/
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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.
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
if (!IsLevelUpNUIOpen(oPC))
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
/*
|
||||||
|
// Mark the class for which the PC is to gain powers and start the conversation
|
||||||
|
SetLocalInt(oPC, "nClass", nClass);
|
||||||
|
StartDynamicConversation("shd_mystconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||||
|
*/
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//AMS Compatibility functions - xwarren:
|
||||||
|
void CopyAMSArray(object oPC, object oAMSToken, int nClass, string sArray, int nMin, int nMax, int nLoopSize = 100)
|
||||||
|
{
|
||||||
|
string sFile = GetFileForClass(nClass);
|
||||||
|
int i = nMin;
|
||||||
|
while(i < nMin + nLoopSize && i < nMax)
|
||||||
|
{
|
||||||
|
int nSpellbookID = persistant_array_get_int(oPC, sArray, i);
|
||||||
|
int nSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||||||
|
if(DEBUG) DoDebug("Copying spell "+IntToString(nSpell));
|
||||||
|
array_set_int(oAMSToken, sArray, i, nSpell);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(i < nMax)
|
||||||
|
DelayCommand(0.0, CopyAMSArray(oPC, oAMSToken, nClass, sArray, i, nMax));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoBuckUpAMS(object oPC, int nClass, string sSpellbook, object oHideToken, object oAMSToken)
|
||||||
|
{
|
||||||
|
if(DEBUG) DoDebug("Creating buck-up copy of "+sSpellbook);
|
||||||
|
if(array_exists(oAMSToken, sSpellbook))
|
||||||
|
array_delete(oAMSToken, sSpellbook);
|
||||||
|
array_create(oAMSToken, sSpellbook);
|
||||||
|
int nSize = persistant_array_get_size(oPC, sSpellbook);
|
||||||
|
DelayCommand(0.0, CopyAMSArray(oPC, oAMSToken, nClass, sSpellbook, 0, nSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AMSCompatibilityCheck(object oPC)
|
||||||
|
{
|
||||||
|
//Get an extra hide token with amagsys info
|
||||||
|
object oAMSToken = GetHideToken(oPC, TRUE);
|
||||||
|
object oHideToken = GetHideToken(oPC); //ebonfowl: no longer used but I'm leaving it to not have to edit other functions
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 1; i <= 8; i++)
|
||||||
|
{
|
||||||
|
int nClass = GetClassByPosition(i, oPC);
|
||||||
|
string sSpellbook;
|
||||||
|
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
||||||
|
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||||
|
{
|
||||||
|
sSpellbook = "Spellbook"+IntToString(nClass);
|
||||||
|
int nSize1 = persistant_array_get_size(oPC, sSpellbook);
|
||||||
|
int nSize2 = array_get_size(oAMSToken, sSpellbook);
|
||||||
|
if(nSize1 > nSize2)
|
||||||
|
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
|
||||||
|
}
|
||||||
|
else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
for(j = 0; j <= 9; j++)
|
||||||
|
{
|
||||||
|
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(j);
|
||||||
|
int nSize1 = persistant_array_get_size(oPC, sSpellbook);
|
||||||
|
int nSize2 = array_get_size(oAMSToken, sSpellbook);
|
||||||
|
if(nSize1 > nSize2)
|
||||||
|
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
530
Notes/prc_nui_com_inc.nss.bak
Normal file
530
Notes/prc_nui_com_inc.nss.bak
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
#include "prc_nui_consts"
|
||||||
|
#include "inc_newspellbook"
|
||||||
|
#include "psi_inc_psifunc"
|
||||||
|
#include "inc_lookups"
|
||||||
|
#include "nw_inc_nui"
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetCurrentSpellLevel
|
||||||
|
// Gets the current spell level the class can achieve at the current
|
||||||
|
// caster level (ranging from 0-9)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
// nLevel:int the caster level
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the circle the class can achieve currently
|
||||||
|
//
|
||||||
|
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetMaxSpellLevel
|
||||||
|
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the highest circle that can be achieved
|
||||||
|
//
|
||||||
|
int GetMaxSpellLevel(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetMinSpellLevel
|
||||||
|
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the lowest circle that can be achieved
|
||||||
|
//
|
||||||
|
int GetMinSpellLevel(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetHighestLevelPossibleInClass
|
||||||
|
// Given a class Id this will determine what the max level of a class can be
|
||||||
|
// achieved
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the highest possible level the class can achieve
|
||||||
|
//
|
||||||
|
int GetHighestLevelPossibleInClass(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetClassSpellbookFile
|
||||||
|
// Gets the class 2da spellbook/ability for the given class Id
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the classID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// string the 2da file name for the spell/abilities of the ClassID
|
||||||
|
//
|
||||||
|
string GetClassSpellbookFile(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetBinderSpellToFeatDictionary
|
||||||
|
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||||
|
// to their feat. This is constructed based off the binder's known location of
|
||||||
|
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||||
|
// this it will be saved to the player locally as a cached result since we do
|
||||||
|
// not need to call this again.
|
||||||
|
//
|
||||||
|
// Argument:
|
||||||
|
// oPlayer:object the player
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||||
|
// and the FeatID of a vestige ability
|
||||||
|
//
|
||||||
|
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetSpellLevelIcon
|
||||||
|
// Takes the spell circle int and gets the icon appropriate for it (i.e. 0 turns
|
||||||
|
// into "ir_cantrips"
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// spellLevel:int the spell level we want the icon for
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// string the spell level icon
|
||||||
|
//
|
||||||
|
string GetSpellLevelIcon(int spellLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetSpellLevelToolTip
|
||||||
|
// Gets the spell level tool tip text based on the int spell level provided (i.e.
|
||||||
|
// 0 turns into "Cantrips")
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// spellLevel:int the spell level we want the tooltip for
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// string the spell level toop tip
|
||||||
|
//
|
||||||
|
string GetSpellLevelToolTip(int spellLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetSpellIcon
|
||||||
|
// Gets the spell icon based off the spellId, or featId supplied
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the class Id
|
||||||
|
// featId:int the featId we can use the icon for
|
||||||
|
// spellId:int the spell Id we want the icon for
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// json:String the string of the icon we want.
|
||||||
|
//
|
||||||
|
json GetSpellIcon(int spellId, int featId=0, int nClass=0);
|
||||||
|
string GetSpellName(int spellId, int realSpellID=0, int featId=0, int nClass=0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GreyOutButton
|
||||||
|
// Takes NUI Button along with it's width and height and greys it out it with a drawn
|
||||||
|
// colored rectangle to represent it's not been selected or not valid.
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// jButton:json the NUI Button
|
||||||
|
// w:float the width of the button
|
||||||
|
// h:float the height of the button
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// json the NUI button greyed out
|
||||||
|
//
|
||||||
|
json GreyOutButton(json jButton, float w, float h);
|
||||||
|
|
||||||
|
//
|
||||||
|
// CreateGreyOutRectangle
|
||||||
|
// Creates a grey out rectangle for buttons
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// w:float the width of the button
|
||||||
|
// h:float the height of the button
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// json the transparant black rectangle
|
||||||
|
//
|
||||||
|
json CreateGreyOutRectangle(float w, float h);
|
||||||
|
|
||||||
|
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
|
||||||
|
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
|
||||||
|
|
||||||
|
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||||
|
{
|
||||||
|
int currentLevel = nLevel;
|
||||||
|
|
||||||
|
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||||
|
if(nClass == CLASS_TYPE_WARBLADE
|
||||||
|
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||||
|
|| nClass == CLASS_TYPE_CRUSADER
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||||
|
{
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Binders don't really have a concept of spell level
|
||||||
|
if (nClass == CLASS_TYPE_BINDER
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
//Shadowsmith has no concept of spell levels
|
||||||
|
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
// Spont casters have their own function
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
|
||||||
|
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||||
|
return maxLevel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// everyone else uses this
|
||||||
|
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||||
|
|
||||||
|
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_PSION
|
||||||
|
|| nClass == CLASS_TYPE_PSYWAR
|
||||||
|
|| nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND)
|
||||||
|
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||||
|
|
||||||
|
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||||
|
|
||||||
|
// in case we somehow go over bounds just don't :)
|
||||||
|
if (currentLevel >= totalLevel)
|
||||||
|
currentLevel = totalLevel - 1;
|
||||||
|
|
||||||
|
//Psionics have MaxPowerLevel as their column name
|
||||||
|
string columnName = "MaxPowerLevel";
|
||||||
|
|
||||||
|
//Invokers have MaxInvocationLevel
|
||||||
|
if (nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||||
|
columnName = "MaxInvocationLevel";
|
||||||
|
|
||||||
|
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||||
|
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||||
|
{
|
||||||
|
columnName = "EvolvingMind";
|
||||||
|
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
columnName = "VestigeLvl";
|
||||||
|
spellLevel2da = "cls_bind_binder";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToB doesn't have a concept of this, but we don't care.
|
||||||
|
|
||||||
|
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||||
|
return maxLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetMinSpellLevel(int nClass)
|
||||||
|
{
|
||||||
|
// again sponts have their own function
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_PSION
|
||||||
|
|| nClass == CLASS_TYPE_PSYWAR
|
||||||
|
|| nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND
|
||||||
|
|| nClass == CLASS_TYPE_WARBLADE
|
||||||
|
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||||
|
|| nClass == CLASS_TYPE_CRUSADER
|
||||||
|
|| nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||||
|
|| nClass == CLASS_TYPE_BINDER)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return GetCurrentSpellLevel(nClass, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetMaxSpellLevel(int nClass)
|
||||||
|
{
|
||||||
|
if (nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSION)
|
||||||
|
return 9;
|
||||||
|
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND)
|
||||||
|
return 5;
|
||||||
|
if (nClass == CLASS_TYPE_PSYWAR)
|
||||||
|
return 6;
|
||||||
|
|
||||||
|
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetHighestLevelPossibleInClass(int nClass)
|
||||||
|
{
|
||||||
|
string sFile;
|
||||||
|
|
||||||
|
//sponts have their spells in the classes.2da
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// everyone else uses this
|
||||||
|
sFile = GetAMSKnownFileName(nClass);
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||||
|
{
|
||||||
|
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
sFile = "cls_bind_binder";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Get2DARowCount(sFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetClassSpellbookFile(int nClass)
|
||||||
|
{
|
||||||
|
string sFile;
|
||||||
|
// Spontaneous casters use a specific file name structure
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
sFile = GetFileForClass(nClass);
|
||||||
|
}
|
||||||
|
// everyone else uses this structure
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sFile = GetAMSDefinitionFileName(nClass);
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
sFile = "vestiges";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetSpellLevelIcon(int spellLevel)
|
||||||
|
{
|
||||||
|
switch (spellLevel)
|
||||||
|
{
|
||||||
|
case 0: return "ir_cantrips";
|
||||||
|
case 1: return "ir_level1";
|
||||||
|
case 2: return "ir_level2";
|
||||||
|
case 3: return "ir_level3";
|
||||||
|
case 4: return "ir_level4";
|
||||||
|
case 5: return "ir_level5";
|
||||||
|
case 6: return "ir_level6";
|
||||||
|
case 7: return "ir_level789";
|
||||||
|
case 8: return "ir_level789";
|
||||||
|
case 9: return "ir_level789";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetSpellLevelToolTip(int spellLevel)
|
||||||
|
{
|
||||||
|
switch (spellLevel)
|
||||||
|
{
|
||||||
|
case 0: return "Cantrips";
|
||||||
|
case 1: return "Level 1";
|
||||||
|
case 2: return "Level 2";
|
||||||
|
case 3: return "Level 3";
|
||||||
|
case 4: return "Level 4";
|
||||||
|
case 5: return "Level 5";
|
||||||
|
case 6: return "Level 6";
|
||||||
|
case 7: return "Level 7";
|
||||||
|
case 8: return "Level 8";
|
||||||
|
case 9: return "Level 9";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
json GetSpellIcon(int spellId,int featId=0,int nClass=0)
|
||||||
|
{
|
||||||
|
// Binder's spells don't have the FeatID on the spells.2da, so we have to use
|
||||||
|
// the mapping we constructed to get it.
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
json binderDict = GetBinderSpellToFeatDictionary();
|
||||||
|
int nFeatID = JsonGetInt(JsonObjectGet(binderDict, IntToString(spellId)));
|
||||||
|
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (featId)
|
||||||
|
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||||
|
|
||||||
|
int masterSpellID = StringToInt(Get2DACache("spells", "Master", spellId));
|
||||||
|
|
||||||
|
// if this is a sub radial spell, then we use spell's icon instead
|
||||||
|
if (masterSpellID)
|
||||||
|
return JsonString(Get2DACache("spells", "IconResRef", spellId));
|
||||||
|
|
||||||
|
// the FeatID holds the accurate spell icon, not the SpellID
|
||||||
|
int nFeatID = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||||
|
|
||||||
|
return JsonString(Get2DACache("feat", "Icon", nFeatID));
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetSpellName(int spellId, int realSpellID=0, int featId=0, int nClass=0)
|
||||||
|
{
|
||||||
|
if ((nClass == CLASS_TYPE_SHADOWSMITH
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWCASTER) && spellId)
|
||||||
|
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||||
|
if (nClass == CLASS_TYPE_TRUENAMER && featId)
|
||||||
|
return GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featId)));
|
||||||
|
if (realSpellID)
|
||||||
|
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", realSpellID)));
|
||||||
|
if (spellId)
|
||||||
|
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||||
|
if (featId)
|
||||||
|
return GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featId)));
|
||||||
|
|
||||||
|
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||||
|
{
|
||||||
|
// a dictionary of <SpellID, FeatID>
|
||||||
|
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||||
|
// if this hasn't been created, create it now.
|
||||||
|
if (binderDict == JsonNull())
|
||||||
|
binderDict = JsonObject();
|
||||||
|
else
|
||||||
|
return binderDict;
|
||||||
|
|
||||||
|
// the starting row for binder spells
|
||||||
|
int spellIndex = 19070;
|
||||||
|
// the starting row for binder feats
|
||||||
|
int featIndex = 9030;
|
||||||
|
//the end of the binder spells/feats
|
||||||
|
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||||
|
{
|
||||||
|
// get the SpellID tied to the feat
|
||||||
|
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||||
|
// if the spellID matches the current index, then this is the spell
|
||||||
|
// attached to the feat
|
||||||
|
if (spellID == spellIndex)
|
||||||
|
{
|
||||||
|
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||||
|
|
||||||
|
// move to next spell/feat
|
||||||
|
featIndex++;
|
||||||
|
spellIndex++;
|
||||||
|
}
|
||||||
|
// else we have reached a subdial spell
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// loop through until we reach back at spellID
|
||||||
|
while (spellIndex < spellID)
|
||||||
|
{
|
||||||
|
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||||
|
|
||||||
|
// add the sub radial to the dict, tied to the master's FeatID
|
||||||
|
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||||
|
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||||
|
|
||||||
|
spellIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||||
|
// if it happens then move on
|
||||||
|
if (spellIndex > spellID)
|
||||||
|
featIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the result
|
||||||
|
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||||
|
return binderDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
json GreyOutButton(json jButton, float w, float h)
|
||||||
|
{
|
||||||
|
json retValue = jButton;
|
||||||
|
|
||||||
|
json jBorders = JsonArray();
|
||||||
|
jBorders = JsonArrayInsert(jBorders, CreateGreyOutRectangle(w, h));
|
||||||
|
|
||||||
|
return NuiDrawList(jButton, JsonBool(FALSE), jBorders);
|
||||||
|
}
|
||||||
|
|
||||||
|
json CreateGreyOutRectangle(float w, float h)
|
||||||
|
{
|
||||||
|
// set the points of the button shape
|
||||||
|
json jPoints = JsonArray();
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||||
|
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||||
|
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||||
|
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||||
|
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||||
|
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||||
|
|
||||||
|
return NuiDrawListPolyLine(JsonBool(TRUE), NuiColor(0, 0, 0, 127), JsonBool(TRUE), JsonFloat(2.0), jPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0)
|
||||||
|
{
|
||||||
|
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_FEATID_VAR, featID);
|
||||||
|
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_SPELLID_VAR, spellId);
|
||||||
|
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR, realSpellId);
|
||||||
|
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR, nClass);
|
||||||
|
ExecuteScript("prc_nui_dsc_view", oPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF)
|
||||||
|
{
|
||||||
|
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_FEATID_VAR);
|
||||||
|
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_SPELLID_VAR);
|
||||||
|
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR);
|
||||||
|
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
||||||
|
}
|
||||||
|
|
||||||
3353
Notes/prc_nui_lv_inc.nss.bak
Normal file
3353
Notes/prc_nui_lv_inc.nss.bak
Normal file
File diff suppressed because it is too large
Load Diff
165
Notes/prc_onplayerchat.nss.bak
Normal file
165
Notes/prc_onplayerchat.nss.bak
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
//::///////////////////////////////////////////////
|
||||||
|
//:: OnPlayerChat eventscript
|
||||||
|
//:: prc_onplayerchat
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
A OnChat script that parses what is said and
|
||||||
|
uses any commands or NUI associated with
|
||||||
|
commands.
|
||||||
|
*/
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
//:: Updated By: Rakiov
|
||||||
|
//:: Created On: 22.05.2005
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
|
||||||
|
/*
|
||||||
|
PRC Chat Command Format:
|
||||||
|
~~command arg1 arg2 arg3 arg4 arg5
|
||||||
|
OR:
|
||||||
|
..command arg1 arg2 arg3 arg4 arg5
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "prc_alterations"
|
||||||
|
#include "prc_inc_chat"
|
||||||
|
#include "prc_inc_chat_dm"
|
||||||
|
#include "prc_inc_chat_pow"
|
||||||
|
#include "prc_inc_chat_shf"
|
||||||
|
#include "nw_inc_nui"
|
||||||
|
#include "prc_string_inc"
|
||||||
|
#include "prc_nui_sb_inc"
|
||||||
|
#include "prc_nui_consts"
|
||||||
|
#include "prc_nui_lv_inc"
|
||||||
|
|
||||||
|
const string CHAT_COMMAND_INDICATOR_1 = "~~";
|
||||||
|
const string CHAT_COMMAND_INDICATOR_2 = "..";
|
||||||
|
const int CHAT_COMMAND_INDICATOR_LENGHT = 2;
|
||||||
|
|
||||||
|
int GetIsChatCommand(string sString)
|
||||||
|
{
|
||||||
|
string sTest = GetStringLeft(sString, CHAT_COMMAND_INDICATOR_LENGHT);
|
||||||
|
if(sTest == CHAT_COMMAND_INDICATOR_1
|
||||||
|
|| sTest == CHAT_COMMAND_INDICATOR_2)
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
string RemoveChatCommandIndicator(string sString)
|
||||||
|
{
|
||||||
|
return GetStringRight(sString, GetStringLength(sString) - CHAT_COMMAND_INDICATOR_LENGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
object oPC = GetPCChatSpeaker();
|
||||||
|
string sChat = GetPCChatMessage();
|
||||||
|
|
||||||
|
if(GetIsChatCommand(sChat))
|
||||||
|
{
|
||||||
|
sChat = RemoveChatCommandIndicator(sChat);
|
||||||
|
SetPCChatVolume(TALKVOLUME_TELL); //Set volume for all chat commands
|
||||||
|
|
||||||
|
if(GetStringWord(sChat, 1) == "help")
|
||||||
|
{
|
||||||
|
if(GetStringWord(sChat, 2) == "")
|
||||||
|
{
|
||||||
|
HelpText(oPC, "=== HELP SUMMARY");
|
||||||
|
HelpText(oPC, "");
|
||||||
|
HelpText(oPC, "Chat commands start with ~~ or .. followed by the command name and then any parameters.");
|
||||||
|
HelpText(oPC, " For example '~~execute test_script' will run the script named 'test_script'.");
|
||||||
|
HelpText(oPC, "");
|
||||||
|
HelpText(oPC, "A hyphen in a command name indicates that the word may be abbreviated as short as the point where the hyphen is.");
|
||||||
|
HelpText(oPC, " For example, 'exec-ute' may be entered as 'execute', 'execu', or 'exec', but not as 'exe'.");
|
||||||
|
HelpText(oPC, "");
|
||||||
|
HelpText(oPC, "Typing '~~help' displays a summary of the available commands (what you're reading now).");
|
||||||
|
HelpText(oPC, "Typing '~~help <command-name>' displays more detailed information about the specified command.");
|
||||||
|
HelpText(oPC, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Debug_ProcessChatCommand_Help(oPC, sChat))
|
||||||
|
{}
|
||||||
|
else if (PowerAttack_ProcessChatCommand_Help(oPC, sChat))
|
||||||
|
{}
|
||||||
|
else if (PnPShifter_ProcessChatCommand_Help(oPC, sChat))
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Debug_ProcessChatCommand(oPC, sChat))
|
||||||
|
{}
|
||||||
|
else if (PowerAttack_ProcessChatCommand(oPC, sChat))
|
||||||
|
{}
|
||||||
|
else if (PnPShifter_ProcessChatCommand(oPC, sChat))
|
||||||
|
{}
|
||||||
|
else
|
||||||
|
SendMessageToPC(oPC, "Unrecognized chat command: " + sChat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(GetLocalInt(oPC, PRC_CHAT_HOOK_ACTIVE))
|
||||||
|
{
|
||||||
|
SetPCChatVolume(TALKVOLUME_TELL);
|
||||||
|
SetLocalString(oPC, PRC_PLAYER_RESPONSE, sChat);
|
||||||
|
ExecuteScript(GetLocalString(oPC, PRC_CHAT_HOOK_SCRIPT), oPC);
|
||||||
|
_clear_chat_vars(oPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get current player message and split it up into a list
|
||||||
|
string sCommand = GetPCChatMessage();
|
||||||
|
json sCommandSplit = StringSplit(sChat);
|
||||||
|
|
||||||
|
if(JsonGetLength(sCommandSplit) > 0)
|
||||||
|
{
|
||||||
|
string firstWord = JsonGetString(JsonArrayGet(sCommandSplit, 0));
|
||||||
|
|
||||||
|
// if first word is /pa we are using the power attack interface
|
||||||
|
if(firstWord == "/pa")
|
||||||
|
{
|
||||||
|
if(JsonGetLength(sCommandSplit) >= 2)
|
||||||
|
{
|
||||||
|
//if a parameter is given then run the power attack command directly.
|
||||||
|
string param1 = JsonGetString(JsonArrayGet(sCommandSplit, 1));
|
||||||
|
int paAmount = StringToInt(param1);
|
||||||
|
SetLocalInt(oPC, "PRC_PowerAttack_Level", paAmount);
|
||||||
|
ExecuteScript("prc_nui_pa_trggr", oPC);
|
||||||
|
|
||||||
|
// update the NUI so it is in sync
|
||||||
|
int nToken = NuiFindWindow(oPC, NUI_PRC_POWER_ATTACK_WINDOW);
|
||||||
|
if (nToken != 0)
|
||||||
|
{
|
||||||
|
NuiSetBind(oPC, nToken, NUI_PRC_PA_TEXT_BIND, JsonString(IntToString(paAmount)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// if no param is given then open the NUI
|
||||||
|
ExecuteScript("prc_nui_pa_view", oPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear message from chat
|
||||||
|
SetPCChatMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If the first word is /sb then we open the Spellbook NUI
|
||||||
|
if(firstWord == "/sb")
|
||||||
|
{
|
||||||
|
ExecuteScript("prc_nui_sb_view", oPC);
|
||||||
|
|
||||||
|
// clear message from chat
|
||||||
|
SetPCChatMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (firstWord == "/lvl")
|
||||||
|
{
|
||||||
|
if (JsonGetLength(sCommandSplit) >= 2)
|
||||||
|
{
|
||||||
|
int classPos = StringToInt(JsonGetString(JsonArrayGet(sCommandSplit, 1)));
|
||||||
|
int nClass = GetClassByPosition(classPos, oPC);
|
||||||
|
OpenNUILevelUpWindow(nClass, oPC);
|
||||||
|
SetPCChatMessage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute scripts hooked to this event for the player triggering it
|
||||||
|
ExecuteAllScriptsHookedToEvent(oPC, EVENT_ONPLAYERCHAT);
|
||||||
|
}
|
||||||
@@ -129,7 +129,7 @@
|
|||||||
125 Soulcaster 16790611 16837012 16837013 16837014 16837015 IR_MYSTIC 4 CLS_ATK_3 CLS_FEAT_SOULC CLS_SAVTHR_WIZ CLS_SKILL_SOULC CLS_BFEAT_SOULC 2 **** **** 1 0 10 11 11 16 16 10 INT 0X00 0X0 0 CLASS_TYPE_SOULCASTER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_SOULC 40 0 1 0 10 10 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
125 Soulcaster 16790611 16837012 16837013 16837014 16837015 IR_MYSTIC 4 CLS_ATK_3 CLS_FEAT_SOULC CLS_SAVTHR_WIZ CLS_SKILL_SOULC CLS_BFEAT_SOULC 2 **** **** 1 0 10 11 11 16 16 10 INT 0X00 0X0 0 CLASS_TYPE_SOULCASTER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_SOULC 40 0 1 0 10 10 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
126 Sacred_Fist 16790612 16825367 16825368 16825369 16825370 IR_SACREDFIST 8 CLS_ATK_1 CLS_FEAT_SACFIS CLS_SAVTHR_WILD CLS_SKILL_SACFIS CLS_BFEAT_SACFIS 4 **** **** 1 0 14 14 12 16 10 10 WIS 0X00 0X0 0 CLASS_TYPE_SACREDFIST 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_SACFIS 40 0 0 1 10 5 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
126 Sacred_Fist 16790612 16825367 16825368 16825369 16825370 IR_SACREDFIST 8 CLS_ATK_1 CLS_FEAT_SACFIS CLS_SAVTHR_WILD CLS_SKILL_SACFIS CLS_BFEAT_SACFIS 4 **** **** 1 0 14 14 12 16 10 10 WIS 0X00 0X0 0 CLASS_TYPE_SACREDFIST 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_SACFIS 40 0 0 1 10 5 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
127 Legendary_Dreadnought 16790613 16826086 16826087 16826088 16826089 IC_LEGDREAD 12 CLS_ATK_1 CLS_FEAT_LGDR CLS_SAVTHR_FIGHT CLS_SKILL_LGDR CLS_BFEAT_LGDR 2 **** **** 1 0 16 13 16 10 10 9 STR 0X00 0X0 0 CLASS_TYPE_LEGENDARY_DREADNOUGHT 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_LGDR 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
127 Legendary_Dreadnought 16790613 16826086 16826087 16826088 16826089 IC_LEGDREAD 12 CLS_ATK_1 CLS_FEAT_LGDR CLS_SAVTHR_FIGHT CLS_SKILL_LGDR CLS_BFEAT_LGDR 2 **** **** 1 0 16 13 16 10 10 9 STR 0X00 0X0 0 CLASS_TYPE_LEGENDARY_DREADNOUGHT 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_LGDR 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
128 Disciple_of_Baalzebul 16790614 16826094 16826095 16826096 16826097 IC_BAALZEBUL 6 CLS_ATK_2 CLS_FEAT_BAAL CLS_SAVTHR_BARD CLS_SKILL_BAAL CLS_BFEAT_BAAL 6 **** **** 1 0 12 14 14 10 12 15 CHA 0X09 0X2 0 CLASS_TYPE_DISC_BAALZEBUL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_BAAL 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
128 Disciple_of_Baalzebul 16790614 16826094 16826095 16826096 16826097 IC_BAALZEBUL 6 CLS_ATK_2 CLS_FEAT_BAAL CLS_SAVTHR_BARD CLS_SKILL_BAAL CLS_BFEAT_BAAL 6 **** **** 1 0 12 14 14 10 12 15 CHA 0X09 0X2 0 CLASS_TYPE_DISC_BAALZEBUL 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_BAAL 40 0 0 0 10 4 0 cls_stat_baal **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
129 Mighty_Contender_of_Kord 16790615 16824935 16824936 16824937 16824938 IC_LEGDREAD 10 CLS_ATK_2 CLS_FEAT_KORD CLS_SAVTHR_CLER CLS_SKILL_KORD CLS_BFEAT_KORD 2 **** **** 1 0 14 8 14 16 10 14 WIS 0X00 0X0 0 CLASS_TYPE_MIGHTY_CONTENDER_KORD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_KORD 40 0 0 1 10 4 0 cls_stat_kord **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
129 Mighty_Contender_of_Kord 16790615 16824935 16824936 16824937 16824938 IC_LEGDREAD 10 CLS_ATK_2 CLS_FEAT_KORD CLS_SAVTHR_CLER CLS_SKILL_KORD CLS_BFEAT_KORD 2 **** **** 1 0 14 8 14 16 10 14 WIS 0X00 0X0 0 CLASS_TYPE_MIGHTY_CONTENDER_KORD 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_KORD 40 0 0 1 10 4 0 cls_stat_kord **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
130 Iaijutsu_Master 16790616 16826114 16826115 16826116 16826117 IC_IAIJUTSU 10 CLS_ATK_1 CLS_FEAT_IAIJ CLS_SAVTHR_ROG CLS_SKILL_IAIJ CLS_BFEAT_IAIJ 4 **** **** 1 0 16 13 16 10 10 9 CHA 0X05 0X1 0 CLASS_TYPE_IAIJUTSU_MASTER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_IAIJ 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
130 Iaijutsu_Master 16790616 16826114 16826115 16826116 16826117 IC_IAIJUTSU 10 CLS_ATK_1 CLS_FEAT_IAIJ CLS_SAVTHR_ROG CLS_SKILL_IAIJ CLS_BFEAT_IAIJ 4 **** **** 1 0 16 13 16 10 10 9 CHA 0X05 0X1 0 CLASS_TYPE_IAIJUTSU_MASTER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_IAIJ 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
131 Disciple_of_Dispater 16790617 16826136 16826137 16826138 16826139 IR_BLKGRD 10 CLS_ATK_1 CLS_FEAT_DISP CLS_SAVTHR_MONK CLS_SKILL_DISP CLS_BFEAT_DISP 4 **** **** 1 0 16 13 16 10 10 9 CON 0X09 0X2 0 CLASS_TYPE_DISPATER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_DISP 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
131 Disciple_of_Dispater 16790617 16826136 16826137 16826138 16826139 IR_BLKGRD 10 CLS_ATK_1 CLS_FEAT_DISP CLS_SAVTHR_MONK CLS_SKILL_DISP CLS_BFEAT_DISP 4 **** **** 1 0 16 13 16 10 10 9 CON 0X09 0X2 0 CLASS_TYPE_DISPATER 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 CLS_PRES_DISP 40 0 0 0 10 4 0 **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
18 FEAT_EKNIGHT_SPELLCASTING_SUEL_ARCHANAMACH 18960 2 1 0
|
18 FEAT_EKNIGHT_SPELLCASTING_SUEL_ARCHANAMACH 18960 2 1 0
|
||||||
19 FEAT_EKNIGHT_SPELLCASTING_WARMAGE 19002 2 1 0
|
19 FEAT_EKNIGHT_SPELLCASTING_WARMAGE 19002 2 1 0
|
||||||
20 FEAT_EKNIGHT_SPELLCASTING_WIZARD 19047 2 1 0
|
20 FEAT_EKNIGHT_SPELLCASTING_WIZARD 19047 2 1 0
|
||||||
|
21 FEAT_EPIC_SWARM_OF_ARROWS 25995 1 -1 0
|
||||||
21 Ambidex 1 1 -1 0
|
21 Ambidex 1 1 -1 0
|
||||||
22 CShot 5 1 -1 0
|
22 CShot 5 1 -1 0
|
||||||
23 Cleave 6 1 -1 0
|
23 Cleave 6 1 -1 0
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
74 Bane_Magic_Undead 23578 0 -1 0
|
74 Bane_Magic_Undead 23578 0 -1 0
|
||||||
75 Bane_Magic_Vermin 23579 0 -1 0
|
75 Bane_Magic_Vermin 23579 0 -1 0
|
||||||
76 **Epic_Feats** **** **** **** ****
|
76 **Epic_Feats** **** **** **** ****
|
||||||
77 FEAT_EPIC_ELDRITCH_THEURGE 23516 3 21 0
|
77 FEAT_EPIC_ELDRITCH_THEURGE 23516 3 11 0
|
||||||
78 FEAT_CRAFT_EPIC_WONDROUS_ITEM 3488 0 -1 0
|
78 FEAT_CRAFT_EPIC_WONDROUS_ITEM 3488 0 -1 0
|
||||||
79 FEAT_CRAFT_EPIC_MAGIC_ARMS_AND_ARMOR 3489 0 -1 0
|
79 FEAT_CRAFT_EPIC_MAGIC_ARMS_AND_ARMOR 3489 0 -1 0
|
||||||
80 FEAT_CRAFT_EPIC_ROD 3490 0 -1 0
|
80 FEAT_CRAFT_EPIC_ROD 3490 0 -1 0
|
||||||
|
|||||||
@@ -20,54 +20,51 @@
|
|||||||
16 WeapProfSim_Dart 7914 3 1 0
|
16 WeapProfSim_Dart 7914 3 1 0
|
||||||
17 WeapProfSim_Light_Mace 7908 3 1 0
|
17 WeapProfSim_Light_Mace 7908 3 1 0
|
||||||
18 WeapProfSim_Morningstar 7923 3 1 0
|
18 WeapProfSim_Morningstar 7923 3 1 0
|
||||||
19 WeapProfSim_Sickle 7929 3 1 0
|
19 WP_Sap 7944 3 1 0
|
||||||
20 WeapProfSim_Sling 7930 3 1 0
|
20 WP_LightCrossbow 7951 3 1 0
|
||||||
21 WP_Katar 7945 3 1 0
|
21 WP_HeavyCrossbow 7952 3 1 0
|
||||||
22 WP_Sap 7944 3 1 0
|
22 WP_Quarterstaff 7953 3 1 0
|
||||||
23 WP_LightCrossbow 7951 3 1 0
|
23 WP_Dagger 7954 3 1 0
|
||||||
24 WP_HeavyCrossbow 7952 3 1 0
|
24 WP_Club 7955 3 1 0
|
||||||
25 WP_Quarterstaff 7953 3 1 0
|
25 WP_Shortsword 7901 3 1 0
|
||||||
26 WP_Dagger 7954 3 1 0
|
26 WP_Shortbow 7910 3 1 0
|
||||||
27 WP_Club 7955 3 1 0
|
27 WP_Rapier 7924 3 1 0
|
||||||
28 WP_Shortsword 7901 3 1 0
|
28 ArmProfLgt 3 3 1 0
|
||||||
29 WP_Shortbow 7910 3 1 0
|
29 FEAT_EPIC_BLINDING_SPEED 491 1 -1 1
|
||||||
30 WP_Rapier 7924 3 1 0
|
30 FEAT_EPIC_SKILL_FOCUS_APPRAISE 588 1 -1 0
|
||||||
31 ArmProfLgt 3 3 1 0
|
31 FEAT_EPIC_SKILL_FOCUS_CONCENTRATION 589 1 -1 0
|
||||||
32 FEAT_EPIC_BLINDING_SPEED 491 1 -1 1
|
32 FEAT_EPIC_SKILL_FOCUS_CRAFT_TRAP 590 1 -1 0
|
||||||
33 FEAT_EPIC_SKILL_FOCUS_APPRAISE 588 1 -1 0
|
33 FEAT_EPIC_SKILL_FOCUS_DISABLETRAP 591 1 -1 0
|
||||||
34 FEAT_EPIC_SKILL_FOCUS_CONCENTRATION 589 1 -1 0
|
34 FEAT_EPIC_SKILL_FOCUS_DISCIPLINE 592 1 -1 0
|
||||||
35 FEAT_EPIC_SKILL_FOCUS_CRAFT_TRAP 590 1 -1 0
|
35 FEAT_EPIC_SKILL_FOCUS_HEAL 593 1 -1 0
|
||||||
36 FEAT_EPIC_SKILL_FOCUS_DISABLETRAP 591 1 -1 0
|
36 FEAT_EPIC_SKILL_FOCUS_HIDE 594 1 -1 0
|
||||||
37 FEAT_EPIC_SKILL_FOCUS_DISCIPLINE 592 1 -1 0
|
37 FEAT_EPIC_SKILL_FOCUS_LISTEN 595 1 -1 0
|
||||||
38 FEAT_EPIC_SKILL_FOCUS_HEAL 593 1 -1 0
|
38 FEAT_EPIC_SKILL_FOCUS_LORE 596 1 -1 0
|
||||||
39 FEAT_EPIC_SKILL_FOCUS_HIDE 594 1 -1 0
|
39 FEAT_EPIC_SKILL_FOCUS_MOVESILENTLY 597 1 -1 0
|
||||||
40 FEAT_EPIC_SKILL_FOCUS_LISTEN 595 1 -1 0
|
40 FEAT_EPIC_SKILL_FOCUS_OPENLOCK 598 1 -1 0
|
||||||
41 FEAT_EPIC_SKILL_FOCUS_LORE 596 1 -1 0
|
41 FEAT_EPIC_SKILL_FOCUS_PARRY 599 1 -1 0
|
||||||
42 FEAT_EPIC_SKILL_FOCUS_MOVESILENTLY 597 1 -1 0
|
42 FEAT_EPIC_SKILL_FOCUS_PERSUADE 601 1 -1 0
|
||||||
43 FEAT_EPIC_SKILL_FOCUS_OPENLOCK 598 1 -1 0
|
43 FEAT_EPIC_SKILL_FOCUS_PICKPOCKET 602 1 -1 0
|
||||||
44 FEAT_EPIC_SKILL_FOCUS_PARRY 599 1 -1 0
|
44 FEAT_EPIC_SKILL_FOCUS_SEARCH 603 1 -1 0
|
||||||
45 FEAT_EPIC_SKILL_FOCUS_PERSUADE 601 1 -1 0
|
45 FEAT_EPIC_SKILL_FOCUS_SETTRAP 604 1 -1 0
|
||||||
46 FEAT_EPIC_SKILL_FOCUS_PICKPOCKET 602 1 -1 0
|
46 FEAT_EPIC_SKILL_FOCUS_SPELLCRAFT 605 1 -1 0
|
||||||
47 FEAT_EPIC_SKILL_FOCUS_SEARCH 603 1 -1 0
|
47 FEAT_EPIC_SKILL_FOCUS_SPOT 606 1 -1 0
|
||||||
48 FEAT_EPIC_SKILL_FOCUS_SETTRAP 604 1 -1 0
|
48 FEAT_EPIC_SKILL_FOCUS_TAUNT 607 1 -1 0
|
||||||
49 FEAT_EPIC_SKILL_FOCUS_SPELLCRAFT 605 1 -1 0
|
49 FEAT_EPIC_SKILL_FOCUS_TUMBLE 608 1 -1 0
|
||||||
50 FEAT_EPIC_SKILL_FOCUS_SPOT 606 1 -1 0
|
50 FEAT_EPIC_SKILL_FOCUS_USEMAGICDEVICE 609 1 -1 0
|
||||||
51 FEAT_EPIC_SKILL_FOCUS_TAUNT 607 1 -1 0
|
51 FEAT_EPIC_SELF_CONCEALMENT_10 748 1 -1 0
|
||||||
52 FEAT_EPIC_SKILL_FOCUS_TUMBLE 608 1 -1 0
|
52 FEAT_EPIC_SELF_CONCEALMENT_20 749 1 -1 0
|
||||||
53 FEAT_EPIC_SKILL_FOCUS_USEMAGICDEVICE 609 1 -1 0
|
53 FEAT_EPIC_SELF_CONCEALMENT_30 750 1 -1 0
|
||||||
54 FEAT_EPIC_SELF_CONCEALMENT_10 748 1 -1 0
|
54 FEAT_EPIC_SELF_CONCEALMENT_40 751 1 -1 0
|
||||||
55 FEAT_EPIC_SELF_CONCEALMENT_20 749 1 -1 0
|
55 FEAT_EPIC_SELF_CONCEALMENT_50 752 1 -1 0
|
||||||
56 FEAT_EPIC_SELF_CONCEALMENT_30 750 1 -1 0
|
56 FEAT_EPIC_SUPERIOR_INITIATIVE 753 1 -1 0
|
||||||
57 FEAT_EPIC_SELF_CONCEALMENT_40 751 1 -1 0
|
57 FEAT_EPIC_DODGE 856 1 -1 0
|
||||||
58 FEAT_EPIC_SELF_CONCEALMENT_50 752 1 -1 0
|
58 FEAT_IMPROVED_WHIRLWIND 868 1 -1 0
|
||||||
59 FEAT_EPIC_SUPERIOR_INITIATIVE 753 1 -1 0
|
59 FEAT_EPIC_SKILL_FOCUS_CRAFT_ARMOR 913 1 -1 0
|
||||||
60 FEAT_EPIC_DODGE 856 1 -1 0
|
60 FEAT_EPIC_SKILL_FOCUS_CRAFT_WEAPON 914 1 -1 0
|
||||||
61 FEAT_IMPROVED_WHIRLWIND 868 1 -1 0
|
61 FEAT_EPIC_SKILL_FOCUS_BLUFF 917 1 -1 0
|
||||||
62 FEAT_EPIC_SKILL_FOCUS_CRAFT_ARMOR 913 1 -1 0
|
62 FEAT_EPIC_SKILL_FOCUS_INTIMIDATE 918 1 -1 0
|
||||||
63 FEAT_EPIC_SKILL_FOCUS_CRAFT_WEAPON 914 1 -1 0
|
63 FEAT_EPIC_SHADOWDANCER 980 3 11 0
|
||||||
64 FEAT_EPIC_SKILL_FOCUS_BLUFF 917 1 -1 0
|
64 FEAT_EPIC_EPIC_SHADOWLORD 1002 2 -1 0
|
||||||
65 FEAT_EPIC_SKILL_FOCUS_INTIMIDATE 918 1 -1 0
|
65 FEAT_EPIC_REFLEXES 585 1 -1 0
|
||||||
66 FEAT_EPIC_SHADOWDANCER 980 3 11 0
|
66 FEAT_LINGERING_DAMAGE 3099 0 -1 0
|
||||||
67 FEAT_EPIC_EPIC_SHADOWLORD 1002 2 -1 0
|
|
||||||
68 FEAT_EPIC_REFLEXES 585 1 -1 0
|
|
||||||
69 FEAT_LINGERING_DAMAGE 3099 0 -1 0
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
36 WP_Falchion 7943 3 1 0
|
36 WP_Falchion 7943 3 1 0
|
||||||
37 WP_Maul 7947 3 1 0
|
37 WP_Maul 7947 3 1 0
|
||||||
38 WP_Kukri 7922 3 1 0
|
38 WP_Kukri 7922 3 1 0
|
||||||
39 WP_Scythe 7926 3 1 1
|
39 WP_Scythe 7926 3 1 0
|
||||||
40 ReadyManeuver 1960 3 1 1
|
40 ReadyManeuver 1960 3 1 1
|
||||||
41 RecoverManeuvers 1973 3 1 1
|
41 RecoverManeuvers 1973 3 1 1
|
||||||
42 **** **** **** **** ****
|
42 **** **** **** **** ****
|
||||||
|
|||||||
43
nwn/nwnprc/trunk/2das/cls_stat_baal.2da
Normal file
43
nwn/nwnprc/trunk/2das/cls_stat_baal.2da
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
2DA V2.0
|
||||||
|
|
||||||
|
Level Str Dex Con Wis Int Cha NaturalAC
|
||||||
|
0 1 **** **** **** **** **** **** ****
|
||||||
|
1 2 **** **** **** **** **** **** ****
|
||||||
|
2 3 **** **** **** **** **** **** ****
|
||||||
|
3 4 **** **** **** **** **** **** ****
|
||||||
|
4 5 **** **** **** **** **** **** ****
|
||||||
|
5 6 **** **** **** **** **** **** ****
|
||||||
|
6 7 **** **** **** **** **** **** ****
|
||||||
|
7 8 **** **** **** **** **** **** ****
|
||||||
|
8 9 **** **** **** **** **** **** ****
|
||||||
|
9 10 **** **** **** **** **** 4 ****
|
||||||
|
10 11 **** **** **** **** **** **** ****
|
||||||
|
11 12 **** **** **** **** **** **** ****
|
||||||
|
12 13 **** **** **** **** **** **** ****
|
||||||
|
13 14 **** **** **** **** **** **** ****
|
||||||
|
14 15 **** **** **** **** **** **** ****
|
||||||
|
15 16 **** **** **** **** **** **** ****
|
||||||
|
16 17 **** **** **** **** **** **** ****
|
||||||
|
17 18 **** **** **** **** **** **** ****
|
||||||
|
18 19 **** **** **** **** **** **** ****
|
||||||
|
19 20 **** **** **** **** **** **** ****
|
||||||
|
20 21 **** **** **** **** **** **** ****
|
||||||
|
21 22 **** **** **** **** **** **** ****
|
||||||
|
22 23 **** **** **** **** **** **** ****
|
||||||
|
23 24 **** **** **** **** **** **** ****
|
||||||
|
24 25 **** **** **** **** **** **** ****
|
||||||
|
25 26 **** **** **** **** **** **** ****
|
||||||
|
26 27 **** **** **** **** **** **** ****
|
||||||
|
27 28 **** **** **** **** **** **** ****
|
||||||
|
28 29 **** **** **** **** **** **** ****
|
||||||
|
29 30 **** **** **** **** **** **** ****
|
||||||
|
30 31 **** **** **** **** **** **** ****
|
||||||
|
31 32 **** **** **** **** **** **** ****
|
||||||
|
32 33 **** **** **** **** **** **** ****
|
||||||
|
33 34 **** **** **** **** **** **** ****
|
||||||
|
34 35 **** **** **** **** **** **** ****
|
||||||
|
35 36 **** **** **** **** **** **** ****
|
||||||
|
36 37 **** **** **** **** **** **** ****
|
||||||
|
37 38 **** **** **** **** **** **** ****
|
||||||
|
38 39 **** **** **** **** **** **** ****
|
||||||
|
39 40 **** **** **** **** **** **** ****
|
||||||
@@ -2349,7 +2349,7 @@
|
|||||||
2345 ShieldCharge **** **** **** **** **** ****
|
2345 ShieldCharge **** **** **** **** **** ****
|
||||||
2346 ShieldSlam **** **** **** **** **** ****
|
2346 ShieldSlam **** **** **** **** **** ****
|
||||||
2347 PhantomSteed **** **** **** **** **** ****
|
2347 PhantomSteed **** **** **** **** **** ****
|
||||||
2348 GaseousForm **** **** **** **** **** ****
|
2348 GaseousForm prc_scr_1564 **** **** **** **** prc_scr_1564
|
||||||
2349 begin_psionics **** **** **** **** **** ****
|
2349 begin_psionics **** **** **** **** **** ****
|
||||||
2350 Augment_QuickSelects **** **** **** **** **** ****
|
2350 Augment_QuickSelects **** **** **** **** **** ****
|
||||||
2351 Augment_Digits_0_4 **** **** **** **** **** ****
|
2351 Augment_Digits_0_4 **** **** **** **** **** ****
|
||||||
|
|||||||
@@ -2349,7 +2349,7 @@
|
|||||||
2345 ShieldCharge **** 1 1 1 **** 0
|
2345 ShieldCharge **** 1 1 1 **** 0
|
||||||
2346 ShieldSlam **** 1 1 1 **** 0
|
2346 ShieldSlam **** 1 1 1 **** 0
|
||||||
2347 PhantomSteed **** 1 1 1 3 0
|
2347 PhantomSteed **** 1 1 1 3 0
|
||||||
2348 GaseousForm **** 1 1 1 3 0
|
2348 GaseousForm 1564 0 0 0 3 0
|
||||||
2349 begin_psionics **** 1 1 1 **** 0
|
2349 begin_psionics **** 1 1 1 **** 0
|
||||||
2350 Augment_QuickSelects **** 1 1 1 **** 0
|
2350 Augment_QuickSelects **** 1 1 1 **** 0
|
||||||
2351 Augment_Digits_0_4 **** 1 1 1 **** 0
|
2351 Augment_Digits_0_4 **** 1 1 1 **** 0
|
||||||
@@ -12696,9 +12696,9 @@
|
|||||||
12692 Favoured_Soul_Enthrall **** 1 1 1 2 0
|
12692 Favoured_Soul_Enthrall **** 1 1 1 2 0
|
||||||
12693 Favoured_Soul_SPIRITUAL_WEAPON **** 1 1 1 2 0
|
12693 Favoured_Soul_SPIRITUAL_WEAPON **** 1 1 1 2 0
|
||||||
12694 Favoured_Soul_REGEN_LIGHT_WOUNDS **** 1 1 1 1 0
|
12694 Favoured_Soul_REGEN_LIGHT_WOUNDS **** 1 1 1 1 0
|
||||||
12695 Favoured_Soul_REGEN_MODERATE_WOUNDS **** 1 1 1 2 0
|
12695 Favoured_Soul_REGEN_MODERATE_WOUNDS **** 1 1 1 3 0
|
||||||
12696 Favoured_Soul_REGEN_SERIOUS_WOUNDS **** 1 1 1 4 0
|
12696 Favoured_Soul_REGEN_SERIOUS_WOUNDS **** 1 1 1 5 0
|
||||||
12697 Favoured_Soul_REGEN_CRITICAL_WOUNDS **** 1 1 1 5 0
|
12697 Favoured_Soul_REGEN_CRITICAL_WOUNDS **** 1 1 1 6 0
|
||||||
12698 Favoured_Soul_Hallow **** 1 1 1 6 0
|
12698 Favoured_Soul_Hallow **** 1 1 1 6 0
|
||||||
12699 Favoured_Soul_SPELL_CHASING_PERFECTION **** 1 1 1 6 0
|
12699 Favoured_Soul_SPELL_CHASING_PERFECTION **** 1 1 1 6 0
|
||||||
12700 Sohei_Silent_Bless_Weapon **** 1 1 1 2 0
|
12700 Sohei_Silent_Bless_Weapon **** 1 1 1 2 0
|
||||||
|
|||||||
@@ -300,3 +300,4 @@
|
|||||||
296 SPELL_MASS_INFLICT_MODERATE_DAMAGE 16976462 17111 6
|
296 SPELL_MASS_INFLICT_MODERATE_DAMAGE 16976462 17111 6
|
||||||
297 SPELL_MASS_INFLICT_SERIOUS_DAMAGE 16976468 17112 7
|
297 SPELL_MASS_INFLICT_SERIOUS_DAMAGE 16976468 17112 7
|
||||||
298 SPELL_MASS_INFLICT_CRITICAL_DAMAGE 16976474 17113 8
|
298 SPELL_MASS_INFLICT_CRITICAL_DAMAGE 16976474 17113 8
|
||||||
|
299 SPELL_GASEOUS_FORM 16835585 2348 3
|
||||||
|
|||||||
@@ -1537,17 +1537,17 @@
|
|||||||
1522 SPELL_INFLICT_MODERATE_DAMAGE_3 16976416 3 2 1250 17096 1 1 1 iss_X1InfMod
|
1522 SPELL_INFLICT_MODERATE_DAMAGE_3 16976416 3 2 1250 17096 1 1 1 iss_X1InfMod
|
||||||
1523 SPELL_INFLICT_MODERATE_DAMAGE_6 16976417 6 2 2250 17096 1 1 1 iss_X1InfMod
|
1523 SPELL_INFLICT_MODERATE_DAMAGE_6 16976417 6 2 2250 17096 1 1 1 iss_X1InfMod
|
||||||
1524 SPELL_INFLICT_MODERATE_DAMAGE_10 16976418 10 2 3750 17096 1 1 1 iss_X1InfMod
|
1524 SPELL_INFLICT_MODERATE_DAMAGE_10 16976418 10 2 3750 17096 1 1 1 iss_X1InfMod
|
||||||
1525 SPELL_INFLICT_SERIOUS_DAMAGE_5 16976422 5 3 2500 17097 1 1 1 iss_X1InfSer
|
1525 SPELL_INFLICT_SERIOUS_DAMAGE_5 16976422 5 3 11250 17097 1 1 1 iss_X1InfSer
|
||||||
1526 SPELL_INFLICT_SERIOUS_DAMAGE_10 16976423 10 3 5000 17097 1 1 1 iss_X1InfSer
|
1526 SPELL_INFLICT_SERIOUS_DAMAGE_10 16976423 10 3 22500 17097 1 1 1 iss_X1InfSer
|
||||||
1527 SPELL_INFLICT_SERIOUS_DAMAGE_15 16976424 15 3 7500 17097 1 1 1 iss_X1InfSer
|
1527 SPELL_INFLICT_SERIOUS_DAMAGE_15 16976424 15 3 33750 17097 1 1 1 iss_X1InfSer
|
||||||
1528 SPELL_INFLICT_CRITICAL_DAMAGE_7 16976428 7 4 10500 17098 1 1 1 iss_X1InfCri
|
1528 SPELL_INFLICT_CRITICAL_DAMAGE_7 16976428 7 4 21000 17098 1 1 1 iss_X1InfCri
|
||||||
1529 SPELL_INFLICT_CRITICAL_DAMAGE_15 16976429 15 4 22500 17098 1 1 1 iss_X1InfCri
|
1529 SPELL_INFLICT_CRITICAL_DAMAGE_15 16976429 15 4 45000 17098 1 1 1 iss_X1InfCri
|
||||||
1530 SPELL_INFLICT_CRITICAL_DAMAGE_20 16976430 20 4 30000 17098 1 1 1 iss_X1InfCri
|
1530 SPELL_INFLICT_CRITICAL_DAMAGE_20 16976430 20 4 60000 17098 1 1 1 iss_X1InfCri
|
||||||
1531 SPELL_MASS_REPAIR_LIGHT_DAMAGE_9 16976434 9 5 16875 17106 0 0 1 is_CurLgtW
|
1531 SPELL_MASS_REPAIR_LIGHT_DAMAGE_9 16976434 9 5 33750 17106 0 0 1 is_CurLgtW
|
||||||
1532 SPELL_MASS_REPAIR_LIGHT_DAMAGE_15 16976435 15 5 28125 17106 0 0 1 is_CurLgtW
|
1532 SPELL_MASS_REPAIR_LIGHT_DAMAGE_15 16976435 15 5 56250 17106 0 0 1 is_CurLgtW
|
||||||
1533 SPELL_MASS_REPAIR_LIGHT_DAMAGE_20 16976436 20 5 37500 17106 0 0 1 is_CurLgtW
|
1533 SPELL_MASS_REPAIR_LIGHT_DAMAGE_20 16976436 20 5 75000 17106 0 0 1 is_CurLgtW
|
||||||
1534 SPELL_MASS_REPAIR_MODERATE_DAMAGE_11 16976440 11 6 20625 17107 0 0 1 is_CurModW
|
1534 SPELL_MASS_REPAIR_MODERATE_DAMAGE_11 16976440 11 6 49500 17107 0 0 1 is_CurModW
|
||||||
1535 SPELL_MASS_REPAIR_MODERATE_DAMAGE_15 16976441 15 6 28125 17107 0 0 1 is_CurModW
|
1535 SPELL_MASS_REPAIR_MODERATE_DAMAGE_15 16976441 15 6 67500 17107 0 0 1 is_CurModW
|
||||||
1536 SPELL_MASS_REPAIR_MODERATE_DAMAGE_20 16976442 20 6 37500 17107 0 0 1 is_CurModW
|
1536 SPELL_MASS_REPAIR_MODERATE_DAMAGE_20 16976442 20 6 37500 17107 0 0 1 is_CurModW
|
||||||
1537 SPELL_MASS_REPAIR_SERIOUS_DAMAGE_13 16976446 13 7 24375 17108 0 0 1 is_CurSerW
|
1537 SPELL_MASS_REPAIR_SERIOUS_DAMAGE_13 16976446 13 7 24375 17108 0 0 1 is_CurSerW
|
||||||
1538 SPELL_MASS_REPAIR_SERIOUS_DAMAGE_16 16976447 16 7 30000 17108 0 0 1 is_CurSerW
|
1538 SPELL_MASS_REPAIR_SERIOUS_DAMAGE_16 16976447 16 7 30000 17108 0 0 1 is_CurSerW
|
||||||
@@ -1565,3 +1565,6 @@
|
|||||||
1550 SPELL_MASS_INFLICT_SERIOUS_DAMAGE_20 16976472 20 7 37500 17113 0 0 1 iss_infserwm
|
1550 SPELL_MASS_INFLICT_SERIOUS_DAMAGE_20 16976472 20 7 37500 17113 0 0 1 iss_infserwm
|
||||||
1551 SPELL_MASS_INFLICT_CRITICAL_DAMAGE_15 16976476 15 8 28125 17114 0 0 1 iss_infcrwnm
|
1551 SPELL_MASS_INFLICT_CRITICAL_DAMAGE_15 16976476 15 8 28125 17114 0 0 1 iss_infcrwnm
|
||||||
1552 SPELL_MASS_INFLICT_CRITICAL_DAMAGE_20 16976477 20 8 37500 17114 0 0 1 iss_infcrwnm
|
1552 SPELL_MASS_INFLICT_CRITICAL_DAMAGE_20 16976477 20 8 37500 17114 0 0 1 iss_infcrwnm
|
||||||
|
1553 SPELL_GASEOUS_FORM_5 16976479 5 3 11250 2348 1 1 1 is_BullStr
|
||||||
|
1554 SPELL_GASEOUS_FORM_10 16976480 10 3 22500 2348 1 1 1 is_BullStr
|
||||||
|
1555 SPELL_GASEOUS_FORM_15 16976481 15 3 33750 2348 1 1 1 is_BullStr
|
||||||
|
|||||||
@@ -4067,7 +4067,7 @@
|
|||||||
4063 Epic_Spell_The_Withering **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4063 Epic_Spell_The_Withering **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
4064 Epic_Spell_Tolodines_Killing_Wind **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4064 Epic_Spell_Tolodines_Killing_Wind **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
4065 Epic_Spell_Transcendent_Vitality **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4065 Epic_Spell_Transcendent_Vitality **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
4066 Epic_Spell_Twinfiend **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4066 Epic_Spell_Twinfiend 0x01000 0x00100 **** **** **** **** **** **** **** **** **** **** ****
|
||||||
4067 Epic_Spell_Unholy_Disciple **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4067 Epic_Spell_Unholy_Disciple **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
4068 Epic_Spell_Unimpinged **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4068 Epic_Spell_Unimpinged **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
4069 Epic_Spell_Unseen_Wanderer **** **** **** **** **** **** **** **** **** **** **** **** ****
|
4069 Epic_Spell_Unseen_Wanderer **** **** **** **** **** **** **** **** **** **** **** **** ****
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ void main()
|
|||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
case 2:
|
case 2:
|
||||||
case 3: sSummon = "ep_summonaberat1"; break;
|
case 3: sSummon = "ep_summonaberat1"; break; //:: Summoned Drider Chief
|
||||||
case 4:
|
case 4:
|
||||||
case 5:
|
case 5:
|
||||||
case 6: sSummon = "ep_summonaberat2"; break;
|
case 6: sSummon = "ep_summonaberat2"; break; //:: Summoned Beholder
|
||||||
case 7:
|
case 7:
|
||||||
case 8: sSummon = "ep_summonaberat3"; break;
|
case 8: sSummon = "ep_summonaberat3"; break; //:: Summoned Mind Flayer Darkener
|
||||||
case 9: sSummon = "ep_summonaberat4"; break;
|
case 9: sSummon = "ep_summonaberat4"; break; //:: Summoned Umber Hulk
|
||||||
case 10: sSummon = "ep_summonaberat5"; break;
|
case 10: sSummon = "ep_summonaberat5"; break; //:: Summoned Battle Devourer
|
||||||
}
|
}
|
||||||
|
|
||||||
effect eSummon = ExtraordinaryEffect(EffectSummonCreature(sSummon, VFX_FNF_SUMMON_EPIC_UNDEAD, 1.0f));
|
effect eSummon = ExtraordinaryEffect(EffectSummonCreature(sSummon, VFX_FNF_SUMMON_EPIC_UNDEAD, 1.0f));
|
||||||
|
|||||||
@@ -1,60 +1,317 @@
|
|||||||
//::///////////////////////////////////////////////
|
//::////////////////////////////////////////////////////////
|
||||||
|
//:: ;-. ,-. ,-. ,-.
|
||||||
|
//:: | ) | ) / ( )
|
||||||
|
//:: |-' |-< | ;-:
|
||||||
|
//:: | | \ \ ( )
|
||||||
|
//:: ' ' ' `-' `-'
|
||||||
|
//::////////////////////////////////////////////////////////
|
||||||
|
//;:
|
||||||
//:: Epic Spell: Twinfiend
|
//:: Epic Spell: Twinfiend
|
||||||
//:: Author: Boneshank (Don Armstrong)
|
//:: Author: Boneshank (Don Armstrong)
|
||||||
|
//:: Updated By: Jaysyn
|
||||||
|
//:: Updated on: 2025-11-18 18:18:09
|
||||||
|
//::
|
||||||
|
//::////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
School: Conjuration (Summoning, Evil)
|
||||||
|
Components: V,S
|
||||||
|
Range: Short
|
||||||
|
Effect: Summons two advanced pit fiends
|
||||||
|
Duration: 1 Turn / Caster level
|
||||||
|
Saving Throw: None
|
||||||
|
Spell Resistance: No
|
||||||
|
|
||||||
|
You summon two advanced pit fiends from the Nine Hells
|
||||||
|
to do your bidding. These devils recieve one bonus hit
|
||||||
|
die for every 2 caster levels of the summoner & maximum
|
||||||
|
hit points per die. The pit fiends follow your orders to
|
||||||
|
the best of their abilities, for the duration of the spell.
|
||||||
|
*/
|
||||||
|
//::////////////////////////////////////////////////////////
|
||||||
//#include "x2_inc_toollib"
|
//#include "x2_inc_toollib"
|
||||||
#include "prc_alterations"
|
#include "prc_alterations"
|
||||||
#include "inc_epicspells"
|
#include "inc_epicspells"
|
||||||
//#include "x2_inc_spellhook"
|
//#include "x2_inc_spellhook"
|
||||||
#include "nw_i0_generic"
|
#include "nw_i0_generic"
|
||||||
|
#include "prc_inc_json"
|
||||||
|
#include "inc_ecl"
|
||||||
|
|
||||||
void main()
|
void SpawnTwinFiend(object oPC, json jDevil, location lTarget, float fDuration)
|
||||||
{
|
{
|
||||||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
MultisummonPreSummon();
|
||||||
SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION);
|
|
||||||
|
|
||||||
if (!X2PreSpellCastCode())
|
object oFiend = JsonToObject(jDevil, lTarget);
|
||||||
|
|
||||||
|
int nCasterLvl = GetTotalCastingLevel(oPC);
|
||||||
|
|
||||||
|
if (!GetIsObjectValid(oFiend))
|
||||||
{
|
{
|
||||||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
SendMessageToPC(oPC, "ss_ep_twinfiend | SpawnTwinFiend() >> oFiend not passed to function.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (GetCanCastSpell(OBJECT_SELF, SPELL_EPIC_TWINF))
|
|
||||||
{
|
string sSummon = "twinfiend_demon";
|
||||||
//Declare major variables
|
|
||||||
float fDuration = RoundsToSeconds(20);
|
|
||||||
object oFiend, oFiend2;
|
|
||||||
// effect eSummon;
|
// effect eSummon;
|
||||||
effect eVis = EffectVisualEffect(460);
|
effect eVis = EffectVisualEffect(460);
|
||||||
effect eVis2 = EffectVisualEffect(VFX_IMP_UNSUMMON);
|
effect eVis2 = EffectVisualEffect(VFX_IMP_UNSUMMON);
|
||||||
|
|
||||||
|
effect eSummon = EffectSummonCreature("", 460, 0.0, 0, VFX_IMP_UNSUMMON, oFiend);
|
||||||
|
|
||||||
|
//:: Set faction to caster<65>s
|
||||||
|
ChangeFaction(oFiend, oPC);
|
||||||
|
SetLocalObject(oFiend, "SUMMONER", oPC);
|
||||||
|
|
||||||
|
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon, lTarget, fDuration);
|
||||||
|
|
||||||
|
if (!GetIsObjectValid(oFiend))
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend | SpawnTwinFiend() >> JsonToObject failed - could not create creature from edited template.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//:: Update creature weapons for Size increase
|
||||||
|
if (nCasterLvl > 14)
|
||||||
|
{
|
||||||
|
if(DEBUG) DoDebug("ss_ep_twinfiend | SpawnTwinFiend() >> Updating Creature weapons for size increase.");
|
||||||
|
|
||||||
|
object oWeapCR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oFiend);
|
||||||
|
MyDestroyObject(oWeapCR);
|
||||||
|
object oWeapCL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oFiend);
|
||||||
|
MyDestroyObject(oWeapCL);
|
||||||
|
object oWeapCB = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oFiend);
|
||||||
|
MyDestroyObject(oWeapCB);
|
||||||
|
|
||||||
|
oWeapCR = CreateItemOnObject("nw_it_crewpsp010", oFiend);
|
||||||
|
ForceEquip(oFiend, oWeapCR, INVENTORY_SLOT_CWEAPON_R);
|
||||||
|
|
||||||
|
oWeapCL = CreateItemOnObject("bite_pitfiend002", oFiend);
|
||||||
|
ForceEquip(oFiend, oWeapCL, INVENTORY_SLOT_CWEAPON_L);
|
||||||
|
|
||||||
|
oWeapCB = CreateItemOnObject("prc_2d6_slamgrab", oFiend);
|
||||||
|
ForceEquip(oFiend, oWeapCB, INVENTORY_SLOT_CWEAPON_B);
|
||||||
|
|
||||||
|
SetObjectVisualTransform(oFiend, OBJECT_VISUAL_TRANSFORM_SCALE, 1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AugmentSummonedCreature(sSummon);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
object oPC = OBJECT_SELF;
|
||||||
|
|
||||||
|
DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||||
|
SetLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_CONJURATION);
|
||||||
|
|
||||||
|
if (!X2PreSpellCastCode())
|
||||||
|
{
|
||||||
|
DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target location
|
||||||
|
location lTarget = PRCGetSpellTargetLocation();
|
||||||
|
|
||||||
|
int nCasterLvl = GetTotalCastingLevel(oPC);
|
||||||
|
|
||||||
|
//:: Load template
|
||||||
|
json jDevil = TemplateToJson("twinfiend_demon", RESTYPE_UTC);
|
||||||
|
if (jDevil == JSON_NULL)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> TemplateToJson failed <20> bad resref or resource missing.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//:: Get Original HD
|
||||||
|
int nOriginalHD = json_GetCreatureHD(jDevil);
|
||||||
|
if (nOriginalHD <= 0)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_GetCreatureHD failed <20> template missing HD data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//:: Stat boost calc
|
||||||
|
int nStatBoost = GetStatBoostsFromHD(nOriginalHD, nCasterLvl/2);
|
||||||
|
|
||||||
|
//:: Add one hit dice per two caster levels
|
||||||
|
jDevil = json_AddHitDice(jDevil, nCasterLvl/2);
|
||||||
|
if (jDevil == JSON_NULL)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_AddHitDice failed - JSON became invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//:: Recalculate & maximize HP
|
||||||
|
int nCurrentHD = json_GetCreatureHD(jDevil);
|
||||||
|
if (nCurrentHD <= 0)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_GetCreatureHD failed <20> template missing HD data.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DEBUG) DoDebug("ss_ep_twinfiend >> nCurrentHD is: "+IntToString(nCurrentHD)+ " entering json_RecalcMaxHP.");
|
||||||
|
jDevil = json_RecalcMaxHP(jDevil, 8);
|
||||||
|
if (jDevil == JSON_NULL)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_RecalcMaxHP failed - JSON became invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//:: Update feats
|
||||||
|
jDevil = json_AddFeatsFromCreatureVars(jDevil, nOriginalHD);
|
||||||
|
if (jDevil == JSON_NULL)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_AddFeatsFromCreatureVars failed <20> JSON became invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//:: Update stats
|
||||||
|
jDevil = json_ApplyAbilityBoostFromHD(jDevil, nOriginalHD);
|
||||||
|
if (jDevil == JSON_NULL)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_ApplyAbilityBoostFromHD failed <20> JSON became invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size increase
|
||||||
|
if (nCasterLvl > 14)
|
||||||
|
{
|
||||||
|
jDevil = json_AdjustCreatureSize(jDevil, 1);
|
||||||
|
if (jDevil == JSON_NULL)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "ss_ep_twinfiend >> json_AdjustCreatureSize failed - JSON became invalid.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetCanCastSpell(oPC, SPELL_EPIC_TWINF))
|
||||||
|
{
|
||||||
|
//:: Declare major variables
|
||||||
|
float fDuration = TurnsToSeconds(nCasterLvl);
|
||||||
|
object oFiend;
|
||||||
|
object oFiend2;
|
||||||
|
|
||||||
|
// effect eSummon;
|
||||||
|
effect eVis = EffectVisualEffect(460);
|
||||||
|
effect eVis2 = EffectVisualEffect(VFX_IMP_UNSUMMON);
|
||||||
|
|
||||||
|
string sSummon = "twinfiend_demon";
|
||||||
|
|
||||||
|
// Despawn existing Twinfiends
|
||||||
|
object oArea = GetArea(oPC);
|
||||||
|
object oObj = GetFirstObjectInArea(oArea);
|
||||||
|
|
||||||
|
while (GetIsObjectValid(oObj))
|
||||||
|
{
|
||||||
|
if (GetTag(oObj) == "TWINFIEND_DEMON")
|
||||||
|
{
|
||||||
|
if (GetLocalObject(oObj, "SUMMONER") == oPC)
|
||||||
|
{
|
||||||
|
DestroyObject(oObj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oObj = GetNextObjectInArea(oArea);
|
||||||
|
}
|
||||||
|
|
||||||
if(GetPRCSwitch(PRC_MULTISUMMON))
|
if(GetPRCSwitch(PRC_MULTISUMMON))
|
||||||
{
|
{
|
||||||
string sSummon = "twinfiend_demon";
|
SpawnTwinFiend(oPC, jDevil, lTarget, fDuration);
|
||||||
effect eSummon = EffectSummonCreature(sSummon, 460);
|
SpawnTwinFiend(oPC, jDevil, lTarget, fDuration);
|
||||||
MultisummonPreSummon();
|
|
||||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon,
|
|
||||||
PRCGetSpellTargetLocation(), fDuration);
|
|
||||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eSummon,
|
|
||||||
PRCGetSpellTargetLocation(), fDuration);
|
|
||||||
DelayCommand(0.5, AugmentSummonedCreature(sSummon));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DelayCommand(1.0, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, PRCGetSpellTargetLocation()));
|
DelayCommand(1.0, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lTarget));
|
||||||
oFiend = CreateObject(OBJECT_TYPE_CREATURE, "twinfiend_demon", PRCGetSpellTargetLocation());
|
//oFiend = CreateObject(OBJECT_TYPE_CREATURE, "twinfiend_demon", PRCGetSpellTargetLocation());
|
||||||
oFiend2 = CreateObject(OBJECT_TYPE_CREATURE, "twinfiend_demon", PRCGetSpellTargetLocation());
|
oFiend = JsonToObject(jDevil, lTarget);
|
||||||
|
DelayCommand(0.0, AugmentSummonedCreature(sSummon));
|
||||||
|
SetCurrentHitPoints(oFiend, GetMaxPossibleHP(oFiend));
|
||||||
|
|
||||||
|
//:: Set faction to caster<65>s
|
||||||
|
ChangeFaction(oFiend, oPC);
|
||||||
|
SetLocalObject(oFiend, "SUMMONER", oPC);
|
||||||
|
|
||||||
|
SetLocalNPC(oPC, oFiend, ASSOCIATE_TYPE_SUMMONED);
|
||||||
|
SetAssociateState(NW_ASC_HAVE_MASTER, TRUE, oFiend);
|
||||||
|
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
|
||||||
|
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
|
||||||
|
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
|
||||||
|
|
||||||
|
//oFiend2 = CreateObject(OBJECT_TYPE_CREATURE, "twinfiend_demon", PRCGetSpellTargetLocation());
|
||||||
|
oFiend2 = JsonToObject(jDevil, lTarget);
|
||||||
|
DelayCommand(0.0, AugmentSummonedCreature(sSummon));
|
||||||
|
SetCurrentHitPoints(oFiend2, GetMaxPossibleHP(oFiend2));
|
||||||
|
|
||||||
|
//:: Set faction to caster<65>s
|
||||||
|
ChangeFaction(oFiend2, oPC);
|
||||||
|
SetLocalObject(oFiend2, "SUMMONER", oPC);
|
||||||
|
|
||||||
|
SetLocalNPC(oPC, oFiend2, ASSOCIATE_TYPE_SUMMONED);
|
||||||
|
SetAssociateState(NW_ASC_HAVE_MASTER, TRUE, oFiend2);
|
||||||
|
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
|
||||||
|
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
|
||||||
|
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
|
||||||
|
|
||||||
SetMaxHenchmen(GetMaxHenchmen() + 2);
|
SetMaxHenchmen(GetMaxHenchmen() + 2);
|
||||||
AddHenchman(OBJECT_SELF, oFiend);
|
AddHenchman(oPC, oFiend);
|
||||||
AddHenchman(OBJECT_SELF, oFiend2);
|
AddHenchman(oPC, oFiend2);
|
||||||
SetMaxHenchmen(GetMaxHenchmen() - 2);
|
SetMaxHenchmen(GetMaxHenchmen() - 2);
|
||||||
|
|
||||||
|
//:: Update creature weapons for Size increase
|
||||||
|
if (nCasterLvl > 14)
|
||||||
|
{
|
||||||
|
if(DEBUG) DoDebug("ss_ep_twinfiend >> Updating Creature weapons for size increase.");
|
||||||
|
|
||||||
|
object oWeapCR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oFiend);
|
||||||
|
MyDestroyObject(oWeapCR);
|
||||||
|
object oWeapCL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oFiend);
|
||||||
|
MyDestroyObject(oWeapCL);
|
||||||
|
object oWeapCB = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oFiend);
|
||||||
|
MyDestroyObject(oWeapCB);
|
||||||
|
|
||||||
|
oWeapCR = CreateItemOnObject("nw_it_crewpsp010", oFiend);
|
||||||
|
ForceEquip(oFiend, oWeapCR, INVENTORY_SLOT_CWEAPON_R);
|
||||||
|
|
||||||
|
oWeapCL = CreateItemOnObject("bite_pitfiend002", oFiend);
|
||||||
|
ForceEquip(oFiend, oWeapCL, INVENTORY_SLOT_CWEAPON_L);
|
||||||
|
|
||||||
|
oWeapCB = CreateItemOnObject("prc_2d6_slamgrab", oFiend);
|
||||||
|
ForceEquip(oFiend, oWeapCB, INVENTORY_SLOT_CWEAPON_B);
|
||||||
|
|
||||||
|
oWeapCR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oFiend2);
|
||||||
|
MyDestroyObject(oWeapCR);
|
||||||
|
oWeapCL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oFiend2);
|
||||||
|
MyDestroyObject(oWeapCL);
|
||||||
|
oWeapCB = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oFiend2);
|
||||||
|
MyDestroyObject(oWeapCB);
|
||||||
|
|
||||||
|
oWeapCR = CreateItemOnObject("nw_it_crewpsp010", oFiend2);
|
||||||
|
ForceEquip(oFiend2, oWeapCR, INVENTORY_SLOT_CWEAPON_R);
|
||||||
|
|
||||||
|
oWeapCL = CreateItemOnObject("bite_pitfiend002", oFiend2);
|
||||||
|
ForceEquip(oFiend2, oWeapCL, INVENTORY_SLOT_CWEAPON_L);
|
||||||
|
|
||||||
|
oWeapCB = CreateItemOnObject("prc_2d6_slamgrab", oFiend2);
|
||||||
|
ForceEquip(oFiend2, oWeapCB, INVENTORY_SLOT_CWEAPON_B);
|
||||||
|
|
||||||
|
SetObjectVisualTransform(oFiend, OBJECT_VISUAL_TRANSFORM_SCALE, 1.1);
|
||||||
|
SetObjectVisualTransform(oFiend2, OBJECT_VISUAL_TRANSFORM_SCALE, 1.1);
|
||||||
|
|
||||||
|
}
|
||||||
|
else DoDebug("ss_ep_twinfiend >> No size change detected.");
|
||||||
|
|
||||||
AssignCommand(oFiend, DetermineCombatRound());
|
AssignCommand(oFiend, DetermineCombatRound());
|
||||||
AssignCommand(oFiend2, DetermineCombatRound());
|
AssignCommand(oFiend2, DetermineCombatRound());
|
||||||
|
|
||||||
DestroyObject(oFiend, fDuration);
|
DestroyObject(oFiend, fDuration);
|
||||||
DelayCommand(fDuration, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis2, GetLocation(oFiend)));
|
DelayCommand(fDuration, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis2, GetLocation(oFiend)));
|
||||||
DestroyObject(oFiend2, fDuration);
|
DestroyObject(oFiend2, fDuration);
|
||||||
DelayCommand(fDuration, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis2, GetLocation(oFiend2)));
|
DelayCommand(fDuration, ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis2, GetLocation(oFiend2)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
|
||||||
|
DeleteLocalInt(oPC, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
|
|||||||
SetLocalObject(oMaster, IntToString(nAssociateType)+"oHench"+IntToString(nCount), oSummon);
|
SetLocalObject(oMaster, IntToString(nAssociateType)+"oHench"+IntToString(nCount), oSummon);
|
||||||
SetLocalInt(oSummon, "iAssocNth", nCount);
|
SetLocalInt(oSummon, "iAssocNth", nCount);
|
||||||
|
|
||||||
SetAssociateState(NW_ASC_HAVE_MASTER,TRUE,oSummon);
|
SetAssociateState(NW_ASC_HAVE_MASTER, TRUE, oSummon);
|
||||||
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
|
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
|
||||||
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
|
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
|
||||||
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
|
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
//:://////////////////////////////////////////////
|
//:://////////////////////////////////////////////
|
||||||
#include "nw_inc_gff"
|
#include "nw_inc_gff"
|
||||||
#include "inc_debug"
|
#include "inc_debug"
|
||||||
|
#include "prc_inc_racial"
|
||||||
|
#include "prc_inc_nwscript"
|
||||||
|
|
||||||
|
|
||||||
//::---------------------------------------------|
|
//::---------------------------------------------|
|
||||||
@@ -30,6 +32,8 @@ int GetMaxPossibleHP(object oCreature)
|
|||||||
int nMaxHP = 0; // Stores the total maximum hitpoints
|
int nMaxHP = 0; // Stores the total maximum hitpoints
|
||||||
int i = 1; // Initialize position for class index
|
int i = 1; // Initialize position for class index
|
||||||
int nConb = GetAbilityModifier(ABILITY_CONSTITUTION, oCreature);
|
int nConb = GetAbilityModifier(ABILITY_CONSTITUTION, oCreature);
|
||||||
|
int nRacial = MyPRCGetRacialType(oCreature);
|
||||||
|
int nSize = PRCGetCreatureSize(oCreature);
|
||||||
|
|
||||||
// Loop through each class position the creature may have, checking each class in turn
|
// Loop through each class position the creature may have, checking each class in turn
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
@@ -54,8 +58,25 @@ int GetMaxPossibleHP(object oCreature)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(nRacial == RACIAL_TYPE_CONSTRUCT || nRacial == RACIAL_TYPE_UNDEAD)
|
||||||
|
{
|
||||||
|
nConb = 0;
|
||||||
|
}
|
||||||
|
|
||||||
nMaxHP += nConb * GetHitDice(oCreature);
|
nMaxHP += nConb * GetHitDice(oCreature);
|
||||||
|
|
||||||
|
if(nRacial == RACIAL_TYPE_CONSTRUCT)
|
||||||
|
{
|
||||||
|
if(nSize == CREATURE_SIZE_FINE) nMaxHP += 0;
|
||||||
|
if(nSize == CREATURE_SIZE_DIMINUTIVE) nMaxHP += 0;
|
||||||
|
if(nSize == CREATURE_SIZE_TINY) nMaxHP += 0;
|
||||||
|
if(nSize == CREATURE_SIZE_SMALL) nMaxHP += 10;
|
||||||
|
if(nSize == CREATURE_SIZE_MEDIUM) nMaxHP += 20;
|
||||||
|
if(nSize == CREATURE_SIZE_LARGE) nMaxHP += 30;
|
||||||
|
if(nSize == CREATURE_SIZE_HUGE) nMaxHP += 40;
|
||||||
|
if(nSize == CREATURE_SIZE_GARGANTUAN) nMaxHP += 60;
|
||||||
|
}
|
||||||
|
|
||||||
return nMaxHP;
|
return nMaxHP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,13 +223,44 @@ int json_GetCreatureHD(json jCreature)
|
|||||||
json json_RecalcMaxHP(json jCreature, int iHitDieValue)
|
json json_RecalcMaxHP(json jCreature, int iHitDieValue)
|
||||||
{
|
{
|
||||||
int iHD = json_GetCreatureHD(jCreature);
|
int iHD = json_GetCreatureHD(jCreature);
|
||||||
int iCON = json_GetCONValue(jCreature);
|
|
||||||
int iMod = GetAbilityModFromValue(iCON);
|
|
||||||
|
|
||||||
int nConBonusHP = iMod * iHD;
|
//:: Retrieve the RacialType field
|
||||||
int iNewMaxHP = (iHitDieValue * iHD); /* nConBonusHP */
|
json jRacialTypeField = JsonObjectGet(jCreature, "Race");
|
||||||
|
int nRacialType = JsonGetInt(jRacialTypeField);
|
||||||
|
|
||||||
//jCreature = GffReplaceShort(jCreature, "MaxHitPoints", iNewMaxHP);
|
//:: Retrieve the CreatureSize from the creature appearance field
|
||||||
|
json jAppearanceField = JsonObjectGet(jCreature, "Appearance_Type");
|
||||||
|
int nAppearance = JsonGetInt(jAppearanceField);
|
||||||
|
|
||||||
|
int nSize = StringToInt(Get2DAString("appearance", "SizeCategory", nAppearance));
|
||||||
|
|
||||||
|
//CEP adds other sizes, take them into account too
|
||||||
|
if(nSize == 20)
|
||||||
|
nSize = CREATURE_SIZE_DIMINUTIVE;
|
||||||
|
else if(nSize == 21)
|
||||||
|
nSize = CREATURE_SIZE_FINE;
|
||||||
|
else if(nSize == 22)
|
||||||
|
nSize = CREATURE_SIZE_GARGANTUAN;
|
||||||
|
else if(nSize == 23)
|
||||||
|
nSize = CREATURE_SIZE_COLOSSAL;
|
||||||
|
|
||||||
|
int iNewMaxHP = (iHitDieValue * iHD);
|
||||||
|
|
||||||
|
if(nRacialType == RACIAL_TYPE_CONSTRUCT)
|
||||||
|
{
|
||||||
|
if(nSize == CREATURE_SIZE_FINE) iNewMaxHP += 0;
|
||||||
|
if(nSize == CREATURE_SIZE_DIMINUTIVE) iNewMaxHP += 0;
|
||||||
|
if(nSize == CREATURE_SIZE_TINY) iNewMaxHP += 0;
|
||||||
|
if(nSize == CREATURE_SIZE_SMALL) iNewMaxHP += 10;
|
||||||
|
if(nSize == CREATURE_SIZE_MEDIUM) iNewMaxHP += 20;
|
||||||
|
if(nSize == CREATURE_SIZE_LARGE) iNewMaxHP += 30;
|
||||||
|
if(nSize == CREATURE_SIZE_HUGE) iNewMaxHP += 40;
|
||||||
|
if(nSize == CREATURE_SIZE_GARGANTUAN) iNewMaxHP += 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(DEBUG) DoDebug("prc_inc_json >> json_RecalcMaxHP | New MaxHP is: "+IntToString(iNewMaxHP)+ ".");
|
||||||
|
|
||||||
|
jCreature = GffReplaceShort(jCreature, "MaxHitPoints", iNewMaxHP);
|
||||||
jCreature = GffReplaceShort(jCreature, "CurrentHitPoints", iNewMaxHP);
|
jCreature = GffReplaceShort(jCreature, "CurrentHitPoints", iNewMaxHP);
|
||||||
jCreature = GffReplaceShort(jCreature, "HitPoints", iNewMaxHP);
|
jCreature = GffReplaceShort(jCreature, "HitPoints", iNewMaxHP);
|
||||||
|
|
||||||
@@ -425,7 +477,7 @@ json json_AddFeatsFromCreatureVars(json jCreature, int nOriginalHD)
|
|||||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Original feat count: " + IntToString(nOriginalFeatCount));
|
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Original feat count: " + IntToString(nOriginalFeatCount));
|
||||||
|
|
||||||
int nAdded = 0;
|
int nAdded = 0;
|
||||||
int i = 1;
|
int i = 0;
|
||||||
int nMaxIterations = 100; // Safety valve
|
int nMaxIterations = 100; // Safety valve
|
||||||
int nIterations = 0;
|
int nIterations = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -277,6 +277,32 @@ void ClearNaturalWeapons(object oPC)
|
|||||||
array_delete(oPC, ARRAY_NAT_PRI_WEAP_ATTACKS);
|
array_delete(oPC, ARRAY_NAT_PRI_WEAP_ATTACKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a natural primary weapon to a creature (PC/NPC).
|
||||||
|
*
|
||||||
|
* This function manages a creature's natural primary weapons by storing their
|
||||||
|
* resource references and attack counts in persistent arrays. If the weapon
|
||||||
|
* being added is the first natural weapon, it may automatically become the
|
||||||
|
* creature's active primary natural weapon, unless the creature is a Monk or
|
||||||
|
* Brawler. Optionally, the weapon can be forced to become the active primary
|
||||||
|
* weapon regardless of class.
|
||||||
|
*
|
||||||
|
* @param oPC The creature object to which the natural weapon will be added.
|
||||||
|
* @param sResRef The resource reference string of the natural weapon.
|
||||||
|
* @param nCount (Optional) The number of attacks this natural weapon provides.
|
||||||
|
* Default is 1.
|
||||||
|
* @param nForceUse (Optional) If TRUE, forces this weapon to become the active
|
||||||
|
* primary natural weapon regardless of the creature's class.
|
||||||
|
* Default is FALSE.
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* - Creates persistent arrays for weapon references and attack counts if they
|
||||||
|
* do not already exist.
|
||||||
|
* - Checks if the weapon is already present to avoid duplicates.
|
||||||
|
* - Adds the weapon and attack count to the arrays.
|
||||||
|
* - Sets the primary natural weapon index to this weapon if it is the first
|
||||||
|
* natural weapon added, unless the creature is a Monk or Brawler.
|
||||||
|
*/
|
||||||
void AddNaturalPrimaryWeapon(object oPC, string sResRef, int nCount = 1, int nForceUse = FALSE)
|
void AddNaturalPrimaryWeapon(object oPC, string sResRef, int nCount = 1, int nForceUse = FALSE)
|
||||||
{
|
{
|
||||||
int nFirstNaturalWeapon = FALSE;
|
int nFirstNaturalWeapon = FALSE;
|
||||||
|
|||||||
@@ -363,7 +363,10 @@ int PRCIsFlying(object oCreature)
|
|||||||
bFlying = TRUE;
|
bFlying = TRUE;
|
||||||
}
|
}
|
||||||
if(!bFlying
|
if(!bFlying
|
||||||
&& ((nWings > 0 && nWings < 79) || nWings == 90))//CEP and Project Q wing models
|
&& ((nWings > 0 && nWings < 79)
|
||||||
|
|| (nWings > 1959 && nWings < 1962)
|
||||||
|
|| (nWings > 1962 && nWings < 1966)
|
||||||
|
|| nWings == 90))//CEP and Project Q wing models
|
||||||
bFlying = TRUE;
|
bFlying = TRUE;
|
||||||
|
|
||||||
if (GetHasSpellEffect(MOVE_SH_BALANCE_SKY, oCreature))
|
if (GetHasSpellEffect(MOVE_SH_BALANCE_SKY, oCreature))
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
|
|
||||||
/* This variable MUST be updated with every new version of the PRC!!! */
|
/* This variable MUST be updated with every new version of the PRC!!! */
|
||||||
|
|
||||||
const string PRC_VERSION = "PRC8 4.69";
|
const string PRC_VERSION = "PRC8 4.70";
|
||||||
|
|
||||||
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */
|
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "psi_inc_psifunc"
|
#include "psi_inc_psifunc"
|
||||||
#include "inc_lookups"
|
#include "inc_lookups"
|
||||||
#include "nw_inc_nui"
|
#include "nw_inc_nui"
|
||||||
|
#include "tob_inc_tobfunc"
|
||||||
|
|
||||||
//
|
//
|
||||||
// GetCurrentSpellLevel
|
// GetCurrentSpellLevel
|
||||||
@@ -153,8 +154,53 @@ json GreyOutButton(json jButton, float w, float h);
|
|||||||
//
|
//
|
||||||
json CreateGreyOutRectangle(float w, float h);
|
json CreateGreyOutRectangle(float w, float h);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetTrueClassType
|
||||||
|
// Gets the true class Id for a provided class Id, mostly for RHD and for
|
||||||
|
// ToB prestige classes
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int classId
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the true classId based off nClass
|
||||||
|
//
|
||||||
|
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF);
|
||||||
|
|
||||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
|
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
|
||||||
|
|
||||||
|
void CallSpellUnlevelScript(object oPC, int nClass, int nLevel);
|
||||||
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
|
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
|
||||||
|
void RemoveIPFeat(object oPC, int ipFeatID);
|
||||||
|
|
||||||
|
void CallSpellUnlevelScript(object oPC, int nClass, int nLevel)
|
||||||
|
{
|
||||||
|
SetScriptParam("UnLevel_ClassChoice", IntToString(nClass));
|
||||||
|
SetScriptParam("UnLevel_LevelChoice", IntToString(nLevel));
|
||||||
|
ExecuteScript("prc_unlvl_script", oPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveIPFeat(object oPC, int ipFeatID)
|
||||||
|
{
|
||||||
|
object oSkin = GetPCSkin(oPC);
|
||||||
|
itemproperty ipTest = GetFirstItemProperty(oSkin);
|
||||||
|
while(GetIsItemPropertyValid(ipTest))
|
||||||
|
{
|
||||||
|
// Check if the itemproperty is a bonus feat that has been marked for removal
|
||||||
|
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_BONUS_FEAT)
|
||||||
|
{
|
||||||
|
if (GetItemPropertySubType(ipTest) == ipFeatID)
|
||||||
|
{
|
||||||
|
if(DEBUG) DoDebug("_ManeuverRecurseRemoveArray(): Removing bonus feat itemproperty:\n" + DebugIProp2Str(ipTest));
|
||||||
|
// If so, remove it
|
||||||
|
RemoveItemProperty(oSkin, ipTest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ipTest = GetNextItemProperty(oSkin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||||
{
|
{
|
||||||
@@ -528,3 +574,39 @@ void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF)
|
|||||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF)
|
||||||
|
{
|
||||||
|
if (nClass == CLASS_TYPE_JADE_PHOENIX_MAGE
|
||||||
|
|| nClass == CLASS_TYPE_MASTER_OF_NINE
|
||||||
|
|| nClass == CLASS_TYPE_DEEPSTONE_SENTINEL
|
||||||
|
|| nClass == CLASS_TYPE_BLOODCLAW_MASTER
|
||||||
|
|| nClass == CLASS_TYPE_RUBY_VINDICATOR
|
||||||
|
|| nClass == CLASS_TYPE_ETERNAL_BLADE
|
||||||
|
|| nClass == CLASS_TYPE_SHADOW_SUN_NINJA)
|
||||||
|
{
|
||||||
|
int trueClass = GetPrimaryBladeMagicClass(oPC);
|
||||||
|
return trueClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((nClass == CLASS_TYPE_SHAPECHANGER
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
||||||
|
|| (nClass == CLASS_TYPE_OUTSIDER
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
||||||
|
|| (nClass == CLASS_TYPE_ABERRATION
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT))
|
||||||
|
return CLASS_TYPE_SORCERER;
|
||||||
|
if (nClass == CLASS_TYPE_FEY
|
||||||
|
&& GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
|
||||||
|
return CLASS_TYPE_BARD;
|
||||||
|
|
||||||
|
return nClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,21 +98,9 @@ void OpenNUILevelUpWindow(int nClass, object oPC=OBJECT_SELF);
|
|||||||
//
|
//
|
||||||
// CloseNUILevelUpWindow
|
// CloseNUILevelUpWindow
|
||||||
// Closes the NUI Level Up Window if its open
|
// Closes the NUI Level Up Window if its open
|
||||||
|
// setting reset to 1 will make it clear the entire cache as if the NUI was never opened
|
||||||
//
|
//
|
||||||
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF);
|
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF, int reset=0);
|
||||||
|
|
||||||
//
|
|
||||||
// GetTrueClassType
|
|
||||||
// Gets the true class Id for a provided class Id, mostly for RHD and for
|
|
||||||
// ToB prestige classes
|
|
||||||
//
|
|
||||||
// Arguments:
|
|
||||||
// nClass:int classId
|
|
||||||
//
|
|
||||||
// Returns:
|
|
||||||
// int the true classId based off nClass
|
|
||||||
//
|
|
||||||
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// GetRemainingSpellChoices
|
// GetRemainingSpellChoices
|
||||||
@@ -432,7 +420,7 @@ json GetChosenReplaceListObject(object oPC=OBJECT_SELF);
|
|||||||
// Returns:
|
// Returns:
|
||||||
// int:Boolean TRUE if the spell is a expanded knowledge spell, FALSE otherwise
|
// int:Boolean TRUE if the spell is a expanded knowledge spell, FALSE otherwise
|
||||||
//
|
//
|
||||||
int IsExpKnowledgePower(int nClass, int spellbookId);
|
int IsExpKnowledgePower(int nClass, int spellbookId, object oPC=OBJECT_SELF);
|
||||||
|
|
||||||
//
|
//
|
||||||
// GetExpKnowledgePowerListRequired
|
// GetExpKnowledgePowerListRequired
|
||||||
@@ -861,7 +849,7 @@ void AddSpellToChosenList(int nClass, int spellbookId, int spellCircle, object o
|
|||||||
// if the power is a expanded knowledge than we immediatly add it to the
|
// if the power is a expanded knowledge than we immediatly add it to the
|
||||||
// extra list, otherwise check to make sure we have made all choices in our
|
// extra list, otherwise check to make sure we have made all choices in our
|
||||||
// base list first before adding it to the extra list.
|
// base list first before adding it to the extra list.
|
||||||
if (IsExpKnowledgePower(nClass, spellbookId)
|
if (IsExpKnowledgePower(nClass, spellbookId, oPC)
|
||||||
|| GetRemainingPowerChoices(nClass, spellCircle, oPC, FALSE) == 0)
|
|| GetRemainingPowerChoices(nClass, spellCircle, oPC, FALSE) == 0)
|
||||||
{
|
{
|
||||||
string sFile = GetClassSpellbookFile(nClass);
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
@@ -975,8 +963,7 @@ void RemoveSpellFromChosenList(int nClass, int spellbookId, int spellCircle, obj
|
|||||||
// for psionics we need to check if the removed spell was a expanded knowledge choice
|
// for psionics we need to check if the removed spell was a expanded knowledge choice
|
||||||
// or not. The id of the list is -1 or -2.
|
// or not. The id of the list is -1 or -2.
|
||||||
int i;
|
int i;
|
||||||
//for (i == -1; i >= -2; i--)
|
for (i == -1; i >= -2; i--)
|
||||||
for (i = -1; i >= -2; i--)
|
|
||||||
{
|
{
|
||||||
json expList = (i == -1) ? GetExpandedChoicesList(nClass, oPC) :
|
json expList = (i == -1) ? GetExpandedChoicesList(nClass, oPC) :
|
||||||
GetEpicExpandedChoicesList(nClass, oPC);
|
GetEpicExpandedChoicesList(nClass, oPC);
|
||||||
@@ -1062,53 +1049,20 @@ void OpenNUILevelUpWindow(int nClass, object oPC=OBJECT_SELF)
|
|||||||
// figure out what the true base class is (mostly true for RHD)
|
// figure out what the true base class is (mostly true for RHD)
|
||||||
int chosenClass = GetTrueClassType(nClass, oPC);
|
int chosenClass = GetTrueClassType(nClass, oPC);
|
||||||
SetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR, chosenClass);
|
SetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR, chosenClass);
|
||||||
|
|
||||||
ExecuteScript("prc_nui_lv_view", oPC);
|
ExecuteScript("prc_nui_lv_view", oPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF)
|
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF, int reset=0)
|
||||||
{
|
|
||||||
if (nClass == CLASS_TYPE_JADE_PHOENIX_MAGE
|
|
||||||
|| nClass == CLASS_TYPE_MASTER_OF_NINE
|
|
||||||
|| nClass == CLASS_TYPE_DEEPSTONE_SENTINEL
|
|
||||||
|| nClass == CLASS_TYPE_BLOODCLAW_MASTER
|
|
||||||
|| nClass == CLASS_TYPE_RUBY_VINDICATOR
|
|
||||||
|| nClass == CLASS_TYPE_ETERNAL_BLADE
|
|
||||||
|| nClass == CLASS_TYPE_SHADOW_SUN_NINJA)
|
|
||||||
{
|
|
||||||
int trueClass = GetPrimaryBladeMagicClass(oPC);
|
|
||||||
return trueClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nClass == CLASS_TYPE_SHAPECHANGER
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|
|
||||||
|| (nClass == CLASS_TYPE_OUTSIDER
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
|
||||||
|| (nClass == CLASS_TYPE_ABERRATION
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|
|
||||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|
|
||||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|
|
||||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|
|
||||||
|| (nClass == CLASS_TYPE_MONSTROUS
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT))
|
|
||||||
return CLASS_TYPE_SORCERER;
|
|
||||||
if (nClass == CLASS_TYPE_FEY
|
|
||||||
&& GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
|
|
||||||
return CLASS_TYPE_BARD;
|
|
||||||
|
|
||||||
return nClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF)
|
|
||||||
{
|
{
|
||||||
int currentClass = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
int currentClass = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
|
||||||
// if we are refreshing the NUI but not finished we need to clear some caching done
|
// if we are refreshing the NUI but not finished we need to clear some caching done
|
||||||
// to save computation time as they will need to be reprocessed.
|
// to save computation time as they will need to be reprocessed.
|
||||||
DeleteLocalJson(oPC, NUI_LEVEL_UP_DISCIPLINE_INFO_VAR + IntToString(currentClass));
|
DeleteLocalJson(oPC, NUI_LEVEL_UP_DISCIPLINE_INFO_VAR + IntToString(currentClass));
|
||||||
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, -20);
|
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, -20);
|
||||||
|
if (reset)
|
||||||
|
{
|
||||||
|
ClearLevelUpNUICaches(currentClass, oPC);
|
||||||
|
}
|
||||||
int nPreviousToken = NuiFindWindow(oPC, NUI_LEVEL_UP_WINDOW_ID);
|
int nPreviousToken = NuiFindWindow(oPC, NUI_LEVEL_UP_WINDOW_ID);
|
||||||
if (nPreviousToken != 0)
|
if (nPreviousToken != 0)
|
||||||
{
|
{
|
||||||
@@ -1127,7 +1081,7 @@ int ShouldSpellButtonBeEnabled(int nClass, int circleLevel, int spellbookId, obj
|
|||||||
|
|
||||||
// if its an expanded knowledge choice and we have already made all our
|
// if its an expanded knowledge choice and we have already made all our
|
||||||
// exp knowledge choices then it needs to be disabled.
|
// exp knowledge choices then it needs to be disabled.
|
||||||
if (IsExpKnowledgePower(nClass, spellbookId))
|
if (IsExpKnowledgePower(nClass, spellbookId, oPC))
|
||||||
{
|
{
|
||||||
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
|
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
|
||||||
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
||||||
@@ -1540,7 +1494,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
|
|||||||
// default logic for spont casters
|
// default logic for spont casters
|
||||||
totalSpellsKnown = GetSpellKnownMaxCount(casterLevel, circleLevel, nClass, oPC);
|
totalSpellsKnown = GetSpellKnownMaxCount(casterLevel, circleLevel, nClass, oPC);
|
||||||
// Favoured Soul has more 0 choices than there are spells for some reason
|
// Favoured Soul has more 0 choices than there are spells for some reason
|
||||||
if (nClass == CLASS_TYPE_FAVOURED_SOUL && circleLevel == 0 && totalSpellsKnown > 7)
|
if (nClass == CLASS_TYPE_FAVOURED_SOUL && circleLevel == 0 && totalSpellsKnown > 6)
|
||||||
totalSpellsKnown = 7;
|
totalSpellsKnown = 7;
|
||||||
|
|
||||||
// logic for spont casters
|
// logic for spont casters
|
||||||
@@ -1555,6 +1509,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
|
|||||||
|
|
||||||
if (chosenCircle == circleLevel)
|
if (chosenCircle == circleLevel)
|
||||||
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, remainingChoices);
|
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, remainingChoices);
|
||||||
|
if (DEBUG) DoDebug("Remaining spell choices is " + IntToString(remainingChoices));
|
||||||
return remainingChoices;
|
return remainingChoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1567,22 +1522,9 @@ void FinishLevelUp(int nClass, object oPC=OBJECT_SELF)
|
|||||||
int nLevel = GetLevelByClass(nClass, oPC);
|
int nLevel = GetLevelByClass(nClass, oPC);
|
||||||
SetPersistantLocalInt(oPC, "LastSpellGainLevel", nLevel);
|
SetPersistantLocalInt(oPC, "LastSpellGainLevel", nLevel);
|
||||||
}
|
}
|
||||||
CloseNUILevelUpWindow(oPC); // Close while selected-class var is still set
|
|
||||||
ClearLevelUpNUICaches(nClass, oPC);
|
ClearLevelUpNUICaches(nClass, oPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* void FinishLevelUp(int nClass, object oPC=OBJECT_SELF)
|
|
||||||
{
|
|
||||||
RemoveSpells(nClass, oPC);
|
|
||||||
LearnSpells(nClass, oPC);
|
|
||||||
if (nClass == CLASS_TYPE_ARCHIVIST)
|
|
||||||
{
|
|
||||||
int nLevel = GetLevelByClass(nClass, oPC);
|
|
||||||
SetPersistantLocalInt(oPC, "LastSpellGainLevel", nLevel);
|
|
||||||
}
|
|
||||||
ClearLevelUpNUICaches(nClass, oPC);
|
|
||||||
} */
|
|
||||||
|
|
||||||
void ClearLevelUpNUICaches(int nClass, object oPC=OBJECT_SELF)
|
void ClearLevelUpNUICaches(int nClass, object oPC=OBJECT_SELF)
|
||||||
{
|
{
|
||||||
// clear the chosen spells you made
|
// clear the chosen spells you made
|
||||||
@@ -1678,11 +1620,13 @@ void RemoveSpells(int nClass, object oPC=OBJECT_SELF)
|
|||||||
{
|
{
|
||||||
string sFile = GetClassSpellbookFile(nClass);
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
string sSpellBook = GetSpellsKnown_Array(nClass);
|
string sSpellBook = GetSpellsKnown_Array(nClass);
|
||||||
|
string spellsAtLevelList = "SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(GetHitDice(oPC));
|
||||||
// remove the spell from the spellbook
|
// remove the spell from the spellbook
|
||||||
array_extract_int(oPC, sSpellBook, nSpellbookID);
|
array_extract_int(oPC, sSpellBook, nSpellbookID);
|
||||||
|
array_extract_int(oPC, spellsAtLevelList, nSpellbookID);
|
||||||
// wipe the spell from the player
|
// wipe the spell from the player
|
||||||
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||||
WipeSpellFromHide(ipFeatID, oPC);
|
RemoveIPFeat(oPC, ipFeatID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1793,6 +1737,7 @@ void LearnSpells(int nClass, object oPC=OBJECT_SELF)
|
|||||||
|
|
||||||
// get location of persistant storage on the hide
|
// get location of persistant storage on the hide
|
||||||
string sSpellbook = GetSpellsKnown_Array(nClass, nSpellLevel);
|
string sSpellbook = GetSpellsKnown_Array(nClass, nSpellLevel);
|
||||||
|
if (DEBUG) DoDebug("Adding spell " + IntToString(nSpellbookID) + "to " + sSpellbook);
|
||||||
//object oToken = GetHideToken(oPC);
|
//object oToken = GetHideToken(oPC);
|
||||||
|
|
||||||
// Create spells known persistant array if it is missing
|
// Create spells known persistant array if it is missing
|
||||||
@@ -1803,13 +1748,25 @@ void LearnSpells(int nClass, object oPC=OBJECT_SELF)
|
|||||||
nSize = 0;
|
nSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string spellsAtLevelList = "SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(GetHitDice(oPC));
|
||||||
|
int spellsAtLevelSize = persistant_array_get_size(oPC, spellsAtLevelList);
|
||||||
|
if (spellsAtLevelSize < 0)
|
||||||
|
{
|
||||||
|
persistant_array_create(oPC, spellsAtLevelList);
|
||||||
|
spellsAtLevelSize = 0;
|
||||||
|
}
|
||||||
|
// set the list of spells learned at this level
|
||||||
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
|
int spellId = StringToInt(Get2DACache(sFile, "SpellID", nSpellbookID));
|
||||||
|
persistant_array_set_int(oPC, spellsAtLevelList, spellsAtLevelSize, spellId);
|
||||||
|
if (DEBUG) DoDebug("Adding spells to array " + spellsAtLevelList);
|
||||||
|
|
||||||
// Mark the spell as known (e.g. add it to the end of oPCs spellbook)
|
// Mark the spell as known (e.g. add it to the end of oPCs spellbook)
|
||||||
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
||||||
|
|
||||||
if (nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
if (nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||||
{
|
{
|
||||||
// add spell
|
// add spell
|
||||||
string sFile = GetClassSpellbookFile(nClass);
|
|
||||||
string sArrayName = "NewSpellbookMem_" + IntToString(nClass);
|
string sArrayName = "NewSpellbookMem_" + IntToString(nClass);
|
||||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
int featId = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||||||
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||||
@@ -1989,7 +1946,7 @@ void RemoveSpellKnown(int nClass, int spellbookId, object oPC=OBJECT_SELF, int n
|
|||||||
//if we could not find the spell here, something went wrong
|
//if we could not find the spell here, something went wrong
|
||||||
if (persistant_array_extract_int(oPC, sTestArray, spellID) < 0)
|
if (persistant_array_extract_int(oPC, sTestArray, spellID) < 0)
|
||||||
{
|
{
|
||||||
SendMessageToPC(oPC, "Could not find spellID " + IntToString(spellID) + " in the class's spellbook!");
|
if (DEBUG) DoDebug("Could not find spellID " + IntToString(spellID) + " in the class's spellbook!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2016,10 +1973,7 @@ void RemoveSpellKnown(int nClass, int spellbookId, object oPC=OBJECT_SELF, int n
|
|||||||
|
|
||||||
// remove spell from player
|
// remove spell from player
|
||||||
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", spellbookId));
|
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", spellbookId));
|
||||||
itemproperty ipFeat = PRCItemPropertyBonusFeat(ipFeatID);
|
RemoveIPFeat(oPC, ipFeatID);
|
||||||
object oSkin = GetPCSkin(oPC);
|
|
||||||
RemoveItemProperty(oSkin, ipFeat);
|
|
||||||
CheckAndRemoveFeat(oSkin, ipFeat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
json GetSpellIDsKnown(int nClass, object oPC=OBJECT_SELF, int nList=0)
|
json GetSpellIDsKnown(int nClass, object oPC=OBJECT_SELF, int nList=0)
|
||||||
@@ -2102,7 +2056,7 @@ string ReasonForDisabledSpell(int nClass, int spellbookId, object oPC=OBJECT_SEL
|
|||||||
|
|
||||||
// if its an expanded knowledge choice and we have already made all our
|
// if its an expanded knowledge choice and we have already made all our
|
||||||
// exp knowledge choices then it needs to be disabled.
|
// exp knowledge choices then it needs to be disabled.
|
||||||
if (IsExpKnowledgePower(nClass, spellbookId))
|
if (IsExpKnowledgePower(nClass, spellbookId, oPC))
|
||||||
{
|
{
|
||||||
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
|
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
|
||||||
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
||||||
@@ -2336,11 +2290,15 @@ json GetChosenReplaceListObject(object oPC=OBJECT_SELF)
|
|||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
int IsExpKnowledgePower(int nClass, int spellbookId)
|
int IsExpKnowledgePower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
|
||||||
{
|
{
|
||||||
string sFile = GetClassSpellbookFile(nClass);
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
|
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
|
||||||
return isExp;
|
if (isExp)
|
||||||
|
return TRUE;
|
||||||
|
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||||
|
int isOuterDomain = (featId) ? !CheckPowerPrereqs(featId, oPC) : FALSE;
|
||||||
|
return isOuterDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
json GetCurrentPowerList(object oPC=OBJECT_SELF)
|
json GetCurrentPowerList(object oPC=OBJECT_SELF)
|
||||||
@@ -2360,12 +2318,8 @@ int ShouldAddPower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
|
|||||||
string sFile = GetClassSpellbookFile(nClass);
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
|
||||||
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
|
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
|
||||||
// if you don't have the prereqs for a power then don't add it. Specific for
|
|
||||||
// psions
|
|
||||||
if (!CheckPowerPrereqs(featId, oPC))
|
|
||||||
return FALSE;
|
|
||||||
// if the power is a expanded knowledge power
|
// if the power is a expanded knowledge power
|
||||||
if (isExp)
|
if (!CheckPowerPrereqs(featId, oPC) || isExp)
|
||||||
{
|
{
|
||||||
// and we have a expanded knowledge choice left to make then show
|
// and we have a expanded knowledge choice left to make then show
|
||||||
// the button
|
// the button
|
||||||
@@ -2374,10 +2328,12 @@ int ShouldAddPower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
|
|||||||
int currentCircle = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
int currentCircle = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
|
||||||
|
|
||||||
int choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC);
|
int choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC);
|
||||||
|
if (DEBUG) DoDebug("You still have " + IntToString(choicesLeft) + " expanded power choices left!");
|
||||||
if (choicesLeft && (currentCircle <= (maxLevel-1)))
|
if (choicesLeft && (currentCircle <= (maxLevel-1)))
|
||||||
addPower = TRUE;
|
addPower = TRUE;
|
||||||
choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
|
||||||
if (choicesLeft)
|
if (DEBUG) DoDebug("You still have " + IntToString(choicesLeft) + " epic expanded power choices left!");
|
||||||
|
if (choicesLeft && (currentCircle <= (maxLevel-1)))
|
||||||
addPower = TRUE;
|
addPower = TRUE;
|
||||||
// otherwise don't show the button.
|
// otherwise don't show the button.
|
||||||
return addPower;
|
return addPower;
|
||||||
@@ -2397,7 +2353,7 @@ void LearnPowers(int nClass, object oPC=OBJECT_SELF)
|
|||||||
int nSpellbookID = JsonGetInt(JsonArrayGet(powerList, i));
|
int nSpellbookID = JsonGetInt(JsonArrayGet(powerList, i));
|
||||||
// get the expanded knowledge list we are adding to if any
|
// get the expanded knowledge list we are adding to if any
|
||||||
int expKnow = GetExpKnowledgePowerListRequired(nClass, nSpellbookID, oPC);
|
int expKnow = GetExpKnowledgePowerListRequired(nClass, nSpellbookID, oPC);
|
||||||
AddPowerKnown(oPC, nClass, nSpellbookID, TRUE, GetManifesterLevel(oPC, nClass, TRUE), expKnow);
|
AddPowerKnown(oPC, nClass, nSpellbookID, TRUE, GetHitDice(oPC), expKnow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3180,13 +3136,18 @@ json GetInvokerKnownListObject(int nClass, object oPC=OBJECT_SELF)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetLocalJson(oPC, NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR + IntToString(nClass), knownObject);
|
SetLocalJson(oPC, NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR + IntToString(nClass), knownObject);
|
||||||
|
if (DEBUG) DoDebug("Printing json representation of allowed invocations for class " + IntToString(nClass));
|
||||||
|
if (DEBUG) DoDebug(JsonDump(knownObject, 2));
|
||||||
return knownObject;
|
return knownObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJECT_SELF, int extra=TRUE)
|
int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJECT_SELF, int extra=TRUE)
|
||||||
{
|
{
|
||||||
|
if (DEBUG) DoDebug ("Getting remaining invocation choices at " + IntToString(chosenCircle) + " circle");
|
||||||
int remaining = 0;
|
int remaining = 0;
|
||||||
int nLevel = GetInvokerLevel(oPC, nClass);
|
int nLevel = GetInvokerLevel(oPC, nClass);
|
||||||
|
if (nClass == CLASS_TYPE_DRAGON_SHAMAN) nLevel = GetLevelByClass(nClass, oPC);
|
||||||
|
if (DEBUG) DoDebug("Invoker level is " + IntToString(nLevel));
|
||||||
|
|
||||||
json knownObject = GetInvokerKnownListObject(nClass, oPC);
|
json knownObject = GetInvokerKnownListObject(nClass, oPC);
|
||||||
json chosenInv = GetChosenSpellListObject(nClass, oPC);
|
json chosenInv = GetChosenSpellListObject(nClass, oPC);
|
||||||
@@ -3214,8 +3175,10 @@ int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJEC
|
|||||||
currentChosen += 1;
|
currentChosen += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (DEBUG) DoDebug(IntToString(currentChosen) + " incantations chosen at " + IntToString(chosenCircle) + " circle");
|
||||||
|
|
||||||
int allowedAtCircle = JsonGetInt(JsonObjectGet(currentLevelKnown, IntToString(i)));
|
int allowedAtCircle = JsonGetInt(JsonObjectGet(currentLevelKnown, IntToString(i)));
|
||||||
|
if (DEBUG) DoDebug(IntToString(allowedAtCircle) + " incantations allowed at " + IntToString(chosenCircle) + " circle");
|
||||||
|
|
||||||
remaining = (allowedAtCircle - currentChosen + remaining);
|
remaining = (allowedAtCircle - currentChosen + remaining);
|
||||||
// if the circle is below the chosen circle and we have a positive remaining,
|
// if the circle is below the chosen circle and we have a positive remaining,
|
||||||
|
|||||||
@@ -93,9 +93,8 @@ void GainPowerPoints(object oChar, int nGain, int bCanExceedMax = FALSE, int bIn
|
|||||||
* @param bInform If TRUE, runs TellCharacterPowerPointStatus() on oChar
|
* @param bInform If TRUE, runs TellCharacterPowerPointStatus() on oChar
|
||||||
* after making the modification.
|
* after making the modification.
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
void GainTemporaryPowerPoints(object oChar, int nGain, float fDuration, int bInform = TRUE);
|
void GainTemporaryPowerPoints(object oChar, int nGain, float fDuration, int bInform = TRUE);
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* Decreases the character's current power point count by up to the given
|
* Decreases the character's current power point count by up to the given
|
||||||
* amount, limited to not going below 0.
|
* amount, limited to not going below 0.
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void CheckIfDeleveled(object oPC);
|
||||||
|
void UpdateLastKnownLevels(object oPC);
|
||||||
void CheckSpellbooks(object oPC);
|
void CheckSpellbooks(object oPC);
|
||||||
void CheckPsionics(object oPC);
|
void CheckPsionics(object oPC);
|
||||||
void CheckInvocations(object oPC);
|
void CheckInvocations(object oPC);
|
||||||
@@ -71,9 +73,72 @@ void main()
|
|||||||
eTest = GetNextEffect(oPC);
|
eTest = GetNextEffect(oPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckIfDeleveled(oPC);
|
||||||
|
|
||||||
DelayCommand(0.0f, CheckSpellbooks(oPC));
|
DelayCommand(0.0f, CheckSpellbooks(oPC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckIfDeleveled(object oPC)
|
||||||
|
{
|
||||||
|
int lastKnownLevel = GetPersistantLocalInt(oPC, "PCLastKnownLevel");
|
||||||
|
int currentLevel = GetHitDice(oPC);
|
||||||
|
if (lastKnownLevel > 0 && currentLevel < lastKnownLevel)
|
||||||
|
{
|
||||||
|
if (DEBUG) DoDebug("The player has de-leveled, checking spells!");
|
||||||
|
json changedClassList = JsonArray();
|
||||||
|
int i;
|
||||||
|
for (i = 1; i <= 8; i++)
|
||||||
|
{
|
||||||
|
int storedClass = GetPersistantLocalInt(oPC, "PCLastKnownClass" + IntToString(i));
|
||||||
|
if (storedClass && storedClass != CLASS_TYPE_INVALID)
|
||||||
|
{
|
||||||
|
int storedLevel = GetPersistantLocalInt(oPC, "PCLastKnownClass" + IntToString(i) + "Levels");
|
||||||
|
int nClass = GetClassByPosition(i, oPC);
|
||||||
|
int currentClassLevels = (GetIsArcaneClass(nClass, oPC) || GetIsDivineClass(nClass, oPC))
|
||||||
|
? GetPrCAdjustedClassLevel(nClass, oPC) : GetLevelByClass(nClass, oPC);
|
||||||
|
if (nClass == CLASS_TYPE_INVALID
|
||||||
|
|| (nClass == storedClass && storedLevel != currentClassLevels))
|
||||||
|
{
|
||||||
|
DoDebug("Class " + IntToString(storedClass) + " lost levels!");
|
||||||
|
changedClassList = JsonArrayInsert(changedClassList, JsonInt(storedClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = lastKnownLevel; i > currentLevel; i--)
|
||||||
|
{
|
||||||
|
int totalChangedClasses = JsonGetLength(changedClassList);
|
||||||
|
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < totalChangedClasses; j++)
|
||||||
|
{
|
||||||
|
int nClass = JsonGetInt(JsonArrayGet(changedClassList, j));
|
||||||
|
DelayCommand(0.0f, CallSpellUnlevelScript(oPC, nClass, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DoDebug("Setting last known player level to " + IntToString(currentLevel));
|
||||||
|
UpdateLastKnownLevels(oPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateLastKnownLevels(object oPC)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 1; i <= 8; i++)
|
||||||
|
{
|
||||||
|
int nClass = GetClassByPosition(i, oPC);
|
||||||
|
int classLevel = (GetIsArcaneClass(nClass, oPC) || GetIsDivineClass(nClass, oPC))
|
||||||
|
? GetPrCAdjustedClassLevel(nClass, oPC) : GetLevelByClass(nClass, oPC);
|
||||||
|
|
||||||
|
SetPersistantLocalInt(oPC, "PCLastKnownClass" + IntToString(i), nClass);
|
||||||
|
SetPersistantLocalInt(oPC, "PCLastKnownClass" + IntToString(i) + "Levels", classLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentLevel = GetHitDice(oPC);
|
||||||
|
SetPersistantLocalInt(oPC, "PCLastKnownLevel", currentLevel);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle new spellbooks
|
// Handle new spellbooks
|
||||||
|
|
||||||
void CheckSpellbooks(object oPC)
|
void CheckSpellbooks(object oPC)
|
||||||
|
|||||||
BIN
nwn/nwnprc/trunk/others/bite_pitfiend001.uti
Normal file
BIN
nwn/nwnprc/trunk/others/bite_pitfiend001.uti
Normal file
Binary file not shown.
BIN
nwn/nwnprc/trunk/others/bite_pitfiend002.uti
Normal file
BIN
nwn/nwnprc/trunk/others/bite_pitfiend002.uti
Normal file
Binary file not shown.
BIN
nwn/nwnprc/trunk/others/hide_pitfiend001.uti
Normal file
BIN
nwn/nwnprc/trunk/others/hide_pitfiend001.uti
Normal file
Binary file not shown.
BIN
nwn/nwnprc/trunk/others/prc_2d4_slamgrab.uti
Normal file
BIN
nwn/nwnprc/trunk/others/prc_2d4_slamgrab.uti
Normal file
Binary file not shown.
BIN
nwn/nwnprc/trunk/others/prc_2d6_slamgrab.uti
Normal file
BIN
nwn/nwnprc/trunk/others/prc_2d6_slamgrab.uti
Normal file
Binary file not shown.
BIN
nwn/nwnprc/trunk/others/prc_scr_1564.uti
Normal file
BIN
nwn/nwnprc/trunk/others/prc_scr_1564.uti
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -55,13 +55,25 @@ int DoPower(object oManifester, object oTarget, struct manifestation manif)
|
|||||||
// It's a creature, target their primary weapon
|
// It's a creature, target their primary weapon
|
||||||
oTarget = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
oTarget = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||||
}
|
}
|
||||||
// Make sure the target is either weapon or ammo
|
|
||||||
|
// Validate that the target is a weapon or ammunition
|
||||||
|
int bIsWeapon = GetWeaponRanged(oTarget) || IPGetIsMeleeWeapon(oTarget);
|
||||||
|
|
||||||
|
int nBase = GetBaseItemType(oTarget);
|
||||||
|
int bIsAmmo = nBase == BASE_ITEM_ARROW || nBase == BASE_ITEM_BOLT || nBase == BASE_ITEM_BULLET;
|
||||||
|
|
||||||
|
if (!(bIsWeapon || bIsAmmo))
|
||||||
|
{
|
||||||
|
oTarget = OBJECT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* // Make sure the target is either weapon or ammo
|
||||||
if(!(GetWeaponRanged(oTarget) || IPGetIsMeleeWeapon(oTarget) ||
|
if(!(GetWeaponRanged(oTarget) || IPGetIsMeleeWeapon(oTarget) ||
|
||||||
GetBaseItemType(oTarget) == BASE_ITEM_ARROW ||
|
GetBaseItemType(oTarget) == BASE_ITEM_ARROW ||
|
||||||
GetBaseItemType(oTarget) == BASE_ITEM_BOLT ||
|
GetBaseItemType(oTarget) == BASE_ITEM_BOLT ||
|
||||||
GetBaseItemType(oTarget) == BASE_ITEM_BULLET
|
GetBaseItemType(oTarget) == BASE_ITEM_BULLET
|
||||||
) )
|
) )
|
||||||
oTarget = OBJECT_INVALID;
|
oTarget = OBJECT_INVALID; */
|
||||||
|
|
||||||
// Make sure we have a valid target
|
// Make sure we have a valid target
|
||||||
if(!GetIsObjectValid(oTarget))
|
if(!GetIsObjectValid(oTarget))
|
||||||
|
|||||||
@@ -966,6 +966,17 @@ void main()
|
|||||||
sResRef += GetAffixForSize(nSize);
|
sResRef += GetAffixForSize(nSize);
|
||||||
AddNaturalPrimaryWeapon(oPC, sResRef, 2);
|
AddNaturalPrimaryWeapon(oPC, sResRef, 2);
|
||||||
}
|
}
|
||||||
|
else if(nRace==RACIAL_TYPE_ZAKYA_RAKSHASA)
|
||||||
|
{
|
||||||
|
string sResRef = "prc_raks_bite_";
|
||||||
|
int nSize = PRCGetCreatureSize(oPC);
|
||||||
|
sResRef += GetAffixForSize(nSize);
|
||||||
|
AddNaturalSecondaryWeapon(oPC, sResRef);
|
||||||
|
//primary weapon
|
||||||
|
sResRef = "prc_claw_1d6l_";
|
||||||
|
sResRef += GetAffixForSize(nSize);
|
||||||
|
AddNaturalPrimaryWeapon(oPC, sResRef, 1);
|
||||||
|
}
|
||||||
else if(nRace==RACIAL_TYPE_LIZARDFOLK)
|
else if(nRace==RACIAL_TYPE_LIZARDFOLK)
|
||||||
{
|
{
|
||||||
string sResRef = "prc_lizf_bite_";
|
string sResRef = "prc_lizf_bite_";
|
||||||
|
|||||||
@@ -158,10 +158,6 @@ void main()
|
|||||||
|
|
||||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oShadow);
|
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oShadow);
|
||||||
|
|
||||||
// Full round wait then move
|
|
||||||
AssignCommand(oShadow, ClearAllActions());
|
|
||||||
AssignCommand(oShadow, ActionWait(6.0));
|
|
||||||
AssignCommand(oShadow, ActionMoveToObject(oPC));
|
|
||||||
|
|
||||||
// Start watch loop
|
// Start watch loop
|
||||||
DelayCommand(6.1, ShadowServantWatch(oShadow, oPC));
|
DelayCommand(6.1, ShadowServantWatch(oShadow, oPC));
|
||||||
@@ -3,8 +3,19 @@
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_ch_summon_9", OBJECT_SELF);
|
object oNPC = OBJECT_SELF;
|
||||||
ExecuteScript("prc_npc_spawn", OBJECT_SELF);
|
|
||||||
|
ExecuteScript("nw_ch_summon_9", oNPC);
|
||||||
|
ExecuteScript("prc_npc_spawn", oNPC);
|
||||||
|
|
||||||
|
//:: Used for the Twinfiend Pit Fiend summon
|
||||||
|
int nUltravision = GetLocalInt(oNPC,"INNATE_ULTRAVISION");
|
||||||
|
if(nUltravision)
|
||||||
|
{
|
||||||
|
effect eUltra = EffectUltravision();
|
||||||
|
eUltra = UnyieldingEffect(eUltra);
|
||||||
|
DelayCommand(0.0f, ApplyEffectToObject(DURATION_TYPE_PERMANENT, eUltra, oNPC));
|
||||||
|
}
|
||||||
|
|
||||||
//use companion appearances
|
//use companion appearances
|
||||||
/*if(GetPRCSwitch(MARKER_PRC_COMPANION))
|
/*if(GetPRCSwitch(MARKER_PRC_COMPANION))
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ void main()
|
|||||||
int bKing = GetHasFeat(FEAT_KING_LIES, oPC) ? 4 : 0;
|
int bKing = GetHasFeat(FEAT_KING_LIES, oPC) ? 4 : 0;
|
||||||
int bDevil = GetHasFeat(FEAT_TONGUE_DEVIL, oPC) ? iInt : 0;
|
int bDevil = GetHasFeat(FEAT_TONGUE_DEVIL, oPC) ? iInt : 0;
|
||||||
|
|
||||||
if (bKing>0) KingofLies(oPC, oSkin,bKing);
|
//if (bKing>0) KingofLies(oPC, oSkin,bKing); Handled in stat 2DA now
|
||||||
if (bDevil>0) DevilTongue(oPC, oSkin,bDevil);
|
if (bDevil>0) DevilTongue(oPC, oSkin,bDevil);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "psi_inc_psifunc"
|
#include "psi_inc_psifunc"
|
||||||
#include "inc_ecl"
|
#include "inc_ecl"
|
||||||
#include "prc_inc_assoc"
|
#include "prc_inc_assoc"
|
||||||
|
#include "prc_inc_combmove"
|
||||||
|
|
||||||
void PreyOnTheWeak(object oDead)
|
void PreyOnTheWeak(object oDead)
|
||||||
{
|
{
|
||||||
@@ -49,6 +50,9 @@ void main()
|
|||||||
object oDead = GetLastBeingDied();
|
object oDead = GetLastBeingDied();
|
||||||
object oKiller = MyGetLastKiller();
|
object oKiller = MyGetLastKiller();
|
||||||
|
|
||||||
|
DelayCommand(0.1f, EndGrapple(oDead, oKiller));
|
||||||
|
DelayCommand(0.2f, EndGrapple(oKiller, oDead));
|
||||||
|
|
||||||
// We are not actually dead until -10
|
// We are not actually dead until -10
|
||||||
// Unless it's a spell death
|
// Unless it's a spell death
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,28 @@ const string CHAT_COMMAND_INDICATOR_1 = "~~";
|
|||||||
const string CHAT_COMMAND_INDICATOR_2 = "..";
|
const string CHAT_COMMAND_INDICATOR_2 = "..";
|
||||||
const int CHAT_COMMAND_INDICATOR_LENGHT = 2;
|
const int CHAT_COMMAND_INDICATOR_LENGHT = 2;
|
||||||
|
|
||||||
|
void ForceRemoveAllSpells(object oPC)
|
||||||
|
{
|
||||||
|
int classId;
|
||||||
|
for(classId = 1; classId < CLASS_TYPE_INVALID; classId++)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
for (j = 0; j <= 40; j++)
|
||||||
|
{
|
||||||
|
DelayCommand(0.0f, CallSpellUnlevelScript(oPC, classId, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SendMessageToPC(oPC, "Finished removing spells.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetCharacterXPAndRemoveSpells(object oPC)
|
||||||
|
{
|
||||||
|
int xp = GetXP(oPC);
|
||||||
|
ForceRemoveAllSpells(oPC);
|
||||||
|
SetXP(oPC, 1);
|
||||||
|
SetXP(oPC, xp);
|
||||||
|
}
|
||||||
|
|
||||||
int GetIsChatCommand(string sString)
|
int GetIsChatCommand(string sString)
|
||||||
{
|
{
|
||||||
string sTest = GetStringLeft(sString, CHAT_COMMAND_INDICATOR_LENGHT);
|
string sTest = GetStringLeft(sString, CHAT_COMMAND_INDICATOR_LENGHT);
|
||||||
@@ -111,6 +133,50 @@ void main()
|
|||||||
string firstWord = JsonGetString(JsonArrayGet(sCommandSplit, 0));
|
string firstWord = JsonGetString(JsonArrayGet(sCommandSplit, 0));
|
||||||
|
|
||||||
// if first word is /pa we are using the power attack interface
|
// if first word is /pa we are using the power attack interface
|
||||||
|
if (firstWord == "/relevel")
|
||||||
|
{
|
||||||
|
int confirmed = GetLocalInt(oPC, "RelevelConfirm");
|
||||||
|
if(confirmed)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "Please wait as we relevel you, this may take some time...");
|
||||||
|
DelayCommand(1.0f, ResetCharacterXPAndRemoveSpells(oPC));
|
||||||
|
DeleteLocalInt(oPC, "RelevelConfirm");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "This will relevel you back to level 1 while preserving XP, type /relevel again to confirm.");
|
||||||
|
SetLocalInt(oPC, "RelevelConfirm", 1);
|
||||||
|
CloseNUILevelUpWindow(oPC, TRUE);
|
||||||
|
}
|
||||||
|
SetPCChatMessage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeleteLocalInt(oPC, "RelevelConfirm");
|
||||||
|
SetPCChatMessage();
|
||||||
|
}
|
||||||
|
if (firstWord == "/resetSpells")
|
||||||
|
{
|
||||||
|
int confirmed = GetLocalInt(oPC, "ResetSpellsConfirm");
|
||||||
|
if (confirmed)
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "Please wait as we remove your spells, this may take some time...");
|
||||||
|
DelayCommand(1.0f, ForceRemoveAllSpells(oPC));
|
||||||
|
DeleteLocalInt(oPC, "ResetSpellsConfirm");
|
||||||
|
CloseNUILevelUpWindow(oPC, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessageToPC(oPC, "This will reset all spell choices among all PRC classes. Type /resetSpells again to confirm.");
|
||||||
|
SetLocalInt(oPC, "ResetSpellsConfirm", 1);
|
||||||
|
}
|
||||||
|
SetPCChatMessage();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeleteLocalInt(oPC, "ResetSpellsConfirm");
|
||||||
|
SetPCChatMessage();
|
||||||
|
}
|
||||||
if(firstWord == "/pa")
|
if(firstWord == "/pa")
|
||||||
{
|
{
|
||||||
if(JsonGetLength(sCommandSplit) >= 2)
|
if(JsonGetLength(sCommandSplit) >= 2)
|
||||||
@@ -147,17 +213,6 @@ void main()
|
|||||||
SetPCChatMessage();
|
SetPCChatMessage();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (firstWord == "/lvl")
|
|
||||||
{
|
|
||||||
if (JsonGetLength(sCommandSplit) >= 2)
|
|
||||||
{
|
|
||||||
int classPos = StringToInt(JsonGetString(JsonArrayGet(sCommandSplit, 1)));
|
|
||||||
int nClass = GetClassByPosition(classPos, oPC);
|
|
||||||
OpenNUILevelUpWindow(nClass, oPC);
|
|
||||||
SetPCChatMessage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute scripts hooked to this event for the player triggering it
|
// Execute scripts hooked to this event for the player triggering it
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ int GetHighestSpellAvailableByDescriptor(object oPC, string sDescriptor)
|
|||||||
sSpellLabel = Get2DACache(sFile, "Label", i);
|
sSpellLabel = Get2DACache(sFile, "Label", i);
|
||||||
if(sSpellLabel != "") // Non-blank row
|
if(sSpellLabel != "") // Non-blank row
|
||||||
{
|
{
|
||||||
SendMessageToPC(oPC, "GetHighestSpellAvailableByDescriptor >> Entered function.");
|
if (DEBUG) DoDebug("GetHighestSpellAvailableByDescriptor >> Entered function.");
|
||||||
SendMessageToPC(oPC, "Row " + IntToString(i) +
|
if (DEBUG) DoDebug("Row " + IntToString(i) +
|
||||||
" Label = " + sSpellLabel +
|
" Label = " + sSpellLabel +
|
||||||
" SpellID = " + IntToString(nSpellID) +
|
" SpellID = " + IntToString(nSpellID) +
|
||||||
" HasSpell " + IntToString(PRCGetHasSpell(nSpellID, oPC)));
|
" HasSpell " + IntToString(PRCGetHasSpell(nSpellID, oPC)));
|
||||||
|
|||||||
474
nwn/nwnprc/trunk/scripts/prc_unlvl_script.nss
Normal file
474
nwn/nwnprc/trunk/scripts/prc_unlvl_script.nss
Normal file
@@ -0,0 +1,474 @@
|
|||||||
|
//::///////////////////////////////////////////////
|
||||||
|
//:: PRC Unlevel Logic
|
||||||
|
//:: prc_unlvl_script
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
This is the logic for removing spells from a PRC class in case of
|
||||||
|
unleveling or for fixing issues
|
||||||
|
*/
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
//:: Created By: Rakiov
|
||||||
|
//:: Created On: 22.09.2025
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "tob_inc_tobfunc"
|
||||||
|
#include "tob_inc_moveknwn"
|
||||||
|
#include "inv_inc_invfunc"
|
||||||
|
#include "shd_inc_mystknwn"
|
||||||
|
#include "shd_inc_shdfunc"
|
||||||
|
#include "true_inc_truknwn"
|
||||||
|
#include "true_inc_trufunc"
|
||||||
|
#include "prc_nui_com_inc"
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// ///
|
||||||
|
/// Implementations ///
|
||||||
|
/// ///
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int FindSpellbookId(int nClass, int spellId)
|
||||||
|
{
|
||||||
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
|
int totalSpells = Get2DARowCount(sFile);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < totalSpells; i++)
|
||||||
|
{
|
||||||
|
int currentSpellId = StringToInt(Get2DACache(sFile, "SpellID", i));
|
||||||
|
if (currentSpellId == spellId)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveSpellsFromPlayer(object oPC, int nClass, string spellArray, string totalSpellsId, int nType=0)
|
||||||
|
{
|
||||||
|
// if we found the spell, then we remove it.
|
||||||
|
int totalRemoved = persistant_array_get_size(oPC, spellArray);
|
||||||
|
if (DEBUG) DoDebug("Found " + IntToString(totalRemoved) + " spells in " + spellArray + ", removing them.");
|
||||||
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < totalRemoved; i++)
|
||||||
|
{
|
||||||
|
int spellId = persistant_array_get_int(oPC, spellArray, i);
|
||||||
|
int spellbookId = FindSpellbookId(nClass, spellId);
|
||||||
|
|
||||||
|
if (spellbookId != 0)
|
||||||
|
{
|
||||||
|
// remove spell from player
|
||||||
|
string spellName = Get2DACache(sFile, "Label", spellbookId);
|
||||||
|
if (DEBUG) DoDebug( "Removing spell " + spellName);
|
||||||
|
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", spellbookId));
|
||||||
|
object oSkin = GetPCSkin(oPC);
|
||||||
|
RemoveIPFeat(oPC, ipFeatID);
|
||||||
|
if (GetIsBladeMagicClass(nClass))
|
||||||
|
{
|
||||||
|
string sDisciplineArray = _MANEUVER_LIST_DISCIPLINE + IntToString(nType) + "_" + Get2DACache(sFile, "Discipline", spellbookId);
|
||||||
|
int totalDiscSpells = GetPersistantLocalInt(oPC, sDisciplineArray);
|
||||||
|
SetPersistantLocalInt(oPC, sDisciplineArray, totalDiscSpells - 1);
|
||||||
|
if (DEBUG) DoDebug(sDisciplineArray + " total maneuvers is now " + IntToString(totalDiscSpells-1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
persistant_array_delete(oPC, spellArray);
|
||||||
|
|
||||||
|
int totalSpellCount = GetPersistantLocalInt(oPC, totalSpellsId);
|
||||||
|
// decrement the amount of spells known.
|
||||||
|
SetPersistantLocalInt(oPC, totalSpellsId,
|
||||||
|
totalSpellCount - totalRemoved
|
||||||
|
);
|
||||||
|
if (DEBUG) DoDebug(totalSpellsId + " total spells is now " + IntToString(totalSpellCount - totalRemoved));
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetMaxSpellsKnownName(int nClass)
|
||||||
|
{
|
||||||
|
if (GetIsShadowMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MYSTERY_LIST_TOTAL_KNOWN;
|
||||||
|
}
|
||||||
|
if (GetIsInvocationClass(nClass))
|
||||||
|
{
|
||||||
|
return _INVOCATION_LIST_TOTAL_KNOWN;
|
||||||
|
}
|
||||||
|
if (GetIsBladeMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MANEUVER_LIST_TOTAL_KNOWN;
|
||||||
|
}
|
||||||
|
if (GetIsTruenamingClass(nClass))
|
||||||
|
{
|
||||||
|
return _UTTERANCE_LIST_TOTAL_KNOWN;
|
||||||
|
}
|
||||||
|
if (GetIsPsionicClass(nClass))
|
||||||
|
{
|
||||||
|
return _POWER_LIST_TOTAL_KNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetGeneralArrayId(int nClass)
|
||||||
|
{
|
||||||
|
if (GetIsShadowMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MYSTERY_LIST_GENERAL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsInvocationClass(nClass))
|
||||||
|
{
|
||||||
|
return _INVOCATION_LIST_GENERAL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsBladeMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MANEUVER_LIST_GENERAL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsTruenamingClass(nClass))
|
||||||
|
{
|
||||||
|
return _UTTERANCE_LIST_GENERAL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsPsionicClass(nClass))
|
||||||
|
{
|
||||||
|
return _POWER_LIST_GENERAL_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetBaseListName(int nClass)
|
||||||
|
{
|
||||||
|
if (GetIsShadowMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MYSTERY_LIST_NAME_BASE;
|
||||||
|
}
|
||||||
|
if (GetIsInvocationClass(nClass))
|
||||||
|
{
|
||||||
|
return _INVOCATION_LIST_NAME_BASE;
|
||||||
|
}
|
||||||
|
if (GetIsBladeMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MANEUVER_LIST_NAME_BASE;
|
||||||
|
}
|
||||||
|
if (GetIsTruenamingClass(nClass))
|
||||||
|
{
|
||||||
|
return _UTTERANCE_LIST_NAME_BASE;
|
||||||
|
}
|
||||||
|
if (GetIsPsionicClass(nClass))
|
||||||
|
{
|
||||||
|
return _POWER_LIST_NAME_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetLevelArrayListName(int nClass)
|
||||||
|
{
|
||||||
|
if (GetIsShadowMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MYSTERY_LIST_LEVEL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsInvocationClass(nClass))
|
||||||
|
{
|
||||||
|
return _INVOCATION_LIST_LEVEL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsBladeMagicClass(nClass))
|
||||||
|
{
|
||||||
|
return _MANEUVER_LIST_LEVEL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsTruenamingClass(nClass))
|
||||||
|
{
|
||||||
|
return _UTTERANCE_LIST_LEVEL_ARRAY;
|
||||||
|
}
|
||||||
|
if (GetIsPsionicClass(nClass))
|
||||||
|
{
|
||||||
|
return _POWER_LIST_LEVEL_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveSpellsAtLevel(object oPC, int nClass, int level, int nList = 0)
|
||||||
|
{
|
||||||
|
if (GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||||
|
{
|
||||||
|
string sFile = GetClassSpellbookFile(nClass);
|
||||||
|
string spellsAtLevelList = ("SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(level));
|
||||||
|
string spellLevelBook = GetSpellsKnown_Array(nClass);
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
|
spellsAtLevelList = spellLevelBook;
|
||||||
|
int totalSpells = Get2DARowCount(sFile);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < totalSpells; i++)
|
||||||
|
{
|
||||||
|
int featID = StringToInt(Get2DACache(sFile, "FeatID", i));
|
||||||
|
if (featID && GetHasFeat(featID, oPC, TRUE))
|
||||||
|
{
|
||||||
|
string spellName = Get2DACache(sFile, "Label", i);
|
||||||
|
if (DEBUG) DoDebug( "Removing spellID " + IntToString(i) + ", spell name: " + spellName);
|
||||||
|
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", i));
|
||||||
|
WipeSpellFromHide(ipFeatID, oPC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
persistant_array_delete(oPC, spellsAtLevelList);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (persistant_array_exists(oPC, spellsAtLevelList))
|
||||||
|
{
|
||||||
|
if (DEBUG) DoDebug( "Removing spells in " + spellsAtLevelList);
|
||||||
|
int knownSpellsCount = persistant_array_get_size(oPC, spellsAtLevelList);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < knownSpellsCount; i++)
|
||||||
|
{
|
||||||
|
int spellId = persistant_array_get_int(oPC, spellsAtLevelList, i);
|
||||||
|
int spellbookId = FindSpellbookId(nClass, spellId);
|
||||||
|
|
||||||
|
if (spellbookId)
|
||||||
|
{
|
||||||
|
array_extract_int(oPC, spellLevelBook, spellbookId);
|
||||||
|
|
||||||
|
// wipe the spell from the player
|
||||||
|
string spellName = Get2DACache(sFile, "Label", spellbookId);
|
||||||
|
if (DEBUG) DoDebug( "Removing spellID " + IntToString(spellbookId) + ", spell name: " + spellName);
|
||||||
|
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", spellbookId));
|
||||||
|
WipeSpellFromHide(ipFeatID, oPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
persistant_array_delete(oPC, spellsAtLevelList);
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BEGUILER
|
||||||
|
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||||
|
|| nClass == CLASS_TYPE_WARMAGE)
|
||||||
|
{
|
||||||
|
int nAdvLearn = GetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass)) - knownSpellsCount;
|
||||||
|
SetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass), nAdvLearn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int chosenList = (nList != 0) ? nList : nClass;
|
||||||
|
string baseList = GetBaseListName(nClass);
|
||||||
|
string totalCountId = GetMaxSpellsKnownName(nClass);
|
||||||
|
|
||||||
|
if (GetIsBladeMagicClass(nClass))
|
||||||
|
{
|
||||||
|
|
||||||
|
// remove maneuvers
|
||||||
|
int maneuver;
|
||||||
|
for (maneuver = 1; maneuver <= MANEUVER_TYPE_MANEUVER; maneuver++)
|
||||||
|
{
|
||||||
|
string spellArray = baseList + IntToString(chosenList) + IntToString(maneuver);
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
|
spellArray += GetGeneralArrayId(nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spellArray += GetLevelArrayListName(nClass) + IntToString(level);
|
||||||
|
}
|
||||||
|
if (persistant_array_exists(oPC, spellArray))
|
||||||
|
{
|
||||||
|
string totalSpellsId = baseList + IntToString(chosenList) + IntToString(maneuver) + totalCountId;
|
||||||
|
RemoveSpellsFromPlayer(oPC, nClass, spellArray, totalSpellsId, maneuver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (GetIsTruenamingClass(nClass))
|
||||||
|
{
|
||||||
|
// Lexicon 1
|
||||||
|
string spellArray = baseList + IntToString(chosenList) + "1";
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
|
spellArray += GetGeneralArrayId(nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spellArray += GetLevelArrayListName(nClass) + IntToString(level);
|
||||||
|
}
|
||||||
|
if (persistant_array_exists(oPC, spellArray))
|
||||||
|
{
|
||||||
|
string totalSpellsId = baseList + IntToString(chosenList) + totalCountId;
|
||||||
|
RemoveSpellsFromPlayer(oPC, nClass, spellArray, totalSpellsId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lexicon 2
|
||||||
|
spellArray = baseList + IntToString(chosenList) + "2";
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
|
spellArray += GetGeneralArrayId(nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spellArray += GetLevelArrayListName(nClass) + IntToString(level);
|
||||||
|
}
|
||||||
|
if (persistant_array_exists(oPC, spellArray))
|
||||||
|
{
|
||||||
|
string totalSpellsId = baseList + IntToString(chosenList) + totalCountId;
|
||||||
|
RemoveSpellsFromPlayer(oPC, nClass, spellArray, totalSpellsId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lexicon 3
|
||||||
|
spellArray = baseList + IntToString(chosenList) + "3";
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
|
spellArray += GetGeneralArrayId(nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spellArray += GetLevelArrayListName(nClass) + IntToString(level);
|
||||||
|
}
|
||||||
|
if (persistant_array_exists(oPC, spellArray))
|
||||||
|
{
|
||||||
|
string totalSpellsId = baseList + IntToString(chosenList) + totalCountId;
|
||||||
|
RemoveSpellsFromPlayer(oPC, nClass, spellArray, totalSpellsId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string spellArray = (baseList + IntToString(chosenList));
|
||||||
|
if (level == 0)
|
||||||
|
{
|
||||||
|
spellArray += GetGeneralArrayId(nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spellArray += GetLevelArrayListName(nClass) + IntToString(level);
|
||||||
|
}
|
||||||
|
if (persistant_array_exists(oPC, spellArray))
|
||||||
|
{
|
||||||
|
if (DEBUG) DoDebug( "Removing spells from " + spellArray);
|
||||||
|
string totalSpellsId = baseList + IntToString(chosenList) + totalCountId;
|
||||||
|
RemoveSpellsFromPlayer(oPC, nClass, spellArray, totalSpellsId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int IsClassPRCSpellCaster(int nClass, object oPlayer)
|
||||||
|
{
|
||||||
|
// This controls who can use the Spellbook NUI, if for some reason you don't
|
||||||
|
// want a class to be allowed to use this you can comment out their line here
|
||||||
|
|
||||||
|
// Bard and Sorc are allowed if they took a PRC that makes them use the spellbook
|
||||||
|
if (GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Arcane Spont
|
||||||
|
if (nClass == CLASS_TYPE_ASSASSIN
|
||||||
|
|| nClass == CLASS_TYPE_BEGUILER
|
||||||
|
|| nClass == CLASS_TYPE_CELEBRANT_SHARESS
|
||||||
|
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||||
|
|| nClass == CLASS_TYPE_DUSKBLADE
|
||||||
|
|| nClass == CLASS_TYPE_HARPER
|
||||||
|
|| nClass == CLASS_TYPE_HEXBLADE
|
||||||
|
|| nClass == CLASS_TYPE_KNIGHT_WEAVE
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWLORD
|
||||||
|
|| nClass == CLASS_TYPE_SUBLIME_CHORD
|
||||||
|
|| nClass == CLASS_TYPE_SUEL_ARCHANAMACH
|
||||||
|
|| nClass == CLASS_TYPE_WARMAGE)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Psionics
|
||||||
|
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_PSION
|
||||||
|
|| nClass == CLASS_TYPE_PSYWAR
|
||||||
|
|| nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Invokers
|
||||||
|
if (nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Divine Spont
|
||||||
|
if (nClass == CLASS_TYPE_ARCHIVIST //while technically prepared, they use the spont system of casting
|
||||||
|
|| nClass == CLASS_TYPE_FAVOURED_SOUL
|
||||||
|
|| nClass == CLASS_TYPE_JUSTICEWW)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// ToB Classes
|
||||||
|
if (nClass == CLASS_TYPE_WARBLADE
|
||||||
|
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||||
|
|| nClass == CLASS_TYPE_CRUSADER)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Mystery Classes
|
||||||
|
if (nClass == CLASS_TYPE_SHADOWCASTER
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWSMITH)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Truenamers
|
||||||
|
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// RHD Casters
|
||||||
|
if ((nClass == CLASS_TYPE_SHAPECHANGER
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_ARANEA
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_OUTSIDER
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_RAKSHASA
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_ABERRATION
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_DRIDER
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_ARKAMOI
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_HOBGOBLIN_WARSOUL
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_REDSPAWN_ARCANISS
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_MONSTROUS
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_MARRUTACT
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_SORCERER))
|
||||||
|
|| (nClass == CLASS_TYPE_FEY
|
||||||
|
&& GetRacialType(oPlayer) == RACIAL_TYPE_GLOURA
|
||||||
|
&& !GetLevelByClass(CLASS_TYPE_BARD)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
// Binders
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckAndRemoveSpellsForClassAtLevel(object oPC, int nClass, int level)
|
||||||
|
{
|
||||||
|
if (IsClassPRCSpellCaster(nClass, oPC))
|
||||||
|
{
|
||||||
|
if (GetIsInvocationClass(nClass))
|
||||||
|
{
|
||||||
|
RemoveSpellsAtLevel(oPC, nClass, level, INVOCATION_LIST_EXTRA);
|
||||||
|
RemoveSpellsAtLevel(oPC, nClass, level, INVOCATION_LIST_EXTRA_EPIC);
|
||||||
|
}
|
||||||
|
if (GetIsPsionicClass(nClass))
|
||||||
|
{
|
||||||
|
RemoveSpellsAtLevel(oPC, nClass, level, POWER_LIST_EXP_KNOWLEDGE);
|
||||||
|
RemoveSpellsAtLevel(oPC, nClass, level, POWER_LIST_EPIC_EXP_KNOWLEDGE);
|
||||||
|
}
|
||||||
|
RemoveSpellsAtLevel(oPC, nClass, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
int nClass = StringToInt(GetScriptParam("UnLevel_ClassChoice"));
|
||||||
|
int nLevel = StringToInt(GetScriptParam("UnLevel_LevelChoice"));
|
||||||
|
if (nClass)
|
||||||
|
{
|
||||||
|
CheckAndRemoveSpellsForClassAtLevel(OBJECT_SELF, nClass, nLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,9 @@ SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_NECROMANCY);
|
|||||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||||
int nCasterLevel = PRCGetCasterLevel(OBJECT_SELF);
|
int nCasterLevel = PRCGetCasterLevel(OBJECT_SELF);
|
||||||
int nDuration = nCasterLevel;
|
int nDuration = nCasterLevel;
|
||||||
|
|
||||||
|
int bIsPC = GetIsPC(OBJECT_SELF);
|
||||||
|
|
||||||
nDuration = 24;
|
nDuration = 24;
|
||||||
string sResRef;
|
string sResRef;
|
||||||
//effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD);
|
//effect eVis = EffectVisualEffect(VFX_FNF_SUMMON_UNDEAD);
|
||||||
@@ -61,7 +64,7 @@ SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_NECROMANCY);
|
|||||||
effect eSummon = EffectSummonCreature(sResRef,VFX_FNF_SUMMON_UNDEAD);
|
effect eSummon = EffectSummonCreature(sResRef,VFX_FNF_SUMMON_UNDEAD);
|
||||||
//Apply summon effect and VFX impact.
|
//Apply summon effect and VFX impact.
|
||||||
MultisummonPreSummon();
|
MultisummonPreSummon();
|
||||||
if(GetPRCSwitch(PRC_CREATE_UNDEAD_UNCONTROLLED))
|
if(GetPRCSwitch(PRC_CREATE_UNDEAD_UNCONTROLLED) && bIsPC)
|
||||||
{
|
{
|
||||||
object oSummon = CreateObject(OBJECT_TYPE_CREATURE, sResRef, PRCGetSpellTargetLocation());
|
object oSummon = CreateObject(OBJECT_TYPE_CREATURE, sResRef, PRCGetSpellTargetLocation());
|
||||||
//make it hostile
|
//make it hostile
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_NECROMANCY);
|
|||||||
//Declare major variables
|
//Declare major variables
|
||||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||||
int nCasterLevel = PRCGetCasterLevel(OBJECT_SELF);
|
int nCasterLevel = PRCGetCasterLevel(OBJECT_SELF);
|
||||||
|
int bIsPC = GetIsPC(OBJECT_SELF);
|
||||||
int nDuration = nCasterLevel;
|
int nDuration = nCasterLevel;
|
||||||
nDuration = 24;
|
nDuration = 24;
|
||||||
string sResRef;
|
string sResRef;
|
||||||
@@ -62,7 +63,7 @@ SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_NECROMANCY);
|
|||||||
|
|
||||||
//Apply VFX impact and summon effect
|
//Apply VFX impact and summon effect
|
||||||
MultisummonPreSummon();
|
MultisummonPreSummon();
|
||||||
if(GetPRCSwitch(PRC_CREATE_UNDEAD_UNCONTROLLED))
|
if(GetPRCSwitch(PRC_CREATE_UNDEAD_UNCONTROLLED) && bIsPC)
|
||||||
{
|
{
|
||||||
object oSummon = CreateObject(OBJECT_TYPE_CREATURE, sResRef, PRCGetSpellTargetLocation());
|
object oSummon = CreateObject(OBJECT_TYPE_CREATURE, sResRef, PRCGetSpellTargetLocation());
|
||||||
//this is to
|
//this is to
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#include "prc_alterations"
|
#include "prc_alterations"
|
||||||
#include "inc_Timestop"
|
#include "inc_timestop"
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
object oTarget = GetExitingObject();
|
object oTarget = GetExitingObject();
|
||||||
|
|||||||
@@ -91,14 +91,15 @@ void main()
|
|||||||
{
|
{
|
||||||
nArmor = nLevel + 5;
|
nArmor = nLevel + 5;
|
||||||
DoCorruptionCost(oPC, ABILITY_STRENGTH, d2(1), 0);
|
DoCorruptionCost(oPC, ABILITY_STRENGTH, d2(1), 0);
|
||||||
|
SignalEvent(oTarget, EventSpellCastAt(oPC, nSpell));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(nSpell == SPELL_GREATER_LUMINOUS_ARMOR)
|
else if(nSpell == SPELL_GREATER_LUMINOUS_ARMOR)
|
||||||
{
|
{
|
||||||
nArmor = nLevel + 8;
|
nArmor = nLevel + 8;
|
||||||
DoCorruptionCost(oPC, ABILITY_STRENGTH, d3(), 0);
|
DoCorruptionCost(oPC, ABILITY_STRENGTH, d3(), 0);
|
||||||
|
SignalEvent(oTarget, EventSpellCastAt(oPC, nSpell));
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ int DoSpell(object oCaster, object oTarget, int nCasterLevel, int nEvent)
|
|||||||
int nDuration = nCasterLevel; // * Duration 1 turn/level
|
int nDuration = nCasterLevel; // * Duration 1 turn/level
|
||||||
if (CheckMetaMagic(nMetaMagic, METAMAGIC_EXTEND)) //Duration is +100%
|
if (CheckMetaMagic(nMetaMagic, METAMAGIC_EXTEND)) //Duration is +100%
|
||||||
nDuration *= 2;
|
nDuration *= 2;
|
||||||
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, 421, FALSE));
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_SHIELD_OF_FAITH, FALSE));
|
||||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_AC_BONUS), oTarget);
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_AC_BONUS), oTarget);
|
||||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(nDuration),TRUE,-1,nCasterLevel);
|
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, TurnsToSeconds(nDuration),TRUE,-1,nCasterLevel);
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -27156,7 +27156,14 @@ A marshal can haste himself and his allies for 1 round. This ability may be use
|
|||||||
|
|
||||||
Hit Die: d10
|
Hit Die: d10
|
||||||
Skill Points at Each Additional Level: 4+ Int Modifier
|
Skill Points at Each Additional Level: 4+ Int Modifier
|
||||||
Bonus Feats: The epic swashbuckler gains a bonus feat every three levels, starting at level 23 </entry>
|
Bonus Feats: The epic swashbuckler gains a bonus feat every three levels.
|
||||||
|
|
||||||
|
Special:
|
||||||
|
Swashbuckler Dodge: This bonus continues to increase by +1 at every five levels after 20th.
|
||||||
|
Grace: An epic swashbuckler gains another +1 bonus on Reflex saves at 29th and 39th level. A swashbuckler loses this bonus when wearing medium or heavy armor or when encumbered.
|
||||||
|
|
||||||
|
Epic Swashbuckler Bonus Feat List:
|
||||||
|
Armor Skin, Blinding Speed, Devastating Critical, Epic Damage Reduction, Epic Prowess, Epic Toughness, Epic Weapon Focus, Improved Stunning Fist, Improved Whirlwind Attack, Overwhelming Critical, Superior Initiative</entry>
|
||||||
<entry id="51045" lang="en" sex="m">Epic Marshal</entry>
|
<entry id="51045" lang="en" sex="m">Epic Marshal</entry>
|
||||||
<entry id="51046" lang="en" sex="m">An epic marshal commands legions of soldiers and sometimes rules his own nation.
|
<entry id="51046" lang="en" sex="m">An epic marshal commands legions of soldiers and sometimes rules his own nation.
|
||||||
His followers are loyal to the death, and his empire is the stuff of legend.
|
His followers are loyal to the death, and his empire is the stuff of legend.
|
||||||
@@ -46024,15 +46031,15 @@ Spell Resistance: No (harmless)
|
|||||||
Physical frailty is but a memory for the subject of this spell. The targeted creature is granted permanent immunity to poison and disease, regeneration +1, and a Constitution bonus of +5.</entry>
|
Physical frailty is but a memory for the subject of this spell. The targeted creature is granted permanent immunity to poison and disease, regeneration +1, and a Constitution bonus of +5.</entry>
|
||||||
<entry id="56299" lang="en" sex="m">Epic Spell: Twinfiend</entry>
|
<entry id="56299" lang="en" sex="m">Epic Spell: Twinfiend</entry>
|
||||||
<entry id="56300" lang="en" sex="m">Researched Epic Spell: Twinfiend</entry>
|
<entry id="56300" lang="en" sex="m">Researched Epic Spell: Twinfiend</entry>
|
||||||
<entry id="56301" lang="en" sex="m">School: Conjuration (Summoning)
|
<entry id="56301" lang="en" sex="m"> School: Conjuration (Summoning, Evil)
|
||||||
Components: V,S
|
Components: V,S
|
||||||
Range: Short
|
Range: Short
|
||||||
Effect: Two summoned pit fiends
|
Effect: Summons two advanced pit fiends
|
||||||
Duration: 20 rounds
|
Duration: 1 Turn / Caster level
|
||||||
Saving Throw: None
|
Saving Throw: None
|
||||||
Spell Resistance: No
|
Spell Resistance: No
|
||||||
|
|
||||||
You summon two pit fiends from the abyss to do your bidding. These devils follow your orders to the best of their abilities, for the duration.</entry>
|
You summon two advanced pit fiends from the Nine Hells to do your bidding. These devils recieve one bonus hit die for every 2 caster levels of the summoner and maximum hit points per die. The pit fiends follow your orders to the best of their abilities, for the duration of the spell.</entry>
|
||||||
<entry id="56302" lang="en" sex="m">Epic Spell: Unholy Disciple</entry>
|
<entry id="56302" lang="en" sex="m">Epic Spell: Unholy Disciple</entry>
|
||||||
<entry id="56303" lang="en" sex="m">Researched Epic Spell: Unholy Disciple</entry>
|
<entry id="56303" lang="en" sex="m">Researched Epic Spell: Unholy Disciple</entry>
|
||||||
<entry id="56304" lang="en" sex="m">School: Necromancy
|
<entry id="56304" lang="en" sex="m">School: Necromancy
|
||||||
@@ -73578,9 +73585,9 @@ Transmuting energy spreads out around the targets, dealing 4d8 points of damage
|
|||||||
<entry id="199260" lang="en" sex="m">Mass Inflict Critical Damage (15)</entry>
|
<entry id="199260" lang="en" sex="m">Mass Inflict Critical Damage (15)</entry>
|
||||||
<entry id="199261" lang="en" sex="m">Mass Inflict Critical Damage (20)</entry>
|
<entry id="199261" lang="en" sex="m">Mass Inflict Critical Damage (20)</entry>
|
||||||
<entry id="199262" lang="en" sex="m">****</entry>
|
<entry id="199262" lang="en" sex="m">****</entry>
|
||||||
<entry id="199263" lang="en" sex="m">****</entry>
|
<entry id="199263" lang="en" sex="m">Gaseous Form (5)</entry>
|
||||||
<entry id="199264" lang="en" sex="m">****</entry>
|
<entry id="199264" lang="en" sex="m">Gaseous Form (10)</entry>
|
||||||
<entry id="199265" lang="en" sex="m">****</entry>
|
<entry id="199265" lang="en" sex="m">Gaseous Form (15)</entry>
|
||||||
<entry id="199266" lang="en" sex="m">****</entry>
|
<entry id="199266" lang="en" sex="m">****</entry>
|
||||||
<entry id="199267" lang="en" sex="m">****</entry>
|
<entry id="199267" lang="en" sex="m">****</entry>
|
||||||
<entry id="199268" lang="en" sex="m">****</entry>
|
<entry id="199268" lang="en" sex="m">****</entry>
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user