PRC8/nwn/nwnprc/trunk/newspellbook/inv_hideous_blow.nss
Jaysyn904 2caeb8941c 2025/05/13 Update
Updated TF Shadowlord's prereq 2da.
Fixed CW Samurai's TWF levelup issue.
Added CW Samurai's skill 2DA back in.
Cleaned up ECL 2DA.
Fixed prereq bug with Imp Crit Eagle Claw.
Added Ability Focus feats for all Shapes, Essences & Invocations with DCs.
Fixed bug with 6th slot of crafting spells prereqs.
Added Reth Dekala HD to Initiator total.
Removed Dark Sun race files.
Updated all racial outsiders, monstrous humanoids, aberrations, giants, humanoids and fey to have the correct weapon & armor profs.
2025-05-13 23:05:31 -04:00

267 lines
12 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Name Eldritch Blast - Hideous Blow
//:: FileName inv_hideous_blow.nss
//:://////////////////////////////////////////////
#include "prc_inc_sp_tch"
#include "inv_inc_invfunc"
#include "prc_inc_combat"
#include "inv_invokehook"
//internal function for delayed damage
void DoDelayedBlast(object oTarget, int nDamageType = DAMAGE_TYPE_FIRE, int nVFX = VFX_IMP_FLAME_M)
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(2), nDamageType), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(nVFX), oTarget);
}
void main()
{
if(!PreInvocationCastCode()) return;
object oPC = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
int nEssence = GetLocalInt(oPC, "BlastEssence");
int nEssence2 = GetLocalInt(oPC, "BlastEssence2");
int nEssenceData = GetLocalInt(oPC, "EssenceData");
int nEssenceData2 = GetLocalInt(oPC, "EssenceData2");
effect eEssence;
//remove Corrupting Blast essence - it's a one-shot power
if(nEssence == INVOKE_CORRUPTING_BLAST)
DeleteLocalInt(oPC, "BlastEssence");
else if(nEssence2 == INVOKE_CORRUPTING_BLAST)
DeleteLocalInt(oPC, "BlastEssence2");
//calculate DC for essence effects
int nInvLevel = GetInvokerLevel(oPC, CLASS_TYPE_WARLOCK);
int nBlastLvl = PRCMin((nInvLevel + 1) / 2, 9);
nBlastLvl = PRCMax(PRCMax(nEssenceData & 0xF, nEssenceData2 & 0xF), nBlastLvl);
int nDC = 10 + nBlastLvl + GetAbilityModifier(ABILITY_CHARISMA);
if(GetHasFeat(FEAT_LORD_OF_ALL_ESSENCES)) nDC += 2;
nDC += InvokerAbilityFocus(oPC, nEssence, nEssence2);
int nDamageType = nEssence ? (nEssenceData >>> 4) & 0xFFF : DAMAGE_TYPE_MAGICAL;
int nDamageType2 = nEssence2 ? (nEssenceData2 >>> 4) & 0xFFF : DAMAGE_TYPE_MAGICAL;
//Set correct blast damage type
if(nDamageType != nDamageType2)
{
if(nDamageType != DAMAGE_TYPE_MAGICAL)
{
if(nDamageType2 == DAMAGE_TYPE_MAGICAL)
nDamageType2 = nDamageType;
}
else if(nDamageType2 != DAMAGE_TYPE_MAGICAL)
{
nDamageType = nDamageType2;
}
}
//get beam and impact vfx
int nBeamVFX, nVis;
switch(nDamageType)
{
case DAMAGE_TYPE_FIRE: nBeamVFX = VFX_BEAM_FIRE; nVis = VFX_IMP_FLAME_M; break;
case DAMAGE_TYPE_COLD: nBeamVFX = VFX_BEAM_COLD; nVis = VFX_IMP_FROST_S; break;
case DAMAGE_TYPE_ACID: nBeamVFX = VFX_BEAM_DISINTEGRATE; nVis = VFX_IMP_ACID_S; break;
case DAMAGE_TYPE_NEGATIVE: nBeamVFX = VFX_BEAM_BLACK; nVis = VFX_IMP_NEGATIVE_ENERGY; break;
default: nBeamVFX = VFX_BEAM_DISINTEGRATE; nVis = VFX_IMP_LIGHTNING_S; break;
}
effect eVis = EffectVisualEffect(nVis);
//add second vfx if needed
if(nDamageType != nDamageType2)
{
switch(nDamageType2)
{
case DAMAGE_TYPE_FIRE: nVis = VFX_IMP_FLAME_M; break;
case DAMAGE_TYPE_COLD: nVis = VFX_IMP_FROST_S; break;
case DAMAGE_TYPE_ACID: nVis = VFX_IMP_ACID_S; break;
case DAMAGE_TYPE_NEGATIVE: nVis = VFX_IMP_NEGATIVE_ENERGY; break;
}
eVis = EffectLinkEffects(eVis, EffectVisualEffect(nVis));
}
int nDam = d6(GetBlastDamageDices(oPC, nInvLevel));
if(GetHasSpellEffect(INVOKE_WILD_FRENZY, oPC))
nDam += 2;
int nAtkBns;
if(GetHasFeat(FEAT_ELDRITCH_SCULPTOR))
nAtkBns += 2;
//Penetrating Blast
int nPenetr = nInvLevel + SPGetPenetr();
if(nEssence == INVOKE_PENETRATING_BLAST || nEssence2 == INVOKE_PENETRATING_BLAST)
nPenetr += 4;
//Bane Blast
int nRace = MyPRCGetRacialType(oTarget);
if(nRace == ((nEssenceData >>> 16) & 0xFF) - 1
|| nRace == ((nEssenceData2 >>> 16) & 0xFF) - 1)
nDam += d6(2);
int nHellFire = 0;
if(GetIsHellFireBlast(oPC))
{
if(HellFireConDamage(oPC))
{
nHellFire = GetLevelByClass(CLASS_TYPE_HELLFIRE_WARLOCK, oPC) * 2;
nBeamVFX = VFX_BEAM_FIRE;
}
}
//Hammer Blast
if(GetObjectType(oTarget) != OBJECT_TYPE_CREATURE && nEssence != INVOKE_HAMMER_BLAST && nEssence2 != INVOKE_HAMMER_BLAST)
{
nDam /= 2;
if(nDam < 1) nDam = 1;
nHellFire /= 2;
}
if(!GetIsReactionTypeFriendly(oTarget))
{
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(oPC, INVOKE_HIDEOUS_BLOW));
int nWpnDmgType = GetWeaponDamageType(oWeapon);
PerformAttack(oTarget, oPC, eVis, 0.0, nAtkBns, 0, nWpnDmgType, "*Hideous Blow Hit*", "*Hideous Blow Miss*", FALSE, oWeapon);
int iAttackRoll = GetLocalInt(oTarget, "PRCCombat_StruckByAttack");
if(iAttackRoll)
{
//Make SR Check
int iSR = PRCDoResistSpell(oPC, oTarget, nPenetr);
if(!iSR)
{
//Apply secondary effects from essence invocations
if(nEssence == INVOKE_PENETRATING_BLAST || nEssence2 == INVOKE_PENETRATING_BLAST)
{
eEssence = EffectSpellResistanceDecrease(5);
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, TurnsToSeconds(1));
}
if((nEssence == INVOKE_HINDERING_BLAST || nEssence2 == INVOKE_HINDERING_BLAST) && PRCGetIsAliveCreature(oTarget))
{
eEssence = EffectSlow();
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, RoundsToSeconds(1));
}
if(nEssence == INVOKE_BINDING_BLAST || nEssence2 == INVOKE_BINDING_BLAST)
{
eEssence = EffectStunned();
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, RoundsToSeconds(1));
}
if(nEssence == INVOKE_BEWITCHING_BLAST || nEssence2 == INVOKE_BEWITCHING_BLAST)
{
eEssence = PRCEffectConfused();
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_MIND_SPELLS))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, RoundsToSeconds(1));
}
if((nEssence == INVOKE_BESHADOWED_BLAST || nEssence2 == INVOKE_BESHADOWED_BLAST) && PRCGetIsAliveCreature(oTarget))
{
eEssence = EffectBlindness();
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, RoundsToSeconds(1));
}
if((nEssence == INVOKE_HELLRIME_BLAST || nEssence2 == INVOKE_HELLRIME_BLAST))
{
eEssence = EffectAbilityDecrease(ABILITY_DEXTERITY, 4);
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, TurnsToSeconds(10));
}
if(nEssence == INVOKE_UTTERDARK_BLAST || nEssence2 == INVOKE_UTTERDARK_BLAST)
{
eEssence = EffectNegativeLevel(2);
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, HoursToSeconds(1));
}
if(nEssence == INVOKE_FRIGHTFUL_BLAST || nEssence2 == INVOKE_FRIGHTFUL_BLAST)
{
effect eDur2 = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
effect eFear = EffectFrightened();
effect eAttackD = EffectAttackDecrease(2);
effect eDmgD = EffectDamageDecrease(2,DAMAGE_TYPE_BLUDGEONING|DAMAGE_TYPE_PIERCING|DAMAGE_TYPE_SLASHING);
effect SaveD = EffectSavingThrowDecrease(SAVING_THROW_ALL,2);
effect Skill = EffectSkillDecrease(SKILL_ALL_SKILLS,2);
eEssence = EffectLinkEffects(eDmgD, eDur2);
eEssence = EffectLinkEffects(eEssence, eAttackD);
eEssence = EffectLinkEffects(eEssence, SaveD);
eEssence = EffectLinkEffects(eEssence, eFear);
eEssence = EffectLinkEffects(eEssence, Skill);
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_FEAR))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, TurnsToSeconds(1));
}
if(nEssence == INVOKE_NOXIOUS_BLAST || nEssence2 == INVOKE_NOXIOUS_BLAST)
{
eEssence = EffectDazed();
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, TurnsToSeconds(1));
}
if(nEssence == INVOKE_CORRUPTING_BLAST || nEssence2 == INVOKE_CORRUPTING_BLAST)
{
if(CheckTurnUndeadUses(oPC, 1))
{
int nRed = GetLevelByClass(CLASS_TYPE_ELDRITCH_DISCIPLE, oPC) / 2;
if(nRed < 1) nRed = 1;
eEssence = EffectSavingThrowDecrease(SAVING_THROW_WILL, nRed);
eEssence = EffectLinkEffects(eEssence, EffectVisualEffect(VFX_DUR_MIND_AFFECTING_NEGATIVE));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, RoundsToSeconds(1));
}
else
SpeakStringByStrRef(40550);//"This ability is tied to your turn undead ability, which has no more uses for today."
}
if((nEssence == INVOKE_SICKENING_BLAST || nEssence2 == INVOKE_SICKENING_BLAST) && PRCGetIsAliveCreature(oTarget))
{
eEssence = EffectSickened();
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_SPELL))
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eEssence, oTarget, 60.0);
}
if((nEssence == INVOKE_BRIMSTONE_BLAST || nEssence2 == INVOKE_BRIMSTONE_BLAST) && !GetLocalInt(oTarget, "BrimstoneFire"))
{
if(!PRCMySavingThrow(SAVING_THROW_REFLEX, oTarget, nDC, SAVING_THROW_TYPE_FIRE))
{
SetLocalInt(oTarget, "BrimstoneFire", TRUE);
int nDuration = nInvLevel / 5;
DelayCommand(RoundsToSeconds(nDuration), DeleteLocalInt(oTarget, "BrimstoneFire"));
int i;
float fRound = RoundsToSeconds(1);
for(i = 1; i <= nDuration; i++)
{
DelayCommand(fRound * i, DoDelayedBlast(oTarget));
}
}
}
//Apply the VFX impact
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
}
//Vitriolic ignores SR
if(nEssence == INVOKE_VITRIOLIC_BLAST || nEssence2 == INVOKE_VITRIOLIC_BLAST)
{
//Apply the VFX impact
if(iSR) ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
//Apply secondary effect from essence invocations
int nDuration = nInvLevel / 5;
int i;
float fRound = RoundsToSeconds(1);
for(i = 1; i <= nDuration; i++)
{
DelayCommand(fRound * i, DoDelayedBlast(oTarget, DAMAGE_TYPE_ACID, VFX_IMP_ACID_S));
}
}
//Apply damage effect
ApplyBlastDamage(oPC, oTarget, iAttackRoll, iSR, nDam, nDamageType, nDamageType2, nHellFire);
}
//Apply Spellblast or Greatreach Blast effect
DoSpellBlast(oPC, iAttackRoll);
}
}