forked from Jaysyn/PRC8
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.
180 lines
7.6 KiB
Plaintext
180 lines
7.6 KiB
Plaintext
/*
|
||
----------------
|
||
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 object’s hardness.
|
||
|
||
This power’s subtype is the same as the type of energy you manifest.
|
||
|
||
Augment: For every additional power point you spend, this power’s 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
|
||
}
|