438 lines
21 KiB
Plaintext
438 lines
21 KiB
Plaintext
|
/*
|
|||
|
----------------
|
|||
|
Energy Current
|
|||
|
|
|||
|
psi_pow_encurr
|
|||
|
----------------
|
|||
|
|
|||
|
2/8/05 by Stratovarius
|
|||
|
*/ /** @file
|
|||
|
|
|||
|
Energy Current
|
|||
|
|
|||
|
Psychokinesis [see text]
|
|||
|
Level: Kineticist 5
|
|||
|
Manifesting Time: 1 standard action
|
|||
|
Range: Close (25 ft. + 5 ft./2 levels)
|
|||
|
Target: Any two creatures no more than 15 ft. apart
|
|||
|
Duration: Concentration, up to 1 round/level
|
|||
|
Saving Throw: Reflex half or Fortitude half; see text
|
|||
|
Power Resistance: Yes
|
|||
|
Power Points: 9
|
|||
|
Metapsionics: Empower, Extend, Maximize
|
|||
|
|
|||
|
Upon manifesting this power, you choose cold, electricity, fire, or sonic.
|
|||
|
Your body<64>s psionically fueled bioenergetic currents produce an arc of
|
|||
|
energy of the chosen type that targets a creature you designate as the
|
|||
|
primary foe for 9d6 points of damage in every round when the power remains
|
|||
|
in effect. Energy also arcs off the primary foe to strike one additional foe
|
|||
|
that is initially within 15 feet of the primary foe, or that subsequently
|
|||
|
moves within 15 feet of the primary foe while the duration lasts. Secondary
|
|||
|
foes take half the damage that the primary foe takes in every round while
|
|||
|
the duration lasts.
|
|||
|
|
|||
|
Should either the primary or secondary foe fall to less than 0 hit points
|
|||
|
(or should a target completely evade the effect with a special ability or
|
|||
|
power), the energy current <20>s arc randomly retargets another primary and/or
|
|||
|
secondary foe while the duration lasts. Targeted foes can move normally,
|
|||
|
possibly moving out of range of the effect, but each round they are targeted
|
|||
|
and remain in range they must make a saving throw to avoid taking full
|
|||
|
damage in that round.
|
|||
|
|
|||
|
Concentrating to maintain energy current is a full-round action. If you take
|
|||
|
damage while maintaining energy current, you must make a successful
|
|||
|
Concentration check (DC 10 + damage dealt) to avoid losing your
|
|||
|
concentration on the power.
|
|||
|
|
|||
|
Cold: A current of this energy type deals +1 point of damage per die. The
|
|||
|
saving throw to reduce damage from a cold current is a Fortitude save
|
|||
|
instead of a Reflex save.
|
|||
|
Electricity: Manifesting a current of this energy type provides a +2 bonus
|
|||
|
to the save DC and a +2 bonus on manifester level checks for
|
|||
|
the purpose of overcoming power resistance.
|
|||
|
Fire: A current of this energy type deals +1 point of damage per die.
|
|||
|
Sonic: A current of this energy type deals -1 point of damage per die and
|
|||
|
ignores an object<63>s hardness.
|
|||
|
|
|||
|
This power<65>s subtype is the same as the type of energy you manifest.
|
|||
|
|
|||
|
Augment: You can augment this power in one or both of the following ways.
|
|||
|
1. For every additional power point you spend, this power<65>s damage increases
|
|||
|
by one die (d6). For each extra two dice of damage, this power<65>s save DC
|
|||
|
increases by 1.
|
|||
|
2. For every 4 additional power points you spend, this power can affect an
|
|||
|
additional secondary target. Any additional secondary target cannot be
|
|||
|
more than 15 feet from another target of the power.
|
|||
|
|
|||
|
@todo 2da
|
|||
|
*/
|
|||
|
|
|||
|
#include "psi_inc_psifunc"
|
|||
|
#include "psi_inc_pwresist"
|
|||
|
#include "psi_spellhook"
|
|||
|
#include "prc_inc_spells"
|
|||
|
#include "psi_inc_enrgypow"
|
|||
|
|
|||
|
|
|||
|
const string SECONDARY_TARGETS_ARRAY = "PRC_Power_EnergyCurrent_SecondaryTargets";
|
|||
|
|
|||
|
|
|||
|
//////////////////////////////////////////////////
|
|||
|
/* Function prototypes */
|
|||
|
//////////////////////////////////////////////////
|
|||
|
|
|||
|
void EnergyCurrentHB(struct manifestation manif, struct energy_adjustments enAdj,
|
|||
|
object oMainTarget, int nDC, int nPen, int nNumberOfDice, int nSecondaryTargets, float fRange,
|
|||
|
location lManifesterOld, int nBeatsRemaining, int bFirst);
|
|||
|
|
|||
|
void SecondaryTargetsCheck(object oManifester, object oMainTarget, int nSecondaryTargets, int nPen);
|
|||
|
|
|||
|
void DoEnergyCurrentDamage(struct manifestation manif, struct energy_adjustments enAdj,
|
|||
|
object oMainTarget, int nDC, int nPen, int nNumberOfDice);
|
|||
|
|
|||
|
|
|||
|
//////////////////////////////////////////////////
|
|||
|
/* Function definitions */
|
|||
|
//////////////////////////////////////////////////
|
|||
|
|
|||
|
void main()
|
|||
|
{
|
|||
|
// Are we running the manifestation part or the eventhook
|
|||
|
if(GetRunningEvent() != EVENT_ONHIT)
|
|||
|
{
|
|||
|
// Power use hook
|
|||
|
if(!PsiPrePowerCastCode()) return;
|
|||
|
|
|||
|
object oManifester = OBJECT_SELF;
|
|||
|
object oMainTarget = PRCGetSpellTargetObject();
|
|||
|
struct manifestation manif =
|
|||
|
EvaluateManifestation(oManifester, oMainTarget,
|
|||
|
PowerAugmentationProfile(PRC_NO_GENERIC_AUGMENTS,
|
|||
|
1, PRC_UNLIMITED_AUGMENTATION,
|
|||
|
4, PRC_UNLIMITED_AUGMENTATION
|
|||
|
),
|
|||
|
METAPSIONIC_EMPOWER | METAPSIONIC_EXTEND | METAPSIONIC_MAXIMIZE
|
|||
|
);
|
|||
|
|
|||
|
if(manif.bCanManifest)
|
|||
|
{
|
|||
|
struct energy_adjustments enAdj =
|
|||
|
EvaluateEnergy(manif.nSpellID, POWER_ENERGYCURRENT_COLD, POWER_ENERGYCURRENT_ELEC, POWER_ENERGYCURRENT_FIRE, POWER_ENERGYCURRENT_SONIC,
|
|||
|
VFX_BEAM_COLD, VFX_BEAM_LIGHTNING, VFX_BEAM_FIRE, VFX_BEAM_ODD);
|
|||
|
int nDC = GetManifesterDC(oManifester) + enAdj.nDCMod + (manif.nTimesAugOptUsed_1 / 2);
|
|||
|
int nPen = GetPsiPenetration(oManifester) + enAdj.nPenMod;
|
|||
|
int nNumberOfDice = 9 + manif.nTimesAugOptUsed_1;
|
|||
|
int nSecondaryTargets = 1 + manif.nTimesAugOptUsed_2;
|
|||
|
effect eDurManifester = EffectVisualEffect(VFX_DUR_PARALYZE_HOLD);
|
|||
|
float fRange = 25.0f + (5.0f * (manif.nManifesterLevel / 2));
|
|||
|
float fDuration = 6.0f * manif.nManifesterLevel;
|
|||
|
if(manif.bExtend) fDuration *= 2;
|
|||
|
|
|||
|
// Get the OnHitCast: Unique on the manifester's armor / hide
|
|||
|
ExecuteScript("prc_keep_onhit_a", oManifester);
|
|||
|
|
|||
|
// Hook eventscript for concentration checks due to being damaged
|
|||
|
AddEventScript(oManifester, EVENT_ONHIT, "psi_pow_encurr", TRUE, FALSE);
|
|||
|
|
|||
|
// Apply a VFX for the dispelling check to look for
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDurManifester, oManifester, fDuration, TRUE, manif.nSpellID, manif.nManifesterLevel);
|
|||
|
|
|||
|
// Power resistance for the first main target
|
|||
|
if(!PRCMyResistPower(oManifester, oMainTarget, nPen))
|
|||
|
{
|
|||
|
// Set the main target to be invalid so the loop will select a new one
|
|||
|
oMainTarget = OBJECT_INVALID;
|
|||
|
}
|
|||
|
|
|||
|
// Start the heartbeat
|
|||
|
EnergyCurrentHB(manif, enAdj, oMainTarget, nDC, nPen, nNumberOfDice, nSecondaryTargets, fRange, GetLocation(oManifester), FloatToInt(fDuration) / 6, TRUE);
|
|||
|
}// end if - Successfull manifestation
|
|||
|
}// end if - Manifesting the power
|
|||
|
else
|
|||
|
{
|
|||
|
object oManifester = OBJECT_SELF;
|
|||
|
object oItem = GetSpellCastItem();
|
|||
|
|
|||
|
// Make sure the one doing the triggering hit was someone else
|
|||
|
if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR ||
|
|||
|
GetBaseItemType(oItem) == BASE_ITEM_CREATUREITEM
|
|||
|
)
|
|||
|
{
|
|||
|
// DC 10 + damage dealt to keep the Energy Current running
|
|||
|
if(!GetIsSkillSuccessful(oManifester, SKILL_CONCENTRATION, (10 + GetTotalDamageDealt())))
|
|||
|
{
|
|||
|
// Set a marker that tells the HB to stop
|
|||
|
SetLocalInt(oManifester, "PRC_Power_EnergyCurrent_ConcentrationBroken", TRUE);
|
|||
|
}
|
|||
|
}// end if - Manifester was the one hit in the triggering attack
|
|||
|
}// end else - Running eventhook
|
|||
|
}
|
|||
|
|
|||
|
void EnergyCurrentHB(struct manifestation manif, struct energy_adjustments enAdj,
|
|||
|
object oMainTarget, int nDC, int nPen, int nNumberOfDice, int nSecondaryTargets, float fRange,
|
|||
|
location lManifesterOld, int nBeatsRemaining, int bFirst)
|
|||
|
{
|
|||
|
// Check expiration
|
|||
|
if(!GetLocalInt(manif.oManifester, "PRC_Power_EnergyCurrent_ConcentrationBroken") && // The manifester's concentration hasn't been broken due to damage
|
|||
|
nBeatsRemaining-- > 0 && // The power's duration hasn't run out yet
|
|||
|
!PRCGetDelayedSpellEffectsExpired(manif.nSpellID, manif.oManifester, manif.oManifester) && // Not dispelled
|
|||
|
!GetBreakConcentrationCheck(manif.oManifester) // The manifester isn't doing anything that breaks their concentration
|
|||
|
)
|
|||
|
{
|
|||
|
location lManifester = GetLocation(manif.oManifester);
|
|||
|
// First, check if the primary target needs to be switched
|
|||
|
if(!bFirst && // Don't reselect even if the original primary target succeeded at it's PR
|
|||
|
(!GetIsObjectValid(oMainTarget) || // The creature no longer exists
|
|||
|
GetCurrentHitPoints(oMainTarget) < 0 || // The creature's HP has gone under zero
|
|||
|
GetDistanceBetween(manif.oManifester, oMainTarget) > fRange // The creature is out of the power's range
|
|||
|
)
|
|||
|
)
|
|||
|
{
|
|||
|
// Select a new main target
|
|||
|
// NOTE: This intentionally ignores the My*ObjectInShape wrapper
|
|||
|
object oTest = GetFirstObjectInShape(SHAPE_SPHERE, fRange, lManifester, TRUE, OBJECT_TYPE_CREATURE);
|
|||
|
while(GetIsObjectValid(oTest))
|
|||
|
{
|
|||
|
// Target only hostiles, and only ones that the manifester can see
|
|||
|
if(oTest != manif.oManifester &&
|
|||
|
spellsIsTarget(oTest, SPELL_TARGET_SELECTIVEHOSTILE, manif.oManifester) &&
|
|||
|
!GetIsDead(oTest) &&
|
|||
|
GetObjectSeen(oTest, manif.oManifester)
|
|||
|
)
|
|||
|
{
|
|||
|
AddToTargetList(oTest, manif.oManifester, INSERTION_BIAS_DISTANCE, FALSE);
|
|||
|
}
|
|||
|
|
|||
|
// Get next potential target
|
|||
|
oTest = GetNextObjectInShape(SHAPE_SPHERE, fRange, lManifester, TRUE, OBJECT_TYPE_CREATURE);
|
|||
|
}// end while - Target selection loop
|
|||
|
|
|||
|
// Select the hostile creature closest to the manifester
|
|||
|
oMainTarget = GetTargetListHead(manif.oManifester);
|
|||
|
|
|||
|
// Power resistance
|
|||
|
if(!PRCMyResistPower(manif.oManifester, oMainTarget, nPen))
|
|||
|
{
|
|||
|
// Set the target to be invalid - No current this round
|
|||
|
oMainTarget = OBJECT_INVALID;
|
|||
|
}
|
|||
|
|
|||
|
// Nuke the secondary targets array so we are forced to fully recalculate it
|
|||
|
array_delete(manif.oManifester, SECONDARY_TARGETS_ARRAY);
|
|||
|
}// end if - Main target selection
|
|||
|
|
|||
|
// Make sure we have a valid primary target at this point
|
|||
|
if(GetIsObjectValid(oMainTarget))
|
|||
|
{
|
|||
|
// Check secondary targets array existence
|
|||
|
if(!array_exists(manif.oManifester, SECONDARY_TARGETS_ARRAY))
|
|||
|
array_create(manif.oManifester, SECONDARY_TARGETS_ARRAY);
|
|||
|
|
|||
|
// If the array contains empty slots or slots with creatures that are now outside the range, reselect secondary targets
|
|||
|
SecondaryTargetsCheck(manif.oManifester, oMainTarget, nSecondaryTargets, nPen);
|
|||
|
|
|||
|
// Run the actual damage dealing
|
|||
|
DoEnergyCurrentDamage(manif, enAdj, oMainTarget, nDC, nPen, nNumberOfDice);
|
|||
|
}// end if - The primary target is valid
|
|||
|
|
|||
|
// Schedule next HB
|
|||
|
DelayCommand(6.0f, EnergyCurrentHB(manif, enAdj, oMainTarget, nDC, nPen, nNumberOfDice,
|
|||
|
nSecondaryTargets, fRange, lManifester, nBeatsRemaining, FALSE
|
|||
|
)
|
|||
|
);
|
|||
|
}
|
|||
|
// Power expired for some reason, make sure VFX are gone
|
|||
|
else
|
|||
|
{
|
|||
|
if(DEBUG) DoDebug("psi_pow_encurr: Power expired");
|
|||
|
PRCRemoveSpellEffects(manif.nSpellID, manif.oManifester, manif.oManifester);
|
|||
|
DeleteLocalInt(manif.oManifester, "PRC_Power_EnergyCurrent_ConcentrationBroken");
|
|||
|
array_delete(manif.oManifester, SECONDARY_TARGETS_ARRAY);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void SecondaryTargetsCheck(object oManifester, object oMainTarget, int nSecondaryTargets, int nPen)
|
|||
|
{
|
|||
|
int i, nFirstEmpty = -1;
|
|||
|
float fRange = FeetToMeters(15.0f);
|
|||
|
object oTest;
|
|||
|
// Loop over the secondary targets array
|
|||
|
for(i = 0; i < nSecondaryTargets; i++)
|
|||
|
{
|
|||
|
// Check if each of the secondary targets still qualifies
|
|||
|
oTest = array_get_object(oManifester, SECONDARY_TARGETS_ARRAY, i);
|
|||
|
//DoDebug("SecondaryTargetsCheck(): Testing if needs replacement: " + DebugObject2Str(oTest));
|
|||
|
if(!GetIsObjectValid(oTest) || // The creature no longer exists
|
|||
|
GetCurrentHitPoints(oTest) < 0 || // The creature's HP has gone under zero
|
|||
|
GetDistanceBetween(oTest, oMainTarget) > fRange // The creature is out of the power's range
|
|||
|
)
|
|||
|
{
|
|||
|
/*DoDebug("SecondaryTargetsCheck(): Needs replacement\n"
|
|||
|
+ "!GetIsObjectValid(oTest) = " + DebugBool2String(!GetIsObjectValid(oTest)) + "\n"
|
|||
|
+ "GetCurrentHitPoints(oTest) < 0 = " + DebugBool2String(GetCurrentHitPoints(oTest) < 0) + "\n"
|
|||
|
+ "GetDistanceBetween(oTest, oMainTarget) > fRange = " + DebugBool2String(GetDistanceBetween(oTest, oMainTarget) > fRange) + "\n"
|
|||
|
);*/
|
|||
|
// If one doesn't, clear the array entry and set the return value to indicate that secondary targets need to be reselected
|
|||
|
array_set_object(oManifester, SECONDARY_TARGETS_ARRAY, i, OBJECT_INVALID);
|
|||
|
|
|||
|
// Store the first empty index, which indicates the need for reselection
|
|||
|
if(nFirstEmpty == -1)
|
|||
|
nFirstEmpty = i;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// If the secondary targets need reselection, do so
|
|||
|
if(nFirstEmpty != -1)
|
|||
|
{
|
|||
|
// An array to store names of temporary variables in
|
|||
|
if(array_exists(oManifester, "PRC_Power_EnCur_Temp"))
|
|||
|
array_delete(oManifester, "PRC_Power_EnCur_Temp");
|
|||
|
array_create(oManifester, "PRC_Power_EnCur_Temp");
|
|||
|
|
|||
|
string sName;
|
|||
|
|
|||
|
// Store the UIDs (memory address) of the current valid secondary targets into a hash table
|
|||
|
for(i = 0; i < nSecondaryTargets; i++)
|
|||
|
{
|
|||
|
oTest = array_get_object(oManifester, SECONDARY_TARGETS_ARRAY, i);
|
|||
|
if(oTest != OBJECT_INVALID)// Do not store OBJECT_INVALID, since it wouldn't get cleared after reselection
|
|||
|
{
|
|||
|
sName = "PRC_Power_EnCur_Target_" + ObjectToString(oTest);
|
|||
|
SetLocalInt(oManifester, sName, TRUE);
|
|||
|
array_set_string(oManifester, "PRC_Power_EnCur_Temp", array_get_size(oManifester, "PRC_Power_EnCur_Temp"), sName);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Get creatures that are eligible for secondary targethood until all slots are filled
|
|||
|
// or there are no more eligible targets left unselected
|
|||
|
i = nFirstEmpty;
|
|||
|
location lTarget = GetLocation(oMainTarget);
|
|||
|
oTest = GetFirstObjectInShape(SHAPE_SPHERE, fRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|||
|
while(GetIsObjectValid(oTest) && i < nSecondaryTargets)
|
|||
|
{
|
|||
|
// Targeting limitations, yay
|
|||
|
if(oTest != oManifester && // Not the manifester
|
|||
|
oTest != oMainTarget && // Not the main target
|
|||
|
!GetIsDead(oTest) && // Target is alive...
|
|||
|
!GetLocalInt(oManifester, "PRC_Power_EnCur_Target_" + ObjectToString(oTest)) && // Not an existing secondary target
|
|||
|
spellsIsTarget(oTest, SPELL_TARGET_SELECTIVEHOSTILE, oManifester) // And the target is hostile
|
|||
|
)
|
|||
|
{
|
|||
|
// Power resistance
|
|||
|
if(!PRCMyResistPower(oManifester, oTest, nPen))
|
|||
|
{
|
|||
|
// Set the target to be invalid - The slot will be left empty this round
|
|||
|
oTest = OBJECT_INVALID;
|
|||
|
}
|
|||
|
|
|||
|
// Store the target in the secondary target array
|
|||
|
array_set_object(oManifester, SECONDARY_TARGETS_ARRAY, i, oTest);
|
|||
|
|
|||
|
// Find next empty slot
|
|||
|
while(array_get_object(oManifester, SECONDARY_TARGETS_ARRAY, ++i) != OBJECT_INVALID)
|
|||
|
;
|
|||
|
}
|
|||
|
|
|||
|
// Get next potential target
|
|||
|
oTest = GetNextObjectInShape(SHAPE_SPHERE, fRange, lTarget, TRUE, OBJECT_TYPE_CREATURE);
|
|||
|
}// end while - Target selection loop
|
|||
|
|
|||
|
// Remove the UID locals
|
|||
|
int nMax = nSecondaryTargets;//array_get_size(oManifester, "PRC_Power_EnCur_Temp");
|
|||
|
for(i = 0; i < nMax; i++)
|
|||
|
{
|
|||
|
DeleteLocalInt(oManifester, array_get_string(oManifester, "PRC_Power_EnCur_Temp", i));
|
|||
|
DeleteLocalInt(oManifester, "PRC_Power_EnCur_Target_"
|
|||
|
+ ObjectToString(array_get_object(oManifester, SECONDARY_TARGETS_ARRAY, i))
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
array_delete(oManifester, "PRC_Power_EnCur_Temp");
|
|||
|
}// end if - Reselect secondary targets
|
|||
|
}
|
|||
|
|
|||
|
void DoEnergyCurrentDamage(struct manifestation manif, struct energy_adjustments enAdj,
|
|||
|
object oMainTarget, int nDC, int nPen, int nNumberOfDice)
|
|||
|
{
|
|||
|
int nDieSize = 6;
|
|||
|
int nDamage, nSecondaryDamage, i;
|
|||
|
effect eVis = EffectVisualEffect(enAdj.nVFX1);
|
|||
|
effect eDamage;
|
|||
|
object oSecondaryTarget;
|
|||
|
|
|||
|
// Try to affect the main target
|
|||
|
// Roll damage
|
|||
|
nDamage = MetaPsionicsDamage(manif, nDieSize, nNumberOfDice, 0, enAdj.nBonusPerDie, TRUE, FALSE);
|
|||
|
// Target-specific stuff
|
|||
|
nDamage = GetTargetSpecificChangesToDamage(oMainTarget, manif.oManifester, nDamage, TRUE, TRUE);
|
|||
|
|
|||
|
// Do save
|
|||
|
if(enAdj.nSaveType == SAVING_THROW_TYPE_COLD)
|
|||
|
{
|
|||
|
// Cold has a fort save for half
|
|||
|
if(PRCMySavingThrow(SAVING_THROW_FORT, oMainTarget, nDC, enAdj.nSaveType))
|
|||
|
{
|
|||
|
if (GetHasMettle(oMainTarget, SAVING_THROW_FORT))
|
|||
|
// This script does nothing if it has Mettle, bail
|
|||
|
nDamage = 0;
|
|||
|
nDamage /= 2;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
// Adjust damage according to Reflex Save, Evasion or Improved Evasion
|
|||
|
nDamage = PRCGetReflexAdjustedDamage(nDamage, oMainTarget, nDC, enAdj.nSaveType);
|
|||
|
|
|||
|
// Fire the ray
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBeam(enAdj.nVFX2, manif.oManifester, BODY_NODE_HAND, nDamage == 0), oMainTarget, 1.7f, FALSE);
|
|||
|
|
|||
|
// Let the main target's AI know it's being targeted with a hostile spell
|
|||
|
PRCSignalSpellEvent(oMainTarget, TRUE, manif.nSpellID, manif.oManifester);
|
|||
|
|
|||
|
// Deal damage if the target didn't Evade it
|
|||
|
if(nDamage > 0)
|
|||
|
{
|
|||
|
eDamage = EffectDamage(nDamage, enAdj.nDamageType);
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oMainTarget);
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oMainTarget);
|
|||
|
|
|||
|
// Secondary targets take half the amount the primary took
|
|||
|
nDamage /= 2;
|
|||
|
|
|||
|
// Deal with the secondary targets
|
|||
|
for(i = 0; i < array_get_size(manif.oManifester, SECONDARY_TARGETS_ARRAY); i++)
|
|||
|
{
|
|||
|
// Get target to affect
|
|||
|
oSecondaryTarget = array_get_object(manif.oManifester, SECONDARY_TARGETS_ARRAY, i);
|
|||
|
// Determine damage
|
|||
|
nSecondaryDamage = nDamage;
|
|||
|
// Target-specific stuff
|
|||
|
nSecondaryDamage = GetTargetSpecificChangesToDamage(oSecondaryTarget, manif.oManifester, nSecondaryDamage, TRUE, TRUE);
|
|||
|
|
|||
|
// Do save
|
|||
|
if(enAdj.nSaveType == SAVING_THROW_TYPE_COLD)
|
|||
|
{
|
|||
|
// Cold has a fort save for half
|
|||
|
if(PRCMySavingThrow(SAVING_THROW_FORT, oSecondaryTarget, nDC, enAdj.nSaveType))
|
|||
|
nSecondaryDamage /= 2;
|
|||
|
}
|
|||
|
else
|
|||
|
// Adjust damage according to Reflex Save, Evasion or Improved Evasion
|
|||
|
nSecondaryDamage = PRCGetReflexAdjustedDamage(nSecondaryDamage, oSecondaryTarget, nDC, enAdj.nSaveType);
|
|||
|
|
|||
|
// Fire the ray
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectBeam(enAdj.nVFX2, oMainTarget, BODY_NODE_CHEST, nSecondaryDamage == 0), oSecondaryTarget, 1.7f, FALSE);
|
|||
|
|
|||
|
// Let the secondary target's AI know it's being targeted with a hostile spell
|
|||
|
PRCSignalSpellEvent(oSecondaryTarget, TRUE, manif.nSpellID, manif.oManifester);
|
|||
|
|
|||
|
// Deal damage if the target didn't Evade it
|
|||
|
if(nSecondaryDamage > 0)
|
|||
|
{
|
|||
|
eDamage = EffectDamage(nSecondaryDamage, enAdj.nDamageType);
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oSecondaryTarget);
|
|||
|
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oSecondaryTarget);
|
|||
|
}// end if - There was still damage remaining to be dealt after adjustments
|
|||
|
}// end for - Secondary targets
|
|||
|
}// end if - There was still damage remaining to be dealt after adjustments
|
|||
|
}
|