236 lines
11 KiB
Plaintext
236 lines
11 KiB
Plaintext
|
/*
|
|||
|
----------------
|
|||
|
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 enemy<6D>s 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 = min(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);
|
|||
|
}
|