2025/06/10 afternoon update
Fixed incorrect action for Sublime Chord songs. Hopefully fixed Factotum Inspiration not accumulating after logging back in. Hopefully fixed Archmage SLA ability from grabbing wrong spell level for spell radials. Bluesteel Bracer script now add itself and not Bloodwar Bracers. Fixed Pearl of Black Doubt as good as NWN will allow. Fixed Diamond Dragon level up blocker.
This commit is contained in:
@@ -17,117 +17,148 @@
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: Stance
|
||||
|
||||
With every miss, your opponents become more uncertain,
|
||||
their doubt growing like an irritating pearl in the mouth
|
||||
of a helpless oyster.
|
||||
|
||||
You prey on your opponents' fear and lack of confidence.
|
||||
Each failed attack against you reminds them that their
|
||||
skill cannot hope to match yours.
|
||||
|
||||
When you enter this stance, you become more difficult to
|
||||
hit with each successive attack that misses you. Each
|
||||
time an opponent misses you with a melee attack, you
|
||||
gain a +2 dodge bonus to AC. This bonus lasts until the
|
||||
start of your next turn and is cumulative for the round.
|
||||
The bonus applies to any attacks made by all opponents
|
||||
until the beginning of your next turn.
|
||||
|
||||
With every miss, your opponents become more uncertain, their doubt growing
|
||||
like an irritating pearl in the mouth of a helpless oyster.
|
||||
|
||||
Whenever a foe swings and misses you, you gain +2 AC.
|
||||
*/
|
||||
|
||||
#include "x0_i0_match"
|
||||
#include "tob_inc_move"
|
||||
#include "tob_movehook"
|
||||
////#include "prc_alterations"
|
||||
|
||||
void PoBDACRecursive(object oTarget, object oAttacker);
|
||||
|
||||
|
||||
// All this one does is zero out the boost every six seconds.
|
||||
void PoBDZeroRecursive(object oTarget)
|
||||
{
|
||||
if(GetHasSpellEffect(MOVE_DM_PEARL_BLACK_DOUBT, oTarget))
|
||||
{
|
||||
DeleteLocalInt(oTarget, "PearlOfBlackDoubtBonus");
|
||||
DelayCommand(6.0, PoBDZeroRecursive(oTarget));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int GetApproximateAPR(object oCreature)
|
||||
{
|
||||
int nBAB = GetBaseAttackBonus(oCreature);
|
||||
int nAttacks = 1;
|
||||
|
||||
// +1 attack per +5 BAB over 6
|
||||
if (nBAB >= 6) nAttacks++;
|
||||
if (nBAB >= 6) nAttacks++;
|
||||
if (nBAB >= 11) nAttacks++;
|
||||
if (nBAB >= 16) nAttacks++;
|
||||
|
||||
// Add 1 if hasted
|
||||
if (GetHasEffect(EFFECT_TYPE_HASTE, oCreature))
|
||||
if (PRCGetHasEffect(EFFECT_TYPE_HASTE, oCreature))
|
||||
{
|
||||
nAttacks++;
|
||||
}
|
||||
|
||||
// NOTE: Dual-wielding or monk logic not included here
|
||||
|
||||
return nAttacks;
|
||||
}
|
||||
|
||||
|
||||
void PoBDACRecursive(object oTarget, object oAttacker)
|
||||
{
|
||||
// No need to do this if the spell doesn't exist
|
||||
if(GetHasSpellEffect(MOVE_DM_PEARL_BLACK_DOUBT, oTarget))
|
||||
{ // No bonuses when not in combat
|
||||
if (GetIsInCombat(oTarget))
|
||||
{
|
||||
int nAPR = GetApproximateAPR(oAttacker);
|
||||
|
||||
int nBonus = GetLocalInt(oTarget, "PearlOfBlackDoubtBonus");
|
||||
nBonus += 2 * nAPR;
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(nBonus)), oTarget, 6.0f);
|
||||
SetLocalInt(oTarget, "PearlOfBlackDoubtBonus", nBonus);
|
||||
|
||||
DelayCommand(0.0, PoBDACRecursive(oTarget, oAttacker));
|
||||
DelayCommand(6.0, PoBDZeroRecursive(oTarget));
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteLocalInt(oTarget, "PearlOfBlackDoubtBonus");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if (!PreManeuverCastCode())
|
||||
{
|
||||
// If code within the PreManeuverCastCode (i.e. UMD) reports FALSE, do not run this spell
|
||||
return;
|
||||
}
|
||||
|
||||
// End of Spell Cast Hook
|
||||
|
||||
object oInitiator = OBJECT_SELF;
|
||||
object oAttacker = GetLastAttacker();
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
//Declare main variables.
|
||||
int nEvent = GetRunningEvent();
|
||||
|
||||
struct maneuver move = EvaluateManeuver(oInitiator, oTarget);
|
||||
|
||||
if(move.bCanManeuver)
|
||||
object oItem;
|
||||
object oInitiator;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
|
||||
switch(nEvent)
|
||||
{
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oInitiator);
|
||||
// Add the OnHit
|
||||
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 9999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
||||
effect eDur = EffectVisualEffect(VFX_DUR_BLUESHIELDPROTECT);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eDur), oTarget, 9999.0);
|
||||
|
||||
PoBDACRecursive(oInitiator, oAttacker);
|
||||
|
||||
|
||||
case EVENT_ONHEARTBEAT: oInitiator = OBJECT_SELF; break;
|
||||
case EVENT_ONPLAYERREST_FINISHED: oInitiator = GetLastBeingRested(); break;
|
||||
|
||||
default:
|
||||
oInitiator = OBJECT_SELF;
|
||||
|
||||
}
|
||||
|
||||
if(nEvent == FALSE)
|
||||
{
|
||||
if (!PreManeuverCastCode())
|
||||
{
|
||||
// If code within the PreManeuverCastCode (i.e. UMD) reports FALSE, do not run this spell
|
||||
return;
|
||||
}
|
||||
// End of Spell Cast Hook
|
||||
|
||||
struct maneuver move = EvaluateManeuver(oInitiator, oTarget);
|
||||
|
||||
if(move.bCanManeuver)
|
||||
{
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oInitiator);
|
||||
|
||||
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1),
|
||||
9999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
||||
|
||||
effect eDur = EffectVisualEffect(VFX_DUR_BLUESHIELDPROTECT);
|
||||
eDur = TagEffect(eDur, "PEARL_OF_BLACK_DOUBT");
|
||||
eDur = ExtraordinaryEffect(eDur);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDur, oTarget, 9999.0);
|
||||
|
||||
if(DEBUG) DoDebug("PoBD stance activated");
|
||||
|
||||
AddEventScript(oInitiator, EVENT_ONHEARTBEAT, "tob_dmnd_prlbdt", TRUE, FALSE);
|
||||
AddEventScript(oInitiator, EVENT_ONPLAYERREST_FINISHED, "tob_dmnd_prlbdt", TRUE, FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
if(nEvent == EVENT_ONHEARTBEAT)
|
||||
{
|
||||
int nBonus = 0;
|
||||
location lLoc = GetLocation(oTarget);
|
||||
object oEnemy = GetFirstObjectInShape(SHAPE_SPHERE, 5.0, lLoc, TRUE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while (GetIsObjectValid(oEnemy))
|
||||
{
|
||||
if (GetIsEnemy(oTarget, oEnemy) &&
|
||||
GetIsInCombat(oEnemy) &&
|
||||
GetDistanceBetween(oEnemy, oTarget) <= 5.0 &&
|
||||
GetCurrentAction(oEnemy) == ACTION_ATTACKOBJECT && // Must be attacking
|
||||
GetAttackTarget(oEnemy) == oTarget) // Must be attacking this PC
|
||||
{
|
||||
int nAPR = GetApproximateAPR(oEnemy);
|
||||
nBonus += 2 * nAPR;
|
||||
|
||||
string s = "Enemy: " + GetName(oEnemy) + " APR: " + IntToString(nAPR);
|
||||
if(DEBUG) DoDebug(s, oTarget);
|
||||
}
|
||||
|
||||
oEnemy = GetNextObjectInShape(SHAPE_SPHERE, 5.0, lLoc);
|
||||
}
|
||||
|
||||
if (nBonus > 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("Applying AC Bonus: " + IntToString(nBonus));
|
||||
|
||||
effect eAC = EffectACIncrease(nBonus);
|
||||
eAC = ExtraordinaryEffect(eAC);
|
||||
eAC = TagEffect(eAC, "PEARL_OF_BLACK_DOUBT_BONUS");
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eAC, oTarget, 5.9);
|
||||
SetLocalInt(oTarget, "PearlOfBlackDoubtBonus", nBonus);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("PoBD: No enemies in melee");
|
||||
DeleteLocalInt(oTarget, "PearlOfBlackDoubtBonus");
|
||||
|
||||
effect eEffect = GetFirstEffect(oInitiator);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
{
|
||||
if(GetEffectTag(eEffect) == "PEARL_OF_BLACK_DOUBT_BONUS")
|
||||
RemoveEffect(oInitiator, eEffect);
|
||||
|
||||
eEffect = GetNextEffect(oInitiator);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nEvent == EVENT_ONPLAYERREST_FINISHED)
|
||||
{
|
||||
effect eEffect = GetFirstEffect(oInitiator);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
{
|
||||
if(GetEffectTag(eEffect) == "PEARL_OF_BLACK_DOUBT")
|
||||
RemoveEffect(oInitiator, eEffect);
|
||||
|
||||
eEffect = GetNextEffect(oInitiator);
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("Removing Pearl of Black Doubt");
|
||||
|
||||
RemoveEventScript(oInitiator, EVENT_ONHEARTBEAT, "tob_dmnd_prlbdt", TRUE, FALSE);
|
||||
RemoveEventScript(oInitiator, EVENT_ONPLAYERREST_FINISHED, "tob_dmnd_prlbdt", TRUE, FALSE);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user