/* ---------------- 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’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 = 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); }