Further file organization
Further file organization
This commit is contained in:
197
nwn/nwnprc/trunk/scripts/prc_gfkill_fattk.nss
Normal file
197
nwn/nwnprc/trunk/scripts/prc_gfkill_fattk.nss
Normal file
@@ -0,0 +1,197 @@
|
||||
//: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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user