2 Commits
v4.79 ... main

Author SHA1 Message Date
Jaysyn904
11a75d23c9 2026/01/12 Update
Gated DEBUG text in unarmed_caller.nss
Added feat constants for the Combat Focus line of feats.
Fixed & tested Fey + PrC spellcasting durations and the caster level returned for templates.
2026-01-12 12:09:37 -05:00
Jaysyn904
a192bca40e 2026/01/11 Update
Updated PRC8 version.
Added EffectIcon for EFFECT_ICON_FATIGUE to PRCEffectFatigue.
Fixed Midnight Augmentation to display all known powers as well as display radial powers.
Draconic Senses now grants all of the abilities that it should. (Lowlight Vision, Darkvision, Ultravision).
2026-01-11 20:41:16 -05:00
9 changed files with 133 additions and 55 deletions

View File

@@ -498,6 +498,7 @@ effect EffectFatigue(){
effect eReturn = EffectAbilityDecrease(ABILITY_STRENGTH, 2); effect eReturn = EffectAbilityDecrease(ABILITY_STRENGTH, 2);
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_DEXTERITY, 2)); eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_DEXTERITY, 2));
eReturn = EffectLinkEffects(eReturn, EffectMovementSpeedDecrease(25)); eReturn = EffectLinkEffects(eReturn, EffectMovementSpeedDecrease(25));
eReturn = EffectLinkEffects(eReturn, EffectIcon(EFFECT_ICON_FATIGUE));
eReturn = TagEffect(eReturn, "PRCFatigue"); eReturn = TagEffect(eReturn, "PRCFatigue");
return eReturn; return eReturn;
} }

View File

@@ -6336,6 +6336,13 @@ const int FEAT_HIDDEN_TALENT_THICKSKIN = 25944;
const int FEAT_HIDDEN_TALENT_VIGOR = 25945; const int FEAT_HIDDEN_TALENT_VIGOR = 25945;
const int FEAT_HIDDEN_TALENT_GRIP_IRON = 25946; const int FEAT_HIDDEN_TALENT_GRIP_IRON = 25946;
//:: Player's Handbook II feats
const int FEAT_COMBAT_FOCUS = -9999;
const int FEAT_COMBAT_STABILITY = -9998;
const int FEAT_COMBAT_DEFENSE = -9997;
const int FEAT_COMBAT_VIGOR = -9996;
const int FEAT_COMBAT_AWARENESS = -9995;
const int FEAT_COMBAT_STRIKE = -9994;

View File

