2026/02/22 Update

Added scripting for Combat Form feats: Combat Focus, Combat Awareness, Combat Stability, Combat Defense, Combat Vitality & Combat Strike.
Updated fighter bonus feat lists for Champion of Torm, Dragon Devotee, Eldritch Knight, Fighter, Hospitaler, Psychic Warrior, Serene Guardian, Spellsword and Warblade.
This commit is contained in:
Jaysyn904
2026-02-22 13:06:52 -05:00
parent 73ce19db22
commit 783f0ddac4
71 changed files with 48853 additions and 48188 deletions

View File

@@ -0,0 +1,83 @@
//:://////////////////////////////////////////////////////////////////
//:: ;-. ,-. ,-. ,-.
//:: | ) | ) / ( )
//:: |-' |-< | ;-:
//:: | | \ \ ( )
//:: ' ' ' `-' `-'
//:://////////////////////////////////////////////////////////////////
//::
/*
Combat Strike
Your intense, focused state allows you to see the one critical
moment in a battle when you hang suspended between victory and
defeat. By pouring the energy required to maintain your focus
into your assault, you batter through your foe's defenses.
Prerequisite: Combat Focus, WIS 13, any two other combat form
feats, base attack bonus +15
Specifics: If you choose to end your combat focus as a swift
action, you gain a bonus on attack rolls and damage rolls equal
to your total number of combat form feats for the rest of your
current turn. You immediately lose all BENEFITS of combat form
feats that affect you only while you are maintaining your combat
focus.
Use: Selected.
Special: A fighter can select Combat Focus as one of his fighter
bonus feats.
*/
//::
//:://////////////////////////////////////////////////////////////////
//:: Script: ft_combat_strike.nss
//:: Author: Jaysyn
//:: Created: 2026-02-22 12:29:37
//:://////////////////////////////////////////////////////////////////
#include "prc_inc_spells"
#include "prc_inc_cmbtform"
#include "prc_x2_itemprop"
void main()
{
object oPC = OBJECT_SELF;
if (!GetHasFeat(FEAT_COMBAT_STRIKE, oPC)) return;
if (!GetLocalInt(oPC, COMBAT_FOCUS_VAR))
{
FloatingTextStringOnCreature("Combat Strike requires active Combat Focus.", oPC, FALSE);
return;
}
if (CountCombatFormFeats(oPC) < 2)
{
FloatingTextStringOnCreature("Combat Strike requires two other Combat Form feats.", oPC, FALSE);
return;
}
// End Combat Focus immediately
DeleteLocalInt(oPC, COMBAT_FOCUS_VAR);
DeleteLocalInt(oPC, COMBAT_FOCUS_END);
// Remove all Combat Form effects by tag immediately
RemoveCombatFocusWillBonus(oPC);
RemoveCombatAwarenessBlindsight(oPC);
RemoveCombatDefenseAC(oPC);
RemoveCombatStabilityBonus(oPC);
RemoveCombatVigorFastHeal(oPC);
// Apply temporary attack/damage bonus for the current turn
int nBonus = CountCombatFormFeats(oPC) + 1;
effect eImpact = EffectVisualEffect(VFX_IMP_PDK_WRATH);
effect eAtk = EffectAttackIncrease(nBonus);
effect eDam = EffectDamageIncrease(IPGetDamageBonusConstantFromNumber(nBonus), DAMAGE_TYPE_BASE_WEAPON);
effect eLink = EffectLinkEffects(eAtk, eDam);
eLink = TagEffect(eLink, "CombatStrike_Bonus");
eLink = SupernaturalEffect(eLink);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eImpact, oPC);
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, 7.0f);
FloatingTextStringOnCreature("*Combat Strike Activated*", oPC, FALSE);
}

View File

