PRC8/nwn/nwnprc/trunk/spells/sp_alcspark.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

214 lines
8.8 KiB
Plaintext
Raw 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.

//////////////////////////////////////////////////////
// Alchemist's Spark
// sp_alcspark.nss
//////////////////////////////////////////////////////
/*
Alchemists Spark: Alchemists spark combines two substances that react violently when mixed.
A flask of alchemists spark has two compartments that keep the two substances separate;
throwing the flask shatters it and allows the substances to mix, releasing a powerful electrical
discharge. Otherwise, alchemical sparl functions like alchemists fire except that it deals 1d8
points of electricity damage on a direct hit (and 1 point of electricity damage to those it splashes),
rather than fire damage. It deals no additional damage after the initial damage.
*/
#include "prc_inc_sp_tch"
//::///////////////////////////////////////////////
//:: PRCDoGrenade
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Does a damage type grenade (direct or splash on miss)
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On:
//:://////////////////////////////////////////////
void PRCDoGrenade(int nDirectDamage, int nSplashDamage, int vSmallHit, int vRingHit, int nDamageType, float fExplosionRadius , int nObjectFilter, int nRacialType=RACIAL_TYPE_ALL)
{
//Declare major variables ( fDist / (3.0f * log( fDist ) + 2.0f) )
object oTarget = PRCGetSpellTargetObject();
int nCasterLvl = PRCGetCasterLevel(OBJECT_SELF);
int nDamage = 0;
int nMetaMagic = PRCGetMetaMagicFeat();
int nCnt;
effect eMissile;
effect eVis = EffectVisualEffect(vSmallHit);
location lTarget = PRCGetSpellTargetLocation();
float fDist = GetDistanceBetween(OBJECT_SELF, oTarget);
int nTouch;
if (GetIsObjectValid(oTarget) == TRUE)
{
/* // * BK September 27 2002
// * if the object is 'far' from the original impact it
// * will be an automatic miss too
location lObject = GetLocation(oTarget);
float fDistance = GetDistanceBetweenLocations(lTarget, lObject);
// SpawnScriptDebugger();
if (fDistance > 1.0)
{
nTouch = -1;
}
else
This did not work. The location and object location are the same.
For now we'll have to live with the possiblity of the 'explosion'
happening away from where the grenade hits.
We could convert everything to splash...
*/
nTouch = PRCDoRangedTouchAttack(oTarget);
}
else
{
nTouch = -1; // * this means that target was the ground, so the user
// * intended to splash
}
if (nTouch >= 1)
{
//Roll damage
int nDam = nDirectDamage;
if(nTouch == 2)
{
nDam *= 2;
}
//Set damage effect
effect eDam = EffectDamage(nDam, nDamageType);
//Apply the MIRV and damage effect
// * only damage enemies
if(spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE,OBJECT_SELF) )
{
// * must be the correct racial type (only used with Holy Water)
if ((nRacialType != RACIAL_TYPE_ALL) && (nRacialType == MyPRCGetRacialType(oTarget)))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, PRCGetSpellId()));
//ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget); VISUALS outrace the grenade, looks bad
}
else
if ((nRacialType == RACIAL_TYPE_ALL) )
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, PRCGetSpellId()));
//ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eVis, oTarget); VISUALS outrace the grenade, looks bad
}
}
// ApplyEffectToObject(DURATION_TYPE_INSTANT, eMissile, oTarget);
}
// *
// * Splash damage always happens as well now
// *
{
effect eExplode = EffectVisualEffect(vRingHit);
//Apply the fireball explosion at the location captured above.
/* float fFace = GetFacingFromLocation(lTarget);
vector vPos = GetPositionFromLocation(lTarget);
object oArea = GetAreaFromLocation(lTarget);
vPos.x = vPos.x - 1.0;
vPos.y = vPos.y - 1.0;
lTarget = Location(oArea, vPos, fFace);
missing code looks bad because it does not jive with visual
*/
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eExplode, lTarget);
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, fExplosionRadius, lTarget, TRUE, nObjectFilter);
//Cycle through the targets within the spell shape until an invalid object is captured.
while (GetIsObjectValid(oTarget))
{
if(spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE,OBJECT_SELF) )
{
float fDelay = GetDistanceBetweenLocations(lTarget, GetLocation(oTarget))/20;
//Roll damage for each target
nDamage = nSplashDamage;
//Set the damage effect
effect eDam = EffectDamage(nDamage, nDamageType);
if(nDamage > 0)
{
// * must be the correct racial type (only used with Holy Water)
if ((nRacialType != RACIAL_TYPE_ALL) && (nRacialType == MyPRCGetRacialType(oTarget)))
{
// Apply effects to the currently selected target.
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, PRCGetSpellId()));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
//This visual effect is applied to the target object not the location as above. This visual effect
//represents the flame that erupts on the target not on the ground.
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
}
else
if ((nRacialType == RACIAL_TYPE_ALL) )
{
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, PRCGetSpellId()));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget));
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget));
}
}
}
//Select the next target within the spell shape.
oTarget = GetNextObjectInShape(SHAPE_SPHERE, fExplosionRadius, lTarget, TRUE, nObjectFilter);
}
}
}
void AddSparkEffectToWeapon(object oTarget, float fDuration)
{
// If the spell is cast again, any previous itemproperties matching are removed.
IPSafeAddItemProperty(oTarget, ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_ELECTRICAL, IP_CONST_DAMAGEBONUS_1d8), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
IPSafeAddItemProperty(oTarget, ItemPropertyVisualEffect(ITEM_VISUAL_ELECTRICAL), fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE);
return;
}
void main()
{
effect eVis = EffectVisualEffect(VFX_IMP_PULSE_COLD);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE);
object oTarget = PRCGetSpellTargetObject();
object oMyWeapon;
int nTarget = GetObjectType(oTarget);
int nDuration = 4;
int nCasterLvl = 1;
if(nTarget == OBJECT_TYPE_ITEM)
{
oMyWeapon = oTarget;
int nItem = IPGetIsMeleeWeapon(oMyWeapon);
if(nItem == TRUE)
{
if(GetIsObjectValid(oMyWeapon))
{
SignalEvent(OBJECT_SELF, EventSpellCastAt(OBJECT_SELF, GetSpellId(), FALSE));
if (nDuration > 0)
{// haaaack: store caster level on item for the on hit spell to work properly
SetLocalInt(oMyWeapon,"X2_SPELL_CLEVEL_FLAMING_WEAPON",nCasterLvl);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, GetItemPossessor(oMyWeapon));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDur, GetItemPossessor(oMyWeapon), RoundsToSeconds(nDuration));
AddSparkEffectToWeapon(oMyWeapon, RoundsToSeconds(nDuration));
}
return;
}
}
else
{
FloatingTextStrRefOnCreature(100944,OBJECT_SELF);
}
}
else if(nTarget == OBJECT_TYPE_CREATURE || OBJECT_TYPE_DOOR || OBJECT_TYPE_PLACEABLE)
{
PRCDoGrenade(d8(1),1, VFX_IMP_LIGHTNING_S, VFX_IMP_LIGHTNING_M, DAMAGE_TYPE_ELECTRICAL ,RADIUS_SIZE_HUGE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
}
}