PRC8_fork/nwn/nwnprc/trunk/psionics/psi_pow_strnmy.nss
Jaysyn904 e641b42f84 Exalted update
Updated Vow of Poverty. Added Sanctify Ki Strike, Holy Strike, Fist of Heavens, Vow of Abstinence, Vow of Chastity & Gift of Faith.  (@fenac).  Turned off the Taunt & Parry skills.  Re-disabled AC & save bonuses from Tumble & Spellcraft.   Updated min() & max() to PRCmin() & PRCmax() to not conflict with similarly named NUI adjacent functions.  Set Point Blank Shot to 30' per PnP.  Added icon for Chosen of Evil.  Started work on Hidden Talent.  Created Psionics function cheatsheet.  Updated release archive.
2025-01-29 22:46:38 -05:00

236 lines
11 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
----------------
Strength of my Enemy
psi_pow_strnmy
----------------
14/12/05 by Stratovarius
*/ /** @file
Strength of My Enemy
Psychometabolism
Level: Psychic warrior 2
Manifesting Time: 1 standard action
Range: Personal
Target: You
Duration: 1 round/level
Power Points: 3
Metapsionics: Extend
You gain the ability to siphon away your enemys strength for your own use.
One of your natural or manufactured weapons becomes the instrument of your
desire, and deals 1 point of Strength damage on each successful hit. You
gain that point of Strength as an enhancement bonus to your Strength score.
Strength you siphon from different foes is tracked separately - the total
siphoned from each individual foe is considered a separate enhancement bonus
to your Strength (maximum +8), and you gain only the highest total.
Augment: For every 3 additional power points you spend, the maximum
enhancement bonus you can add to your Strength increases by 2.
*/
#include "prc_inc_spells"
#include "psi_inc_onhit"
#include "psi_inc_psifunc"
#include "psi_spellhook"
const string STRNMY_ARRAY = "PRC_Power_StrengthOfMyEnemy_Array";
void DispelMonitor(object oManifester, object oTarget, object oWeapon, int nSpellID);
void CleanUpArray(object oCreature);
void main()
{
// Determine whether this script call is about manifesting the power or an OnHit
if(GetRunningEvent() != EVENT_ONHIT)
{
// Spellhook
if (!PsiPrePowerCastCode()){ return; }
object oManifester = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
struct manifestation manif =
EvaluateManifestation(oManifester, oTarget,
PowerAugmentationProfile(PRC_NO_GENERIC_AUGMENTS,
3, PRC_UNLIMITED_AUGMENTATION
),
METAPSIONIC_EXTEND
);
if(manif.bCanManifest)
{
int nMaxBonus = 8 + (2* manif.nTimesAugOptUsed_1);
int nDuration = manif.nManifesterLevel;
if(manif.bExtend) nDuration *= 2;
effect eVis = EffectVisualEffect(VFX_COM_HIT_NEGATIVE);
eVis = EffectLinkEffects(eVis, EffectVisualEffect(VFX_IMP_PULSE_NEGATIVE));
effect eDur = EffectVisualEffect(VFX_DUR_PROTECTION_EVIL_MINOR);
float fDuration = 6.0f * nDuration;
object oWeapon;
// Target checks
if(!IPGetIsMeleeWeapon(oTarget))
{
// If the target was the manifester, get either their primary hand weapon or first creature weapon
if(GetObjectType(oTarget) == OBJECT_TYPE_CREATURE)
{
object oTemp = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
if(IPGetIsMeleeWeapon(oTemp))
oWeapon = oTemp;
else if(GetIsObjectValid(oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oTarget)))
oWeapon = oTemp;
else if(GetIsObjectValid(oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oTarget)))
oWeapon = oTemp;
else if(GetIsObjectValid(oTemp = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oTarget)))
oWeapon = oTemp;
// No creature weapon, either
else
oWeapon = OBJECT_INVALID;
}
else
oWeapon = OBJECT_INVALID;
}
// Target was a weapon
else
{
oWeapon = oTarget;
oTarget = GetItemPossessor(oWeapon);
}
// At this point, the target should be either the weapon, or an invalid object
if(!GetIsObjectValid(oWeapon))
{
// "Target is not valid for Strength of my Enemy!"
FloatingTextStrRefOnCreature(16826668, oManifester, FALSE);
return;
}
// Concurrent instances of the power not allowed
if(!GetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_Duration"))
{
// Add onhit itemproperty to the weapon
IPSafeAddItemProperty(oWeapon, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1),
fDuration, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE
);
// Add a marker local to the weapon
SetLocalInt(oWeapon, "PRC_Power_StrengthOfMyEnemy_Active", TRUE);
// Add eventscript
AddEventScript(oTarget, EVENT_ONHIT, "psi_pow_strnmy", TRUE, FALSE);
// Store manifestation data in local vars
SetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_Duration", nDuration);
SetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_MaxBonus", nMaxBonus);
SetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_ManifLvl", manif.nManifesterLevel);
// Initialise highest strength bonus granted tracker
// First, if, for some reason, the array exists already, perform cleanup
if(array_exists(oTarget, STRNMY_ARRAY))
CleanUpArray(oTarget);
// Create the array
array_create(oTarget, STRNMY_ARRAY);
// Init the current bonus tracking variable to 0
SetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_CurBonus", 0);
// Apply VFX
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDur, oTarget, fDuration, TRUE, manif.nSpellID, manif.nManifesterLevel);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
// Start dispelling monitor
DelayCommand(6.0f, DispelMonitor(oManifester, oTarget, oWeapon, manif.nSpellID));
}
}// end if - Successfull manifestation
}// end if - Manifesting the power
else
{
object oManifester = OBJECT_SELF;
object oWeapon = GetSpellCastItem();
object oTarget = PRCGetSpellTargetObject();
// Make sure the item triggering OnHit was the Strength of my Enemy weapon
if(GetLocalInt(oWeapon, "PRC_Power_StrengthOfMyEnemy_Active"))
{
// No point in doing any of this if the target is immune
if(GetIsImmune(oTarget, IMMUNITY_TYPE_ABILITY_DECREASE))
return;
// Get data
int nMaxBonus = GetLocalInt(oManifester, "PRC_Power_StrengthOfMyEnemy_MaxBonus");
int nManifesterLevel = GetLocalInt(oManifester, "PRC_Power_StrengthOfMyEnemy_ManifLvl");
int nCurrentBonus = GetLocalInt(oManifester, "PRC_Power_StrengthOfMyEnemy_CurBonus");
int nGainedFromCurrent = GetLocalInt(oManifester, "PRC_Power_SomE_STRGainedFrom_" + ObjectToString(oTarget));
// Make an array entry in the tracking array for the current target if it doesn't have one already
if(nGainedFromCurrent == 0)
array_set_object(oManifester, STRNMY_ARRAY, array_get_size(oManifester, STRNMY_ARRAY), oTarget);
// Apply the damage
ApplyAbilityDamage(oTarget, ABILITY_STRENGTH, 1, DURATION_TYPE_TEMPORARY, TRUE, -1.0f);
// Keep track of how many times we've drained the person, which is one more than previous
nGainedFromCurrent = PRCMin(nGainedFromCurrent + 1, nMaxBonus); // Do not allow the value to exceed the max bonus. It probably doesn't matter, but it's ugly :P
SetLocalInt(oManifester, "PRC_Power_SomE_STRGainedFrom_" + ObjectToString(oTarget), nGainedFromCurrent);
// Check ff the amount gained from current target is greater than the current bonus, but not higher than the maximum
if(nGainedFromCurrent > nCurrentBonus &&
nGainedFromCurrent <= nMaxBonus
)
{
// Apply Strength bonus for a duration equal to the remaining duration of this power, with accuracy of +-6s
float fDuration = 6.0f * GetLocalInt(oManifester, "PRC_Power_StrengthOfMyEnemy_Duration");
effect eStr = EffectAbilityIncrease(ABILITY_STRENGTH, nGainedFromCurrent);
effect eVis = EffectVisualEffect(VFX_IMP_IMPROVE_ABILITY_SCORE);
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eStr, oManifester, fDuration, TRUE, POWER_STRENGTH_OF_MY_ENEMY, nManifesterLevel);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oManifester);
// Update the highest bonus tracker
SetLocalInt(oManifester, "PRC_Power_StrengthOfMyEnemy_CurBonus", nGainedFromCurrent);
}// end if - We need to increase the STR bonus in effect
}// end if - OnHit triggered by the corrent item
}// end else - Running OnHit
}
void DispelMonitor(object oManifester, object oTarget, object oWeapon, int nSpellID)
{
int nRoundsRemain = GetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_Duration");
if(PRCGetDelayedSpellEffectsExpired(nSpellID, oTarget, oManifester) || // Has the power expired somehow since last check
nRoundsRemain <= 0 // Or is it running out of duration now
)
{
if(DEBUG) DoDebug("psi_pow_strnmy: Power expired, clearing");
// Remove effects
PRCRemoveSpellEffects(nSpellID, oManifester, oTarget);
// Unhook event
RemoveEventScript(oTarget, EVENT_ONHIT, "psi_pow_strnmy", TRUE, FALSE);
// Clear locals
DeleteLocalInt(oWeapon, "PRC_Power_StrengthOfMyEnemy_Active");
DeleteLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_Duration");
DeleteLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_MaxBonus");
DeleteLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_ManifLvl");
DeleteLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_CurBonus");
CleanUpArray(oTarget);
}
else
{
// Decrement rounds remaining and schedule next HB
SetLocalInt(oTarget, "PRC_Power_StrengthOfMyEnemy_Duration", nRoundsRemain - 1);
DelayCommand(6.0f, DispelMonitor(oManifester, oTarget, oWeapon, nSpellID));
}
}
void CleanUpArray(object oCreature)
{
int i, max = array_get_size(oCreature, STRNMY_ARRAY);
for(i = 0; i < max; i++)
DeleteLocalInt(oCreature, "PRC_Power_SomE_STRGainedFrom_" + ObjectToString(array_get_object(oCreature, STRNMY_ARRAY, i)));
array_delete(oCreature, STRNMY_ARRAY);
}