PRC8/nwn/nwnprc/trunk/scripts/prc_gfkill_fattk.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

198 lines
8.5 KiB
Plaintext

//:Ghost-Faced Killer Frightful Attack
//
//Power Attack must be active.
//The attack must be a Sudden Strike (Sneak Attack.)
//The victim makes a Will Save (DC 10 + GFK class level + GFK Cha modifier.)
//If the victim fails the save, the victim dies of fright.
//If the victim succeeds, the victim becomes shaken for 1 round per GFK class
//level.
//Victims immune to mind-affecting effects, immune to fear, or with more Hit
//Dice than the GFK's character level are immune to this frightful attack.
//All onlookers in a 30 foot radius who are not the victim, the GFK, or allies
//of the GFK must make a will save (DC 10 + GFK class level + GFK Cha modifier
//+ damage modifier of power attack.)
//If the onlooker succeeds the will save, no effect is applied.
//If the onlooker has less Hit Dice than the GFK class level + GFK Cha modifier,
//and fails the save, the onlooker becomes panicked for 1 round per GFK class
//level.
//If the onlooker has more Hit Dice than the GFK class level + GFK Cha modifier,
//and fails the save, the onlooker becomes shaken for 1 round per GFK class
//level.
#include "prc_inc_combat"
void DoFrightfulAttack(object oPC, object oTarget);
void DelayFrightfulAttackCheck(object oPC, object oTarget) {
if(GetIsDead(oTarget)) {
float fGFKSize = StringToFloat(Get2DACache("appearance","PREFATCKDIST",GetAppearanceType(oPC)));
object oNewTarget;
oNewTarget = MyFirstObjectInShape(SHAPE_SPHERE, fGFKSize, GetLocation(oPC), TRUE);
if ( GetIsObjectValid(oNewTarget) ) {
if ( oNewTarget == oPC ) {
oNewTarget = MyNextObjectInShape(SHAPE_SPHERE, fGFKSize, GetLocation(oPC), TRUE);
}
}
if ( GetIsObjectValid(oNewTarget) ) {
if ( oNewTarget != oPC ) {
if ( GetCanSneakAttack(oNewTarget,oPC)) {
DoFrightfulAttack(oPC, oNewTarget);
} else {
effect eEffect;
PerformAttack(oNewTarget,oPC,eEffect);
}
}
}
}
}
void DoFrightfulAttack(object oPC, object oTarget) {
//Does the GFK have frightful cleave yet?
int iGFKFrightfulCleave = GetHasFeat( FEAT_FRIGHTFUL_CLEAVE, oPC );
//What is the GFK class level?
int iGFKClassLevel = GetLevelByClass(CLASS_TYPE_GHOST_FACED_KILLER, oPC);
//What is the GFK character level?
int iGFKCharacterLevel = GetHitDice(oPC);
//What is the Cha modifier?
int iGFKCharModifier = GetAbilityModifier(ABILITY_CHARISMA, oPC);
//What is the Hit Dice of the target?
int iTargetHD = GetHitDice(oTarget);
//Can the GFK use a Sudden Strike? (sneak attack)
int iSuddenStrike = GetCanSneakAttack(oTarget, oPC);
if ( ! iSuddenStrike ) {
//Replace all of these with FloatingTextStrRefOnCreature() later.
FloatingTextStrRefOnCreature(16832361, oPC, FALSE);
//FloatingTextStringOnCreature("Frightful Attack must be a Sudden Strike (Sneak Attack).", oPC, FALSE);
IncrementRemainingFeatUses(oPC, FEAT_FRIGHTFUL_ATTACK);
}
//What level of Power Attack did the GFK use while making this attack?
//Not sure if this is correct.
int iDamageBonus = GetLocalInt(oPC, "PRC_PowerAttack_Level");
if ( GetActionMode(oPC, ACTION_MODE_POWER_ATTACK) ) {
iDamageBonus = 5;
}
if ( GetActionMode(oPC, ACTION_MODE_IMPROVED_POWER_ATTACK) ) {
iDamageBonus = 10;
}
if ( iDamageBonus <= 0 ) {
//Replace all of these with FloatingTextStrRefOnCreature() later.
FloatingTextStrRefOnCreature(16832362, oPC, FALSE);
//FloatingTextStringOnCreature("Power Attack must be active to use Frightful Attack.", oPC, FALSE);
IncrementRemainingFeatUses(oPC, FEAT_FRIGHTFUL_ATTACK);
}
//Is the target immune to mind-affecting effects?
int iTargetIMA = GetIsImmune(oTarget, IMMUNITY_TYPE_MIND_SPELLS, OBJECT_INVALID);
//Is the target immune to fear?
int iTargetIF = GetIsImmune(oTarget, IMMUNITY_TYPE_FEAR, OBJECT_INVALID);
if ( iSuddenStrike && iDamageBonus > 0 ) {
effect eEffect;
if ( ! iTargetIF && ! iTargetIMA ) {
if ( iTargetHD < iGFKCharacterLevel ) {
//We use PerformAttack from prc_inc_combat to make this easier
//eShaken = EffectShaken();
//eDeath = EffectDeath(TRUE,FALSE);
int iSave = PRCMySavingThrow( SAVING_THROW_WILL, oTarget, 10 + iGFKClassLevel + iGFKCharModifier, SAVING_THROW_TYPE_FEAR);
if ( iSave < 2 ) {
if ( iSave == 0 ) {
eEffect = EffectDeath(TRUE,FALSE);
}
else if (GetHasMettle(oTarget, SAVING_THROW_WILL)) // Ignores partial effects
{
eEffect = EffectVisualEffect(VFX_IMP_WILL_SAVING_THROW_USE);
}
else
{
eEffect = EffectShaken();
}
PerformAttack(oTarget, oPC, eEffect, IntToFloat(iGFKClassLevel));
} else {
//Should NEVER enter this code, but here for sanity
PerformAttack(oTarget, oPC, eEffect);
//Replace all of these with FloatingTextStrRefOnCreature() later.
FloatingTextStrRefOnCreature(16832363, oPC, FALSE);
//FloatingTextStringOnCreature("Failed Frightful Attack: Target is immune to fear.", oPC, FALSE);
}
} else {
PerformAttack(oTarget, oPC, eEffect);
//Replace all of these with FloatingTextStrRefOnCreature() later.
FloatingTextStrRefOnCreature(16832364, oPC, FALSE);
//FloatingTextStringOnCreature("Failed Frightful Attack: Target has too many Hit Dice.", oPC, FALSE);
}
} else {
PerformAttack(oTarget, oPC, eEffect);
//Replace all of these with FloatingTextStrRefOnCreature() later.
//16832365
//FloatingTextStringOnCreature("Failed Frightful Attack: Target must not be immune to sneak attacks, mind affecting effects, or fear.", oPC, FALSE);
FloatingTextStrRefOnCreature(16832365, oPC, FALSE);
}
//Frighten the onlookers.
//int nDamage;
effect eVis = EffectVisualEffect(VFX_IMP_FEAR_S);
effect eFearE = EffectFrightened();
effect eShakenE = EffectShaken();
effect eMind = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_FEAR);
effect eImpact = EffectVisualEffect(VFX_FNF_LOS_NORMAL_20);
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
float fDelay;
float fDuration = RoundsToSeconds( iGFKClassLevel );
//Link the fear and mind effects
effect eLink1 = EffectLinkEffects(eFearE, eMind);
effect eFear = EffectLinkEffects(eLink1, eDur);
effect eLink2 = EffectLinkEffects(eShakenE, eMind);
effect eShaken = EffectLinkEffects(eLink2, eDur);
//Apply Impact
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eImpact, GetSpellTargetLocation());
object oCurrentTarget;
//Get first target in the spell cone
oCurrentTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, GetSpellTargetLocation(), TRUE);
while(GetIsObjectValid(oCurrentTarget)) {
fDelay = PRCGetRandomDelay();
//The victim (oTarget) the Ghost-Faced Killer (oPC), and allies of the Ghost-Faced Killer are unaffected.
if((oCurrentTarget != oTarget) && (!GetIsFriend(oCurrentTarget, oPC)) && (oCurrentTarget != oPC)) {
//Make a will save
if(!PRCMySavingThrow(SAVING_THROW_WILL, oCurrentTarget, 10 + iGFKClassLevel + iGFKCharModifier + iDamageBonus, SAVING_THROW_TYPE_FEAR, OBJECT_SELF, fDelay)) {
//Apply the linked effects and the VFX impact
int iCurrentHD = GetHitDice( oCurrentTarget );
if ( iCurrentHD < ( iGFKClassLevel + iGFKCharModifier ) ) {
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eFear, oCurrentTarget, fDuration, TRUE, -1, -1));
} else {
DelayCommand(fDelay, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eShaken, oCurrentTarget, fDuration, TRUE, -1, -1));
}
}
}
//Get next target in the spell cone
oCurrentTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, GetSpellTargetLocation(), TRUE);
}
}
//delay this to see if we need to cleave
if(iGFKFrightfulCleave) {
DelayCommand(0.01, DelayFrightfulAttackCheck(oPC, oTarget));
}
}
void main() {
object oPC = OBJECT_SELF;
object oTarget = PRCGetSpellTargetObject();
//Is the player trying to Frightful Attack himself?
if(oPC == oTarget) {
IncrementRemainingFeatUses(oPC, FEAT_FRIGHTFUL_ATTACK);
return;
}
DoFrightfulAttack(oPC, oTarget);
}