forked from Jaysyn/PRC8
2025/11/20 Update
Updated epic swashbucker tlk. Added notes on Martial Study. Updated Shadow Servant to scale with Shadow Master level, per PnP. Made Disciple of Baalzebul's CHA boost intrinsic. Swarm of Arrows is an Eldritch Knight epic bonus feat. Epic eldritch theurge is 11th level, not 21st level. Updated Shadowdancer weapon proficiencies. WP: Scythe was a usable feat for Warblade. Gaseous Form added to iprp_spells. Set Favoured Soul's Regen X Wounds spells to the correct spell level. Updated Twinfiend to not suck. Tweaked GetMaxPossibleHP for Undead & Constructs. Updated PRCIsFlying() for newer CEP2 wings. More fixes and updated for NUI levelup menu. (@Rakiov) Added support for de-leveling AMS classes (@Rakiov) Zakya Rakshasa have a claw & bite attack. Added check to end grapples after target death. Removed debug message in GetHighestSpellAvailableByDescriptor() Monsters won't summon uncontrolled undead. Added Signal Event to Luminous Armor. Corrected Signal Event on Shield of Faith.
This commit is contained in:
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.
@@ -1,168 +0,0 @@
|
||||
//::////////////////////////////////////////////////////////
|
||||
//:: ;-. ,-. ,-. ,-.
|
||||
//:: | ) | ) / ( )
|
||||
//:: |-' |-< | ;-:
|
||||
//:: | | \ \ ( )
|
||||
//:: ' ' ' `-' `-'
|
||||
//::///////////////////////////////////////////////////////
|
||||
//::
|
||||
/*
|
||||
Impactscript for Shadow Servant.
|
||||
(this is handled in the Familiar script)
|
||||
|
||||
Shadow Servant (Su): At 1st level, your shadow familiar permanently
|
||||
transforms into a Medium shadow elemental. It loses all familiar
|
||||
traits, but gains new abilities as your shadow servant.
|
||||
|
||||
Should your shadow servant die, you can summon a replacement after
|
||||
24 hours pass. Your shadow servant cannot travel farther from you
|
||||
than 30 feet + 10 feet for each of your master of shadow levels
|
||||
(40 feet at 1st level and a maximum of 130 feet at 10th level). If
|
||||
it is forcibly separated from you by more than this distance, the
|
||||
servant dissipates instantly, and you must wait 24 hours to summon
|
||||
a new one.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Script: mshadw_shadserv.nss
|
||||
//:: Author: Jaysyn
|
||||
//:: Created: 2025-11-11 19:25:58
|
||||
//:://////////////////////////////////////////////
|
||||
#include "prc_inc_json"
|
||||
#include "prc_inc_spells"
|
||||
|
||||
const string SHADOW_SERVANT_RESREF = "prc_shadow_serv";
|
||||
|
||||
// Watch function: despawns Shadow Servant if master is dead or out of range
|
||||
void ShadowServantWatch(object oShadow, object oPC)
|
||||
{
|
||||
if(DEBUG) DoDebug("mshadw_shadserv >> ShadowServantWatch: Starting function.");
|
||||
|
||||
int nMaster = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
|
||||
|
||||
float fRange = 30.0 + (nMaster * 10);
|
||||
|
||||
if (!GetIsObjectValid(oShadow) || !GetIsObjectValid(oPC)) return;
|
||||
|
||||
if (GetIsDead(oPC) ||
|
||||
GetDistanceBetween(oShadow, oPC) > FeetToMeters(fRange))
|
||||
{
|
||||
DestroyObject(oShadow);
|
||||
return;
|
||||
}
|
||||
|
||||
DelayCommand(1.0, ShadowServantWatch(oShadow, oPC));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
|
||||
int nMaster = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
|
||||
|
||||
int nDexBonus = (nMaster >= 5 && (nMaster % 2)) ? (nMaster - 3) : 0;
|
||||
|
||||
float fRange = 30.0 + (nMaster * 10);
|
||||
|
||||
// Target location
|
||||
location lTarget = GetSpellTargetLocation();
|
||||
|
||||
// Distance check
|
||||
if (GetDistanceBetweenLocations(GetLocation(oPC), lTarget) > FeetToMeters(fRange))
|
||||
{
|
||||
SendMessageToPC(oPC, "That location is too far away.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Load template
|
||||
json jShadow = TemplateToJson(SHADOW_SERVANT_RESREF, RESTYPE_UTC);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: TemplateToJson failed <20> bad resref or resource missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Original HD
|
||||
int nOriginalHD = json_GetCreatureHD(jShadow);
|
||||
if (nOriginalHD <= 0)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_GetCreatureHD failed <20> template missing HD data.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Add Hit Dice
|
||||
int nHDToAdd = nMaster -1;
|
||||
|
||||
if (nHDToAdd < 0) nHDToAdd = 0;
|
||||
|
||||
jShadow = json_AddHitDice(jShadow, nHDToAdd);
|
||||
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AddHitDice failed - JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Update feats
|
||||
jShadow = json_AddFeatsFromCreatureVars(jShadow, nOriginalHD);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AddFeatsFromCreatureVars failed <20> JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Update stats
|
||||
jShadow = json_ApplyAbilityBoostFromHD(jShadow, nOriginalHD);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_ApplyAbilityBoostFromHD failed <20> JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Bonus DEX from Shadow Servant class ability
|
||||
jShadow = json_UpdateTemplateStats(jShadow, 0, nDexBonus);
|
||||
|
||||
// Size increase
|
||||
if (nMaster > 2)
|
||||
{
|
||||
jShadow = json_AdjustCreatureSize(jShadow, 1, TRUE);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AdjustCreatureSize failed - JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
object oShadow = JsonToObject(jShadow, lTarget);
|
||||
effect eSummon = ExtraordinaryEffect(EffectSummonCreature("", VFX_FNF_SUMMON_UNDEAD, 0.0, 0, VFX_IMP_UNSUMMON, oShadow));
|
||||
|
||||
ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eSummon, lTarget);
|
||||
|
||||
if (!GetIsObjectValid(oShadow))
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: JsonToObject failed - could not create creature from edited template.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set faction to caster<65>s
|
||||
ChangeFaction(oShadow, oPC);
|
||||
SetLocalObject(oShadow, "ANIMATOR", oPC);
|
||||
|
||||
SetCurrentHitPoints(oShadow, GetMaxPossibleHP(oShadow));
|
||||
|
||||
effect eGhost = EffectVisualEffect(VFX_DUR_GHOST_TRANSPARENT);
|
||||
eGhost = UnyieldingEffect(eGhost);
|
||||
|
||||
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
|
||||
DelayCommand(6.1, ShadowServantWatch(oShadow, oPC));
|
||||
}
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user