2025/12/31 Update

Happy New Year!
Added Defensive Manifestation for psionics users.
Removed Talent from Grapple Combat Ability so AI wouldn't use it.
Charnel Touch is unlimited uses & shouldn't cause an AoO.
Switched Rain of Fire to use PRCEffectDamage().
Fixed issue where initiator couldn't take a maneuver in a 2nd sword magic class when having the prereq manuevers from a previous sword magic class.
Set Archetypal Form on Sphere of Ultimate Destruction.
Set Archetypal Form on Black Blade of Disaster.
Added missing immunities to Blighter's Undead WIldshape.
Removed incorrect prereq from Claw at the Moon's TLK entry.
Fixed pluralized Undead Wildshapes.
NPC death always cleans up a grapple.
This commit is contained in:
Jaysyn904
2025-12-31 22:09:21 -05:00
parent 33098fc061
commit 3fb5d61772
27 changed files with 6240 additions and 6053 deletions

View File

@@ -3025,6 +3025,7 @@ const int FEAT_SPLIT_PSIONIC_RAY = 4941;
const int FEAT_TWIN_POWER = 4942;
const int FEAT_WIDEN_POWER = 4943;
const int FEAT_QUICKEN_POWER = 4944;
const int FEAT_DEFENSIVE_MANIFESTATION = 2350;
// Sanctified Mind
const int FEAT_SANCMIND_PARTITION_MIND = 2231;

View File

@@ -2528,7 +2528,79 @@ int IsRequiredForOtherManeuvers(int nClass, int prereq, string discipline, objec
return FALSE;
}
int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_SELF)
int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_SELF)
{
string sFile = GetClassSpellbookFile(nClass);
int prereqs = StringToInt(Get2DACache(sFile, "Prereqs", spellbookId));
string discipline = Get2DACache(sFile, "Discipline", spellbookId);
// First check if this class is allowed to access this discipline
if (!IsAllowedDiscipline(nClass, spellbookId, oPC))
return FALSE;
// If no prerequisites required and class has access, allow it
if (!prereqs)
return TRUE;
// For maneuvers with prerequisites, count across all Blade Magic classes
json discInfo = GetDisciplineInfoObject(nClass, oPC);
json classDisc2Info = JsonObject();
json classDisc3Info = JsonObject();
if (nClass == CLASS_TYPE_SWORDSAGE)
{
if (GetLevelByClass(CLASS_TYPE_WARBLADE, oPC))
classDisc2Info = GetDisciplineInfoObject(CLASS_TYPE_WARBLADE, oPC);
if (GetLevelByClass(CLASS_TYPE_CRUSADER, oPC))
classDisc3Info = GetDisciplineInfoObject(CLASS_TYPE_CRUSADER, oPC);
}
if (nClass == CLASS_TYPE_CRUSADER)
{
if (GetLevelByClass(CLASS_TYPE_WARBLADE, oPC))
classDisc2Info = GetDisciplineInfoObject(CLASS_TYPE_WARBLADE, oPC);
if (GetLevelByClass(CLASS_TYPE_SWORDSAGE, oPC))
classDisc3Info = GetDisciplineInfoObject(CLASS_TYPE_SWORDSAGE, oPC);
}
if (nClass == CLASS_TYPE_WARBLADE)
{
if (GetLevelByClass(CLASS_TYPE_CRUSADER, oPC))
classDisc2Info = GetDisciplineInfoObject(CLASS_TYPE_CRUSADER, oPC);
if (GetLevelByClass(CLASS_TYPE_SWORDSAGE, oPC))
classDisc3Info = GetDisciplineInfoObject(CLASS_TYPE_SWORDSAGE, oPC);
}
// Sum up maneuver counts from all classes for this discipline
int nManCount = 0;
// Check primary class
json chosenDisc = JsonObjectGet(discInfo, discipline);
if (chosenDisc != JsonNull())
{
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE)));
}
// Check second class
chosenDisc = JsonObjectGet(classDisc2Info, discipline);
if (chosenDisc != JsonNull())
{
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE)));
}
// Check third class
chosenDisc = JsonObjectGet(classDisc3Info, discipline);
if (chosenDisc != JsonNull())
{
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)));
nManCount += JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE)));
}
// Check if we have enough maneuvers for the prerequisite
return nManCount >= prereqs;
}
/* int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_SELF)
{
string sFile = GetClassSpellbookFile(nClass);
int prereqs = StringToInt(Get2DACache(sFile, "Prereqs", spellbookId));
@@ -2546,7 +2618,7 @@ int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_S
}
return FALSE;
}
} */
int GetMaxInitiatorCircle(int nClass, object oPC=OBJECT_SELF)
{

View File

@@ -443,6 +443,8 @@ struct manifestation{
int bWiden;
/// Whether Quicken Power was used with this manifestation
int bQuicken;
//:: Whether Defensive Manifesation was used with this manifestation
int bDefensive;
};
//////////////////////////////////////////////////

View File

@@ -819,6 +819,25 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
// Psionic focus loss from using metapsionics. Has a side effect of telling the manifester which metapsionics were actually active
PayMetapsionicsFocuses(manif);
}
if(GetLocalInt(oManifester, "PRC_DefensiveManifestActive"))
{
// Concentration check (DC 15 + power level)
int nPowerLevel = GetPowerLevel(oManifester);
int nDC = 15 + nPowerLevel;
if(!GetPRCIsSkillSuccessful(oManifester, SKILL_CONCENTRATION, nDC))
{
// Failed - PP already deducted, but prevent manifestation
manif.bCanManifest = FALSE;
SendMessageToPC(oManifester, "Defensive manifestion concentration check failed.");
return manif;
}
// Set defensive flag for any other systems that need it
SendMessageToPC(oManifester, "Defensive manifestion concentration check successful.");
manif.bDefensive = TRUE;
}
//* APPLY SIDE-EFFECTS THAT RESULT FROM SUCCESSFULL MANIFESTATION HERE *//
// Psicraft for all those who can see

View File

@@ -1,3 +1,6 @@
const int DEFENSIVE_MANIFESTATION = 2375;
//real power spell constants
// Level 1 Powers