forked from Jaysyn/PRC8
215 lines
8.6 KiB
Plaintext
215 lines
8.6 KiB
Plaintext
|
/////////////////////////////////////////////
|
|||
|
// Alchemist's Frost
|
|||
|
// sp_alcfrost.nss
|
|||
|
/////////////////////////////////////////////
|
|||
|
/*
|
|||
|
Alchemist<EFBFBD>s Frost: A thin liquid that grows extremely cold when exposed to air, alchemist<73>s frost
|
|||
|
functions like alchemists fire except that it deals 1d8 points of cold damage on a direct hit (and
|
|||
|
1 point of cold damage on a splash), 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 AddFrostEffectToWeapon(object oTarget, float fDuration)
|
|||
|
{
|
|||
|
// If the spell is cast again, any previous itemproperties matching are removed.
|
|||
|
IPSafeAddItemProperty(oTarget, ItemPropertyDamageBonus(IP_CONST_DAMAGETYPE_COLD, IP_CONST_DAMAGEBONUS_1d8), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
|
|||
|
IPSafeAddItemProperty(oTarget, ItemPropertyVisualEffect(ITEM_VISUAL_COLD), 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));
|
|||
|
AddFrostEffectToWeapon(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_FROST_S, VFX_IMP_FROST_L, DAMAGE_TYPE_COLD ,RADIUS_SIZE_HUGE, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
|
|||
|
}
|
|||
|
|
|||
|
}
|