//: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);
}