@@ -797,6 +797,7 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if (nCastingClass == CLASS_TYPE_BARD || GetLevelByClass(CLASS_TYPE_BARD, oCaster)) if (nCastingClass == CLASS_TYPE_BARD || GetLevelByClass(CLASS_TYPE_BARD, oCaster))
{ {
//:: Includes RHD as bard. If they started with bard levels, then it //:: Includes RHD as bard. If they started with bard levels, then it
//:: counts as a prestige class, otherwise RHD is used instead of bard levels. //:: counts as a prestige class, otherwise RHD is used instead of bard levels.
if(nRace == RACIAL_TYPE_GLOURA) if(nRace == RACIAL_TYPE_GLOURA)
@@ -904,9 +905,13 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_UNSEEN_SPELLCASTING_BARD, oCaster)) if(GetHasFeat(FEAT_UNSEEN_SPELLCASTING_BARD, oCaster))
nArcane += GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oCaster); nArcane += GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oCaster);
if(GetHasFeat(FEAT_VIRTUOSO_SPELLCASTING_BARD, oCaster)) // if(GetHasFeat(FEAT_VIRTUOSO_SPELLCASTING_BARD, oCaster))
// nArcane += GetLevelByClass(CLASS_TYPE_VIRTUOSO, oCaster);
if(GetHasFeat(FEAT_VIRTUOSO_SPELLCASTING_BARD, oCaster)
&& !(GetRacialType(oCaster) == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster)))
nArcane += GetLevelByClass(CLASS_TYPE_VIRTUOSO, oCaster); nArcane += GetLevelByClass(CLASS_TYPE_VIRTUOSO, oCaster);
if(GetHasFeat(FEAT_WWOC_SPELLCASTING_BARD, oCaster)) if(GetHasFeat(FEAT_WWOC_SPELLCASTING_BARD, oCaster))
nArcane += GetLevelByClass(CLASS_TYPE_WAR_WIZARD_OF_CORMYR, oCaster); nArcane += GetLevelByClass(CLASS_TYPE_WAR_WIZARD_OF_CORMYR, oCaster);
@@ -960,7 +965,8 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
} }
//:: End Bard Arcane PrC casting calculations //:: End Bard Arcane PrC casting calculations
if(nCastingClass == CLASS_TYPE_BARD || nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster)) //if(nCastingClass == CLASS_TYPE_BARD || nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
if((nCastingClass == CLASS_TYPE_FEY || nCastingClass == CLASS_TYPE_BARD) && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
{ {
if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey RHD caster (not bard)"); if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey RHD caster (not bard)");

View File

@@ -417,7 +417,10 @@ int GetPrCAdjustedClassLevel(int nClass, object oCaster = OBJECT_SELF)
// is it arcane, divine or neither? // is it arcane, divine or neither?
if(GetIsArcaneClass(nClass, oCaster) && nClass != CLASS_TYPE_SUBLIME_CHORD) if(GetIsArcaneClass(nClass, oCaster) && nClass != CLASS_TYPE_SUBLIME_CHORD)
{ {
if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs if(nClass == CLASS_TYPE_FEY && GetRacialType(oCaster) == RACIAL_TYPE_GLOURA)
iTemp = GetArcanePRCLevels(oCaster, nClass);
else if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
iTemp = GetArcanePRCLevels(oCaster, nClass); iTemp = GetArcanePRCLevels(oCaster, nClass);
} }
else if(GetIsDivineClass(nClass, oCaster)) else if(GetIsDivineClass(nClass, oCaster))

View File

@@ -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.79"; const string PRC_VERSION = "PRC8 4.80";
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */ /* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */

View File

@@ -29,7 +29,7 @@
*/ */
//::////////////////////////////////////////////// //:://////////////////////////////////////////////
//::////////////////////////////////////////////// //:://////////////////////////////////////////////
#include "prc_inc_spells"
////////////////////////////////////////////////// //////////////////////////////////////////////////
/* Constants */ /* Constants */
////////////////////////////////////////////////// //////////////////////////////////////////////////
@@ -572,6 +572,22 @@ int GetMaxPowerCount(object oCreature, int nList)
int GetHasPower(int nPower, object oCreature = OBJECT_SELF) int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
{ {
// Debug output
if (DEBUG) DoDebug("GetHasPower: Checking power " + IntToString(nPower));
// Check if it's a subradial spell first
if (GetIsSubradialSpell(nPower))
{
if(DEBUG) DoDebug("GetHasPower: " + IntToString(nPower) + " is a subradial");
int nMasterSpell = GetMasterSpellFromSubradial(nPower);
if (nMasterSpell != -1)
{
if(DEBUG) DoDebug("GetHasPower: Master spell is " + IntToString(nMasterSpell));
nPower = nMasterSpell;
}
}
// Check MISC list first (for Hidden Talent and similar feats) // Check MISC list first (for Hidden Talent and similar feats)
if(GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_INVALID), oCreature)) if(GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_INVALID), oCreature))
return TRUE; return TRUE;
@@ -597,6 +613,7 @@ int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
// add new psionic classes here // add new psionic classes here
) )
return TRUE; return TRUE;
return FALSE; return FALSE;
} }

View File