@@ -0,0 +1,205 @@
//:://////////////////////////////////////////////////////////////////
//:: ;-. ,-. ,-. ,-.
//:: | ) | ) / ( )
//:: |-' |-< | ;-:
//:: | | \ \ ( )
//:: ' ' ' `-' `-'
//:://////////////////////////////////////////////////////////////////
//::
/*
Combat Focus
Type of Feat: Combat Form, Fighter Bonus Feat.
The way of the warrior requires more than simple, brute strength.
Some warriors bring their minds to such keen focus during the heat
of battle that they can attain superhuman levels of endurance,
perception, and mental toughness. Through intense mental exercise
and training, you learn to enter a state of perfect martial
clarity.
Prerequisite: WIS 13
Specifics: In battle, you push aside the chaos of the fight and
attain a focused state that grants you a keen, clear picture of
the battle. Fear and pain ebb away as you focus solely on
defeating your enemy. The first time you make a successful
attack during an encounter, you gain your combat focus. In this
state, your mind and body become one, allowing you to overcome
mundane physical limits. You can maintain your combat focus for
10 rounds after entering it, +1 additional round per combat form
feat you possess aside from this one. You can only gain your
combat focus once per encounter. While you are maintaining your
combat focus, you gain a +2 bonus on Will saves. If you have
three or more combat form feats, this bonus increases to +4.
Use: Automatic.
Special: A fighter can select Combat Focus as one of his fighter
bonus feats.
*/
//::
//:://////////////////////////////////////////////////////////////////
//:: Script: prc_combatfocus.nss
//:: Author: Jaysyn
//:: Created: 2026-02-22 12:29:37
//:://////////////////////////////////////////////////////////////////
#include "prc_alterations"
#include "prc_inc_function"
#include "prc_inc_cmbtform"
#include "inc_eventhook"
void CombatFocus_AddOnHitToItem(object oItem)
{
if (!GetIsObjectValid(oItem)) return;
itemproperty ipOnHit = ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1);
ipOnHit = TagItemProperty(ipOnHit, "Tag_PRC_OnHitKeeper");
IPSafeAddItemProperty(oItem, ipOnHit, 999999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
AddEventScript(oItem, EVENT_ITEM_ONHIT, "prc_combatfocus", TRUE, FALSE);
}
// Helper to remove OnHit property from a weapon/ammo
void CombatFocus_RemoveOnHitFromItem(object oItem)
{
if (!GetIsObjectValid(oItem)) return;
RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "prc_combatfocus", TRUE, FALSE);
RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY);
}
void main()
{
int nEvent = GetRunningEvent();
object oPC;
// Resolve the correct PC based on the event
switch (nEvent)
{
case EVENT_ONPLAYERREST_FINISHED: oPC = GetLastBeingRested(); break;
case EVENT_ONPLAYEREQUIPITEM: oPC = GetItemLastEquippedBy(); break;
case EVENT_ONPLAYERUNEQUIPITEM: oPC = GetItemLastUnequippedBy(); break;
case EVENT_ONHEARTBEAT: oPC = OBJECT_SELF; break;
case EVENT_ITEM_ONHIT: oPC = OBJECT_SELF; break;
default: oPC = OBJECT_SELF; break;
}
if (nEvent == FALSE) // EvalPRCFeats entry
{
if (!GetHasFeat(FEAT_COMBAT_FOCUS, oPC)) return;
// Register EVENT_ITEM_ONHIT once if not already registered
if (!GetLocalInt(oPC, "CmbtFocus_OnHit_Registered"))
{
AddEventScript(oPC, EVENT_ITEM_ONHIT, "prc_combatfocus", TRUE, FALSE);
SetLocalInt(oPC, "CmbtFocus_OnHit_Registered", TRUE);
}
// Register equip/unequip events once
if (!GetLocalInt(oPC, "CmbtFocus_EquipHooks_Registered"))
{
AddEventScript(oPC, EVENT_ONPLAYEREQUIPITEM, "prc_combatfocus", TRUE, FALSE);
AddEventScript(oPC, EVENT_ONPLAYERUNEQUIPITEM, "prc_combatfocus", TRUE, FALSE);
SetLocalInt(oPC, "CmbtFocus_EquipHooks_Registered", TRUE);
}
// Register rest-finished event once
if (!GetLocalInt(oPC, "CmbtFocus_RestHook_Registered"))
{
AddEventScript(oPC, EVENT_ONPLAYERREST_FINISHED, "prc_combatfocus", TRUE, FALSE);
SetLocalInt(oPC, "CmbtFocus_RestHook_Registered", TRUE);
}
// Apply Will bonus if focus is active
if (GetLocalInt(oPC, COMBAT_FOCUS_VAR))
{
ApplyCombatFocusWillBonus(oPC);
// Always ensure heartbeat is registered while focus is active
if (!GetLocalInt(oPC, "CmbtFocus_HB_Registered"))
{
AddEventScript(oPC, EVENT_ONHEARTBEAT, "prc_combatfocus", TRUE, FALSE);
SetLocalInt(oPC, "CmbtFocus_HB_Registered", TRUE);
}
}
else
{
// Remove Will bonus if focus is not active
if (GetLocalInt(oPC, "CombatFocus_Will"))
RemoveCombatFocusWillBonus(oPC);
}
}
else if (nEvent == EVENT_ONPLAYEREQUIPITEM)
{
object oItem = GetItemLastEquipped();
if (!GetIsObjectValid(oItem)) return;
// Skip VoP and Forsaker to avoid conflicts
if (GetHasFeat(FEAT_VOWOFPOVERTY, oPC) || GetLevelByClass(CLASS_TYPE_FORSAKER, oPC)) return;
if (IPGetIsMeleeWeapon(oItem))
{
CombatFocus_AddOnHitToItem(oItem);
// Also add to ammo if ranged
object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC);
if (GetIsObjectValid(oAmmo)) CombatFocus_AddOnHitToItem(oAmmo);
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC);
if (GetIsObjectValid(oAmmo)) CombatFocus_AddOnHitToItem(oAmmo);
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC);
if (GetIsObjectValid(oAmmo)) CombatFocus_AddOnHitToItem(oAmmo);
}
}
else if (nEvent == EVENT_ONPLAYERUNEQUIPITEM)
{
object oItem = GetItemLastUnequipped();
if (!GetIsObjectValid(oItem)) return;
if (IPGetIsMeleeWeapon(oItem))
{
CombatFocus_RemoveOnHitFromItem(oItem);
// Also remove from ammo if ranged
CombatFocus_RemoveOnHitFromItem(GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC));
CombatFocus_RemoveOnHitFromItem(GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC));
CombatFocus_RemoveOnHitFromItem(GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC));
}
}
else if (nEvent == EVENT_ONHEARTBEAT)
{
if (!GetIsPC(oPC) || !GetLocalInt(oPC, COMBAT_FOCUS_VAR)) return;
// Combat Awareness HP display only
if (GetHasFeat(FEAT_COMBAT_AWARENESS, oPC))
ShowAdjacentHP(oPC);
}
else if (nEvent == EVENT_ONPLAYERREST_FINISHED)
{
RemoveCombatFocusWillBonus(oPC);
DeleteLocalInt(oPC, COMBAT_FOCUS_VAR);
DeleteLocalInt(oPC, "CombatFocus_RoundsRemaining");
DeleteLocalInt(oPC, COMBAT_FOCUS_ENC);
if (GetLocalInt(oPC, "CmbtFocus_HB_Registered"))
{
RemoveEventScript(oPC, EVENT_ONHEARTBEAT, "prc_combatfocus", TRUE, FALSE);
DeleteLocalInt(oPC, "CmbtFocus_HB_Registered");
}
object oRightHand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
if (GetIsObjectValid(oRightHand) && IPGetIsMeleeWeapon(oRightHand))
{
DelayCommand(1.0f, CombatFocus_AddOnHitToItem(oRightHand));
}
}
else if (nEvent == EVENT_ITEM_ONHIT)
{
if (!GetIsPC(oPC)) return;
if (!GetHasFeat(FEAT_COMBAT_FOCUS, oPC)) return;
if (GetLocalInt(oPC, COMBAT_FOCUS_VAR)) return;
if (GetLocalInt(oPC, COMBAT_FOCUS_ENC)) return;
CombatFocus_OnAttackHit(oPC);
// Start round decay heartbeat
if (!GetLocalInt(oPC, "CmbtFocus_HB_Registered"))
{
AddEventScript(oPC, EVENT_ONHEARTBEAT, "prc_combatfocus", TRUE, FALSE);
SetLocalInt(oPC, "CmbtFocus_HB_Registered", TRUE);
DelayCommand(6.0, CombatFocus_DecayRounds(oPC));
}
// Start combat-end detection
DelayCommand(6.0, CombatFocus_CombatEndHeartbeat(oPC));
}
}