Files
PRC8/nwn/nwnprc/trunk/include/prc_inc_factotum.nss
Jaysyn904 3b6c74985e 2025/12/03 Update
Finished Hidden Talent.
Tweaked Factotum abilities to hopefully not run out of uses.
Tweaked Twinfiends skill function.
Hopefully fixed the Factotum's Inspiration not generating issues.
Hopefullly fixed Double Chakra bind.
Hopefully fixed Totemist's Double Totem Bind.
Hopefully fixed Girallon Arms.
Fixed Kuthrik Claws not granting Weapon Finesse.
Added missing medium centaur hoof slam uti.
Added new tentacle slam creature weapon (works the same, looks better).
Updated Spell Effect NUI to ignore system spells (@Rakiov).
Fixed typo in Guided Strike.
2025-12-03 15:33:47 -05:00

283 lines
9.2 KiB
Plaintext

/*
* Factotum general functions handling.
*
* @author Stratovarius - 2019.12.21
*/
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
/**
* Stores SpellIds for Arcane Dilettante
*
* @param oPC PC to target
* @param nSpell SpellID to store
*/
void PrepareArcDilSpell(object oPC, int nSpell);
/**
* Returns TRUE if there are more spells to learn
*
* @param oPC PC to target
*/
void PrepareArcDilSpell(object oPC, int nSpell);
//////////////////////////////////////////////////
/* Constants */
//////////////////////////////////////////////////
const int FACTOTUM_SLOT_1 = 3887;
const int FACTOTUM_SLOT_2 = 3888;
const int FACTOTUM_SLOT_3 = 3889;
const int FACTOTUM_SLOT_4 = 3890;
const int FACTOTUM_SLOT_5 = 3891;
const int FACTOTUM_SLOT_6 = 3892;
const int FACTOTUM_SLOT_7 = 3893;
const int FACTOTUM_SLOT_8 = 3894;
const int BRILLIANCE_SLOT_1 = 3917;
const int BRILLIANCE_SLOT_2 = 3918;
const int BRILLIANCE_SLOT_3 = 3919;
//////////////////////////////////////////////////
/* Include section */
//////////////////////////////////////////////////
#include "prc_inc_function"
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
void PrepareArcDilSpell(object oPC, int nSpell)
{
if (DEBUG) DoDebug("PrepareArcDilSpell "+IntToString(nSpell));
int nClass = GetLevelByClass(CLASS_TYPE_FACTOTUM, oPC);
// Done like this because you can only have a certain amount at a given level
if (!GetLocalInt(oPC, "ArcDilSpell1") && nClass >= 2) SetLocalInt(oPC, "ArcDilSpell1", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell2") && nClass >= 4) SetLocalInt(oPC, "ArcDilSpell2", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell3") && nClass >= 7) SetLocalInt(oPC, "ArcDilSpell3", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell4") && nClass >= 9) SetLocalInt(oPC, "ArcDilSpell4", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell5") && nClass >= 12) SetLocalInt(oPC, "ArcDilSpell5", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell6") && nClass >= 14) SetLocalInt(oPC, "ArcDilSpell6", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell7") && nClass >= 17) SetLocalInt(oPC, "ArcDilSpell7", nSpell);
else if (!GetLocalInt(oPC, "ArcDilSpell8") && nClass >= 20) SetLocalInt(oPC, "ArcDilSpell8", nSpell);
}
int GetMaxLearnedArcDil(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_FACTOTUM, oPC);
int nCount, nMax;
if (GetLocalInt(oPC, "ArcDilSpell1")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell2")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell3")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell4")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell5")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell6")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell7")) nCount++;
if (GetLocalInt(oPC, "ArcDilSpell8")) nCount++;
if(nClass >= 2) nMax++;
if(nClass >= 4) nMax++;
if(nClass >= 7) nMax++;
if(nClass >= 9) nMax++;
if(nClass >= 12) nMax++;
if(nClass >= 14) nMax++;
if(nClass >= 17) nMax++;
if(nClass >= 20) nMax++;
int nReturn = FALSE;
if (nMax > nCount) nReturn = TRUE;
return nReturn;
}
int GetFactotumSlot(object oPC)
{
int nSlot = PRCGetSpellId();
if (nSlot == FACTOTUM_SLOT_1) return GetLocalInt(oPC, "ArcDilSpell1");
if (nSlot == FACTOTUM_SLOT_2) return GetLocalInt(oPC, "ArcDilSpell2");
if (nSlot == FACTOTUM_SLOT_3) return GetLocalInt(oPC, "ArcDilSpell3");
if (nSlot == FACTOTUM_SLOT_4) return GetLocalInt(oPC, "ArcDilSpell4");
if (nSlot == FACTOTUM_SLOT_5) return GetLocalInt(oPC, "ArcDilSpell5");
if (nSlot == FACTOTUM_SLOT_6) return GetLocalInt(oPC, "ArcDilSpell6");
if (nSlot == FACTOTUM_SLOT_7) return GetLocalInt(oPC, "ArcDilSpell7");
if (nSlot == FACTOTUM_SLOT_8) return GetLocalInt(oPC, "ArcDilSpell8");
if (nSlot == BRILLIANCE_SLOT_1) return GetLocalInt(oPC, "CunningAbility1");
if (nSlot == BRILLIANCE_SLOT_2) return GetLocalInt(oPC, "CunningAbility2");
if (nSlot == BRILLIANCE_SLOT_3) return GetLocalInt(oPC, "CunningAbility3");
return -1;
}
void CheckFactotumSlots(object oPC)
{
int i;
for (i = 1; i <= 8; i++)
{
string sSpell = "ArcDilSpell";
int nSpell = GetLocalInt(oPC, sSpell+IntToString(i));
sSpell = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpell)));
if (nSpell > 0) FloatingTextStringOnCreature("Arcane Dilettante Slot "+IntToString(i)+" is "+sSpell, oPC, FALSE);
}
}
void CheckBrillianceSlots(object oPC)
{
int i;
for (i = 1; i <= 3; i++)
{
string sSpell = "CunningAbility";
int nSpell = GetLocalInt(oPC, sSpell+IntToString(i));
sSpell = GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", nSpell)));
if (nSpell > 0) FloatingTextStringOnCreature("Cunning Brilliance Slot "+IntToString(i)+" is "+sSpell, oPC, FALSE);
}
}
void ClearFactotumSlots(object oPC)
{
int i;
for (i = 1; i <= 50; i++)
{
DeleteLocalInt(oPC, "ArcDilSpell"+IntToString(i));
DeleteLocalInt(oPC, "CunningKnowledge"+IntToString(i));
DeleteLocalInt(oPC, "CunningAbility"+IntToString(i));
}
DeleteLocalInt(oPC, "CunningBrillianceCount");
DeleteLocalInt(oPC, "CunningBrilliance");
}
int GetMaxArcDilSpellLevel(object oPC)
{
int nClass = GetLevelByClass(CLASS_TYPE_FACTOTUM, oPC);
int nMax = -1;
if(nClass >= 18) nMax = 7;
else if(nClass >= 15) nMax = 6;
else if(nClass >= 13) nMax = 5;
else if(nClass >= 10) nMax = 4;
else if(nClass >= 8) nMax = 3;
else if(nClass >= 5) nMax = 2;
else if(nClass >= 3) nMax = 1;
else if(nClass >= 2) nMax = 0;
if (DEBUG) DoDebug("GetMaxArcDilSpellLevel "+IntToString(nMax));
return nMax;
}
void SetInspiration(object oPC)
{
int nInspiration = 2;
int nClass = GetLevelByClass(CLASS_TYPE_FACTOTUM, oPC);
if(nClass >= 20) nInspiration = 10;
else if(nClass >= 17) nInspiration = 8;
else if(nClass >= 14) nInspiration = 7;
else if(nClass >= 11) nInspiration = 6;
else if(nClass >= 8) nInspiration = 5;
else if(nClass >= 5) nInspiration = 4;
else if(nClass >= 2) nInspiration = 3;
int i, nFont;
for(i = FEAT_FONT_INSPIRATION_1; i <= FEAT_FONT_INSPIRATION_10; i++)
if(GetHasFeat(i, oPC)) nFont++;
//nInspiration += nFont * (1 + nFont + 1) / 2;
nInspiration += nFont * (nFont + 1) / 2;
SetLocalInt(oPC, "InspirationPool", nInspiration);
FloatingTextStringOnCreature("Encounter begins with "+IntToString(nInspiration)+" inspiration", oPC, FALSE);
}
void ClearInspiration(object oPC)
{
DeleteLocalInt(oPC, "InspirationPool");
FloatingTextStringOnCreature("Encounter ends, inspiration lost", oPC, FALSE);
}
int ExpendInspiration(object oPC, int nCost)
{
if (nCost <= 0) return FALSE;
int nInspiration = GetLocalInt(oPC, "InspirationPool");
if (nInspiration >= nCost)
{
SetLocalInt(oPC, "InspirationPool", nInspiration-nCost);
FloatingTextStringOnCreature("You have "+IntToString(nInspiration-nCost)+" inspiration remaining this encounter", oPC, FALSE);
return TRUE;
}
FloatingTextStringOnCreature("You do not have enough inspiration", oPC, FALSE);
return FALSE;
}
void MarkAbilitySaved(object oPC, int nAbil)
{
if (DEBUG) DoDebug("MarkAbilitySaved nAbil is "+IntToString(nAbil));
if (!GetLocalInt(oPC, "CunningAbility1")) SetLocalInt(oPC, "CunningAbility1", nAbil);
else if (!GetLocalInt(oPC, "CunningAbility2")) SetLocalInt(oPC, "CunningAbility2", nAbil);
else if (!GetLocalInt(oPC, "CunningAbility3")) SetLocalInt(oPC, "CunningAbility3", nAbil);
}
int GetIsAbilitySaved(object oPC, int nAbil)
{
int i, nCount, nTest;
for (i = 0; i <= 3; i++)
{
nTest = GetLocalInt(oPC, "CunningAbility"+IntToString(i));
if (nTest == nAbil)
nCount = TRUE;
}
if (DEBUG) DoDebug("GetIsAbilitySaved is "+IntToString(nCount));
return nCount;
}
void FactotumTriggerAbil(object oPC, int nAbil)
{
object oSkin = GetPCSkin(oPC);
itemproperty ipIP;
if (nAbil == FEAT_BARBARIAN_RAGE)
ExecuteScript("NW_S1_BarbRage", oPC);
else if (nAbil == FEAT_BARBARIAN_ENDURANCE)
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_BarbEndurance);
else if (nAbil == FEAT_SNEAK_ATTACK)
{
SetLocalInt(oPC, "FactotumSneak", TRUE);
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oPC));
DelayCommand(59.9, DeleteLocalInt(oPC, "FactotumSneak"));
DelayCommand(60.0, ExecuteScript("prc_sneak_att", oPC));
}
else if (nAbil == 3665) // Mettle
{
SetLocalInt(oPC, "FactotumMettle", TRUE);
DelayCommand(60.0, DeleteLocalInt(oPC, "FactotumMettle"));
}
else if (nAbil == FEAT_CRUSADER_SMITE)
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_CRUSADER_SMITE);
IPSafeAddItemProperty(oSkin, ipIP, 60.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
/*void AddCunningBrillianceAbility(object oPC, int nAbil)
{
if (DEBUG) DoDebug("AddCunningBrillianceAbility "+IntToString(nAbil));
object oSkin = GetPCSkin(oPC);
itemproperty ipIP;
if (nAbil == FEAT_BARBARIAN_ENDURANCE)
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_BarbEndurance);
else if (nAbil == FEAT_BARBARIAN_RAGE)
ipIP = PRCItemPropertyBonusFeat(IP_CONST_FEAT_RAGE);
IPSafeAddItemProperty(oSkin, ipIP, 9999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
MarkAbilitySaved(oPC, nAbil);
}
*/