239 lines
7.6 KiB
Plaintext
239 lines
7.6 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: Epic Dragon Breath
|
|
//:: x2_s2_edragbrth
|
|
//:: Copyright (c) 2001 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Calculates the proper damage and DC Save for the
|
|
breath weapon based on the HD of the dragon.
|
|
|
|
This spell is only intended to be used by the
|
|
shifter's/druids dragon breath ability
|
|
|
|
Druid's without at least 10 levels of shifter
|
|
will do 4 dice damage less than a true shifter
|
|
|
|
Green Dragon Gas also poisons the creatures
|
|
to make up for its lower damage
|
|
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Georg Zoeller
|
|
//:: Created On: 2003-Oct-14
|
|
//:://////////////////////////////////////////////
|
|
#include "NW_I0_SPELLS"
|
|
#include "X0_i0_spells"
|
|
#include "x2_inc_shifter"
|
|
void main()
|
|
{
|
|
int nAge;
|
|
int bShifter = (GetLevelByClass(CLASS_TYPE_SHIFTER,OBJECT_SELF)>=10);
|
|
int bPoison = FALSE;
|
|
|
|
/* This totally doesn't work right, GetHasFeat has been incorrectly used.
|
|
If this is the last use per day of Dragon Shape, GetHasFeat will return 0
|
|
because it is no longer useable. Therefore, the damage calculation will be wrong.
|
|
// -------------------------------------------------------------------------
|
|
// We assume this spell is only used in dragon form
|
|
// -------------------------------------------------------------------------
|
|
if (GetHasFeat(873,OBJECT_SELF))
|
|
{
|
|
nAge = GetLevelByClass(CLASS_TYPE_DRUID,OBJECT_SELF) + GetLevelByClass(CLASS_TYPE_SHIFTER,OBJECT_SELF);
|
|
}
|
|
// -------------------------------------------------------------------------
|
|
// .. this case should never happen, but people do strange things with
|
|
// the toolset
|
|
// -------------------------------------------------------------------------
|
|
else if (GetIsPC(OBJECT_SELF))
|
|
{
|
|
nAge = GetHitDice(OBJECT_SELF)/2;
|
|
}
|
|
else
|
|
{
|
|
nAge = GetHitDice(OBJECT_SELF);
|
|
}
|
|
*/
|
|
// This should work better.
|
|
nAge = GetLevelByClass(CLASS_TYPE_DRUID,OBJECT_SELF) + GetLevelByClass(CLASS_TYPE_SHIFTER,OBJECT_SELF);
|
|
// Just in case...
|
|
if (nAge==0)
|
|
{
|
|
if (GetIsPC(OBJECT_SELF))
|
|
{
|
|
nAge = GetHitDice(OBJECT_SELF)/2;
|
|
}
|
|
else
|
|
{
|
|
nAge = GetHitDice(OBJECT_SELF);
|
|
}
|
|
}
|
|
|
|
int nDice;
|
|
int nDamage;
|
|
int nDamageDice;
|
|
int nDC;
|
|
// -------------------------------------------------------------------------
|
|
// Your damage dice and save DC are dependent on your hit dice
|
|
// -------------------------------------------------------------------------
|
|
if (nAge <= 6) //Wyrmling
|
|
{
|
|
nDice = 2;
|
|
}
|
|
else if (nAge >= 7 && nAge <= 9) //Very Young
|
|
{
|
|
nDice = 4;
|
|
}
|
|
else if (nAge >= 10 && nAge <= 12) //Young
|
|
{
|
|
nDice = 6;
|
|
}
|
|
else if (nAge >= 13 && nAge <= 15) //Juvenile
|
|
{
|
|
nDice = 12;
|
|
}
|
|
else if (nAge >= 16 && nAge <= 18) //Young Adult
|
|
{
|
|
nDice = 16;
|
|
}
|
|
else if (nAge >= 19 && nAge <= 21) //Adult
|
|
{
|
|
nDice = 20;
|
|
}
|
|
else if (nAge >= 22 && nAge <= 24) //Mature Adult
|
|
{
|
|
nDice = 24;
|
|
}
|
|
else if (nAge >= 25 && nAge <= 27) //Old
|
|
{
|
|
nDice = 28;
|
|
}
|
|
else if (nAge >= 28 && nAge <= 30) //Very Old
|
|
{
|
|
nDice = 32;
|
|
}
|
|
else if (nAge >= 31 && nAge <= 33) //Ancient
|
|
{
|
|
nDice = 36;
|
|
}
|
|
else if (nAge >= 34 && nAge <= 37) //Wyrm
|
|
{
|
|
nDice = 40;
|
|
}
|
|
else if (nAge > 37 && nAge <40) //Great Wyrm
|
|
{
|
|
nDice = 44;
|
|
}
|
|
else
|
|
{
|
|
nDice = 48;
|
|
}
|
|
|
|
nDC = ShifterGetSaveDC(OBJECT_SELF,SHIFTER_DC_NORMAL,TRUE);
|
|
|
|
if (!bShifter) // a shifter is a bit better at controlling this weapon
|
|
{
|
|
nDice -=4;
|
|
nDC -=4;
|
|
}
|
|
|
|
int nSpellId= GetSpellId();
|
|
int nVis;
|
|
int nType;
|
|
int nSave;
|
|
|
|
if (nSpellId == 796) // lightning
|
|
{
|
|
nVis = VFX_IMP_LIGHTNING_S;
|
|
nType = DAMAGE_TYPE_ELECTRICAL;
|
|
nSave = SAVING_THROW_TYPE_ELECTRICITY;
|
|
nDamageDice = 8;
|
|
}
|
|
else if (nSpellId == 797) // fire
|
|
{
|
|
nVis = VFX_IMP_FLAME_M;
|
|
nType = DAMAGE_TYPE_FIRE;
|
|
nSave = SAVING_THROW_TYPE_FIRE;
|
|
nDamageDice = 10;
|
|
}
|
|
else //gas
|
|
{
|
|
nVis = VFX_IMP_POISON_L;
|
|
nType = DAMAGE_TYPE_ACID;
|
|
nSave = SAVING_THROW_TYPE_ACID;
|
|
nDamageDice = 6;
|
|
bPoison = TRUE;
|
|
}
|
|
|
|
effect eVis = EffectVisualEffect(nVis);
|
|
effect eDamage;
|
|
effect ePoison;
|
|
object oTarget;
|
|
int nDamStrike;
|
|
float fDelay;
|
|
//------------------------------------------------------------------
|
|
// Loop over all creatures, doors and placeables in the area of effect
|
|
//------------------------------------------------------------------
|
|
location lFinalTarget = GetSpellTargetLocation();
|
|
vector vFinalPosition;
|
|
if ( lFinalTarget == GetLocation(OBJECT_SELF) )
|
|
{
|
|
// Since the target and origin are the same, we have to determine the
|
|
// direction of the spell from the facing of OBJECT_SELF (which is more
|
|
// intuitive than defaulting to East everytime).
|
|
|
|
// In order to use the direction that OBJECT_SELF is facing, we have to
|
|
// instead we pick a point slightly in front of OBJECT_SELF as the target.
|
|
vector lTargetPosition = GetPositionFromLocation(lFinalTarget);
|
|
vFinalPosition.x = lTargetPosition.x + cos(GetFacing(OBJECT_SELF));
|
|
vFinalPosition.y = lTargetPosition.y + sin(GetFacing(OBJECT_SELF));
|
|
lFinalTarget = Location(GetAreaFromLocation(lFinalTarget),vFinalPosition,GetFacingFromLocation(lFinalTarget));
|
|
}
|
|
|
|
oTarget = GetFirstObjectInShape(SHAPE_SPELLCONE, 15.0, lFinalTarget, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE);
|
|
while (GetIsObjectValid(oTarget))
|
|
{
|
|
if(oTarget != OBJECT_SELF && spellsIsTarget(oTarget,SPELL_TARGET_STANDARDHOSTILE, OBJECT_SELF))
|
|
{
|
|
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
|
fDelay = GetDistanceBetween(OBJECT_SELF, oTarget)/20;
|
|
|
|
//------------------------------------------------------------------
|
|
// Calculate and Apply Reflex Save Adjusted Damage
|
|
//------------------------------------------------------------------
|
|
switch ( nDamageDice )
|
|
{
|
|
case 6:
|
|
nDamage = d6(nDice);
|
|
break;
|
|
case 8:
|
|
nDamage = d8(nDice);
|
|
break;
|
|
case 10:
|
|
nDamage = d10(nDice);
|
|
break;
|
|
}
|
|
nDamStrike = GetReflexAdjustedDamage(nDamage,oTarget, nDC,nSave, OBJECT_SELF);
|
|
if(nDamStrike > 0)
|
|
{
|
|
|
|
eDamage = EffectDamage(nDamStrike, nType);
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT,eDamage,oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,oTarget));
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// Green Dragon Breath is poisonous for creatures!
|
|
//------------------------------------------------------------------
|
|
if (bPoison && GetObjectType(oTarget) ==OBJECT_TYPE_CREATURE)
|
|
{
|
|
ePoison = EffectPoison(44);
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_INSTANT,eVis,oTarget));
|
|
DelayCommand(fDelay, ApplyEffectToObject(DURATION_TYPE_PERMANENT,ePoison,oTarget));
|
|
}
|
|
}
|
|
oTarget = GetNextObjectInShape(SHAPE_SPELLCONE, 15.0, lFinalTarget, OBJECT_TYPE_CREATURE | OBJECT_TYPE_DOOR | OBJECT_TYPE_PLACEABLE );
|
|
}
|
|
}
|
|
|
|
|