@@ -166,24 +166,37 @@ void main()
string sFeatID; string sFeatID;
int added = 0; int added = 0;
for(i = 14001; i < 14260 ; i++) for(i = 14001; i < 14351 ; i++)
{ {
// Skip blank IDs between 14266 and 14329
if(i >= 14266 && i < 14330)
continue;
nPowerLevel = StringToInt(Get2DACache("spells", "Innate", i)); nPowerLevel = StringToInt(Get2DACache("spells", "Innate", i));
if(nPowerLevel > nMaxLevel) if(nPowerLevel > nMaxLevel)
break; continue;
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", i))); string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", i)));
if(sName != "") // Check if it's a regular power or a subradial
int bHasPower = GetHasPower(i, oMeldshaper);
if (!bHasPower && GetIsSubradialSpell(i))
{ {
if (GetHasPower(i, oMeldshaper)) // For subradials, check if they know the master spell
int nMasterSpell = GetMasterSpellFromSubradial(i);
if (nMasterSpell != -1)
{
bHasPower = GetHasPower(nMasterSpell, oMeldshaper);
}
}
if (bHasPower)
{ {
if(SORT) AddToTempList(oMeldshaper, sName, i); if(SORT) AddToTempList(oMeldshaper, sName, i);
else AddChoice(sName, i, oMeldshaper); else AddChoice(sName, i, oMeldshaper);
added++; added++;
} }
} }
}
if(SORT) if(SORT)
{ {

View File

@@ -288,15 +288,43 @@ void main()
///////////////////////////Draconic Senses////////////////////////// ///////////////////////////Draconic Senses//////////////////////////
if(GetHasFeat(FEAT_DRACONIC_SENSES, oPC)) if(GetHasFeat(FEAT_DRACONIC_SENSES, oPC))
{ {
effect eLow = EffectBonusFeat(FEAT_DARKVISION);
effect eDark = EffectBonusFeat(FEAT_LOWLIGHTVISION);
//effect eUltra = EffectUltravision();
effect eUltra = EffectBonusFeat(FEAT_ULTRAVISION);
effect eLink;
if(DEBUG) DoDebug("Entering Draconic Senses Branch. nPower is: "+IntToString(nPower)+".");
switch(nPower) switch(nPower)
{ {
case 1: IPSafeAddItemProperty(oSkin, ItemPropertyBonusFeat(IP_CONST_FEAT_LOWLIGHT_VISION), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); break; case 1:
case 2: IPSafeAddItemProperty(oSkin, ItemPropertyBonusFeat(IP_CONST_FEAT_LOWLIGHT_VISION), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); break; case 2:
case 3: IPSafeAddItemProperty(oSkin, ItemPropertyDarkvision(), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); break; {
//Using Ultravision as the ability is Blindsense, not Blindsight if(DEBUG) DoDebug("Draconic Senses Branch Case 1 & 2: Lowlight vision");
default: IPSafeAddItemProperty(oSkin, ItemPropertyDarkvision(), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); //IPSafeAddItemProperty(oSkin, ItemPropertyBonusFeat(IP_CONST_FEAT_LOWLIGHT_VISION), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); break;
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ExtraordinaryEffect(EffectUltravision()), oPC); break; SPApplyEffectToObject(DURATION_TYPE_PERMANENT, UnyieldingEffect(eLow), oPC);
break;
} }
case 3:
{
if(DEBUG) DoDebug("Draconic Senses Branch Case 3: Lowlight vision + Darkvision");
//IPSafeAddItemProperty(oSkin, ItemPropertyDarkvision(), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); break;
eLink = EffectLinkEffects(eLow, eDark);
SPApplyEffectToObject(DURATION_TYPE_PERMANENT, UnyieldingEffect(eLink), oPC);
break;
}
//;: Using Ultravision as the ability is Blindsense, not Blindsight
default:
{
if(DEBUG) DoDebug("Draconic Senses Branch Default: Lowlight vision + Darkvision + Ultravsion");
//IPSafeAddItemProperty(oSkin, ItemPropertyDarkvision(), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
eLink = EffectLinkEffects(eLow, eDark);
eLink = EffectLinkEffects(eUltra, eLink);
SPApplyEffectToObject(DURATION_TYPE_PERMANENT, UnyieldingEffect(eLink), oPC);
break;
}
}
if(DEBUG) DoDebug("Draconic Senses: Adding skill bonuses.");
SetCompositeBonus(oSkin, "DS_Spot", nPower, ITEM_PROPERTY_SKILL_BONUS, SKILL_SPOT); SetCompositeBonus(oSkin, "DS_Spot", nPower, ITEM_PROPERTY_SKILL_BONUS, SKILL_SPOT);
SetCompositeBonus(oSkin, "DS_Search", nPower, ITEM_PROPERTY_SKILL_BONUS, SKILL_SEARCH); SetCompositeBonus(oSkin, "DS_Search", nPower, ITEM_PROPERTY_SKILL_BONUS, SKILL_SEARCH);
SetCompositeBonus(oSkin, "DS_Listen", nPower, ITEM_PROPERTY_SKILL_BONUS, SKILL_LISTEN); SetCompositeBonus(oSkin, "DS_Listen", nPower, ITEM_PROPERTY_SKILL_BONUS, SKILL_LISTEN);

View File

@@ -17,20 +17,23 @@
void main() void main()
{ {
if (DEBUG)
{
DoDebug("unarmed_caller: FUNCTION STARTED"); DoDebug("unarmed_caller: FUNCTION STARTED");
DoDebug("unarmed_caller: CALL_UNARMED_FEATS = " + IntToString(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FEATS))); DoDebug("unarmed_caller: CALL_UNARMED_FEATS = " + IntToString(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FEATS)));
DoDebug("unarmed_caller: CALL_UNARMED_FISTS = " + IntToString(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FISTS))); DoDebug("unarmed_caller: CALL_UNARMED_FISTS = " + IntToString(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FISTS)));
}
int bCont = FALSE; int bCont = FALSE;
if(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FEATS)) if(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FEATS))
{ {
DoDebug("unarmed_caller: CALLING UnarmedFeats"); if (DEBUG) DoDebug("unarmed_caller: CALLING UnarmedFeats");
UnarmedFeats(OBJECT_SELF); UnarmedFeats(OBJECT_SELF);
bCont = TRUE; bCont = TRUE;
} }
if(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FISTS)) if(GetLocalInt(OBJECT_SELF, CALL_UNARMED_FISTS))
{ {
DoDebug("unarmed_caller: CALLING UnarmedFists"); if (DEBUG) DoDebug("unarmed_caller: CALLING UnarmedFists");
UnarmedFists(OBJECT_SELF); UnarmedFists(OBJECT_SELF);
bCont = TRUE; bCont = TRUE;
} }