PRC8_fork/nwn/nwnprc/trunk/psionics/psi_pow_enmiss.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
Updated AMS marker feats.  Removed arcane & divine marker feats.  Updated Dread Necromancer for epic progression. Updated weapon baseitem models.  Updated new weapons for crafting & npc equip.
 Updated prefix.  Updated release archive.
2024-02-11 14:01:05 -05:00

180 lines
7.6 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.

/*
----------------
Energy Missile
psi_pow_enmiss
----------------
31/7/05 by Stratovarius
*/ /** @file
Energy Missile
Psychokinesis [see text]
Level: Kineticist 2
Manifesting Time: 1 standard action
Range: Medium (100 ft. + 10 ft./ level)
Targets: Up to five creatures or objects; no two targets can be more than 15 ft. apart.
Duration: Instantaneous
Saving Throw: Reflex half or Fortitude half; see text
Power Resistance: Yes
Power Points: 3
Metapsionics: Empower, Maximize, Twin
Upon manifesting this power, you choose cold, electricity, fire, or sonic.
You release a powerful missile of energy of the chosen type at your foe. The
missile deals 3d6 points of damage to each creature or object you target, to
the maximum of five targets. You cannot hit the same target multiple times
with the same manifestation of this power.
Cold: A missile of this energy type deals +1 point of damage per die. The
saving throw to reduce damage from a cold missile is a Fortitude save
instead of a Reflex save.
Electricity: Manifesting a missile 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 missile of this energy type deals +1 point of damage per die.
Sonic: A missile of this energy type deals -1 point of damage per die and
ignores an objects hardness.
This powers subtype is the same as the type of energy you manifest.
Augment: For every additional power point you spend, this powers damage
increases by one die (d6) and its save DC increases by 1.
@todo 2da
*/
#include "psi_inc_psifunc"
#include "psi_inc_pwresist"
#include "psi_spellhook"
#include "prc_inc_spells"
#include "psi_inc_enrgypow"
void main()
{
/*
Spellcast Hook Code
Added 2004-11-02 by Stratovarius
If you want to make changes to all powers,
check psi_spellhook to find out more
*/
if (!PsiPrePowerCastCode())
{
// If code within the PrePowerCastHook (i.e. UMD) reports FALSE, do not run this spell
return;
}
// End of Spell Cast Hook
object oManifester = OBJECT_SELF;
struct manifestation manif =
EvaluateManifestation(oManifester, OBJECT_INVALID,
PowerAugmentationProfile(1,
1, PRC_UNLIMITED_AUGMENTATION
),
METAPSIONIC_EMPOWER | METAPSIONIC_MAXIMIZE | METAPSIONIC_TWIN
);
if(manif.bCanManifest)
{
struct energy_adjustments enAdj =
EvaluateEnergy(manif.nSpellID, POWER_ENERGYMISSILE_COLD, POWER_ENERGYMISSILE_ELEC, POWER_ENERGYMISSILE_FIRE, POWER_ENERGYMISSILE_SONIC,
VFX_IMP_FROST_L, VFX_IMP_LIGHTNING_M, VFX_IMP_FLAME_M, VFX_IMP_SONIC);
int nDC = GetManifesterDC(oManifester) + manif.nTimesGenericAugUsed + enAdj.nDCMod;
int nPen = GetPsiPenetration(oManifester) + enAdj.nPenMod;
int nNumberOfDice = 3 + manif.nTimesAugOptUsed_1;
int nDieSize = 6;
int nMissileCount = 5;
int nDamage, i;
location lTarget = PRCGetSpellTargetLocation();
float fRadius = FeetToMeters(15.0f);
float fDelay, fDistance;
effect eMissile = EffectVisualEffect(VFX_IMP_MIRV);
effect eVis = EffectVisualEffect(enAdj.nVFX2);
effect eDamage;
object oSelectedTarget = PRCGetSpellTargetObject();
object oTarget;
// Handle Twin Power
int nRepeats = manif.bTwin ? 2 : 1;
for(; nRepeats > 0; nRepeats--)
{
// Determine targets by looping over the area and sorting the hostiles in there according to distance from manifester
oTarget = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lTarget, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oTarget))
{
// Target only hostiles, and only ones that the manifester can see
if(oTarget != oManifester &&
oTarget != oSelectedTarget &&
spellsIsTarget(oTarget, SPELL_TARGET_SELECTIVEHOSTILE, oManifester) &&
GetObjectSeen(oTarget, oManifester)
)
{
AddToTargetList(oTarget, oManifester, INSERTION_BIAS_DISTANCE, FALSE);
}
// Get next potential target
oTarget = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lTarget, TRUE, OBJECT_TYPE_CREATURE);
}// end while - Target selection loop
// Hit the 5 first creatures in the list. Or a specifically selected target and 4 first
i = 0;
oTarget = GetIsObjectValid(oSelectedTarget) ?
oSelectedTarget :
GetTargetListHead(oManifester);
while((i++ < nMissileCount) && GetIsObjectValid(oTarget))
{
// Let the AI know
PRCSignalSpellEvent(oTarget, TRUE, manif.nSpellID, oManifester);
// Calculate base delay and do the missile VFX
fDelay = 0.1f * i;
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget));
// Make an SR check
if(PRCMyResistPower(oManifester, oTarget, nPen))
{
// Roll damage
nDamage = MetaPsionicsDamage(manif, nDieSize, nNumberOfDice, 0, enAdj.nBonusPerDie, TRUE, FALSE);
// Target-specific stuff
nDamage = GetTargetSpecificChangesToDamage(oTarget, 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, oTarget, nDC, enAdj.nSaveType))
{
if (GetHasMettle(oTarget, 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, oTarget, nDC, enAdj.nSaveType);
if(nDamage > 0)
{
eDamage = EffectDamage(nDamage, enAdj.nDamageType);
// Calculate delay
fDistance = GetDistanceBetween(oManifester, oTarget);
fDelay += fDistance / (3.0f * log(fDistance) + 2.0f);
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget));
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
}// end if - There was still damage remaining to be dealt after adjustments
}// end if - SR check
// Get next target from the list
oTarget = GetTargetListHead(oManifester);
}// end while - Effect application loop
// Clear the target list, so it will be empty for the second round of a Twinned power
PurgeTargetList(oManifester);
}// end if - Twin Power
}// end if - Successfull manifestation
}