#include "x2_inc_spellhook"
//::////////////////////////////////////////////////////:://
//:: Invizible420's Alternate <span class="highlight">Timestop</span> Spell          //:://
//::                                                  //:://
//:: By: Invizible420                                 //:://
//:: Modified By: Shayan                                 //:://
//:: (Created 12/20/02 updated 12/08/04 (v 2.0)      //:://
//::////////////////////////////////////////////////////:://
//::                                                  //:://
//:: Persistent World Workaround for Bioware's        //:://
//:: Default <span class="highlight">Timestop</span> Spell.  This will Decrease      //:://
//:: Attack and Movement Speed, then CutSceneDominate //:://
//:: creatures within a radius of the caster.         //:://
//::                                                  //:://
//:: This version now uses the module to dominate the //:://
//:: the creatures, this stops PC from dominating     //:://
//:: other PC's.  Also added a fix to not dominate    //:://
//:: a caster's familiars.                            //:://
//::                                                  //:://
//:: Contact info/Bug Reports: Digiddy777@yahoo.com   //:://
//::////////////////////////////////////////////////////:://
#include "NW_I0_GENERIC"
float iInterval = 6.0; //the minimum time gap between casting Tmestops simulataneously.
// Customize User Defined Variables
float fDur   = IntToFloat(d4(4)); // Duration in seconds  //max is 16 seconds
float fDist  = 50.0; // Radius in meters
int iSlow    = 100;  // Percentage to decrease movement by
int iDAttack = 100;  // Amount to decrease attack by

// Has item in inventory to avoid the effects of a time stop.
int GetIsTimeStopImmune(object oCreature) {
    return (GetResRef(GetItemInSlot(INVENTORY_SLOT_CLOAK, oCreature)) == "sha_tsimmuneclok");
}

//Sends a message to all PCs and DMs in the area indicating that creature that did not freeze for
// Timestop is infact immune to it.
void SendTSImmuneMessageToPCs(object TSImmune)
{
    object oArea = GetArea(OBJECT_SELF);
    object oObj  = GetFirstObjectInShape(SHAPE_SPHERE, fDist, GetSpellTargetLocation(), FALSE, OBJECT_TYPE_CREATURE);
    while(GetIsObjectValid(oObj))
    {
        if(GetIsPC(oObj) || GetIsDM(oObj))
        {
            SendMessageToPC(oObj, GetName(TSImmune) + " is immune to Time Stop.");
        }
        oObj = GetNextObjectInShape(SHAPE_SPHERE, fDist, GetSpellTargetLocation(), FALSE, OBJECT_TYPE_CREATURE);
    }
}
// Function to resume creature(s) previous actions wrapped for Delay
void ResumeLast(object oResumee, object oIntruder)
    {
    // Delay DetermineCombatRound
    DelayCommand(fDur+0.25,AssignCommand(oResumee,DetermineCombatRound(oIntruder)));
    }
// Function to control <span class="highlight">TimeStop</span> effects
void TSEffects(object oEffector, object oCaster)
    {
    // Check if stopped creature is a hostile
    if (GetIsReactionTypeHostile(oCaster,oEffector) == TRUE && !GetIsPC(oEffector)) {
    // Start the resume combat round after <span class="highlight">Timestop</span>
            ResumeLast(oEffector, oCaster);
    }
    // Decrease the creature(s) attack
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectAttackDecrease(iDAttack,ATTACK_BONUS_MISC),oEffector,fDur);
    // <span class="highlight">Stop</span> the creature(s) from moving for fDur seconds
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectCutsceneImmobilize(),oEffector,fDur);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectCutsceneParalyze(),oEffector,fDur);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,SupernaturalEffect(EffectVisualEffect(VFX_DUR_FREEZE_ANIMATION)),oEffector,fDur);

    // Make module dominate the creature(s) for fDur seconds
 //   AssignCommand(GetModule(),ApplyEffectToObject(DURATION_TYPE_TEMPORARY,EffectCutsceneDominated(),oEffector,fDur));
    // Clear the creature(s) action que
    AssignCommand(oEffector,ClearAllActions(TRUE));
    // Disable Commandable (actions que)
    SetCommandable(FALSE,oEffector);
    // Enable Commandable after fDur
    DelayCommand(fDur,SetCommandable(TRUE,oEffector));
    }
// Function to get creature(s) within radius and apply the alternate <span class="highlight">TimeStop</span>
void TimeStop(object oTarget)
{
    object oNearestC;  // Define nearest creature
    // Begin loop to find all creatures within the fDist meter radius
    oNearestC = GetFirstObjectInShape(SHAPE_SPHERE, fDist, GetLocation(oTarget), FALSE, OBJECT_TYPE_CREATURE);
    while(GetIsObjectValid(oNearestC))
         {
         // To make sure it doesn't <span class="highlight">stop</span> the caster or caster's familiar
         string sNCName = GetName(oNearestC);
         if (oNearestC != oTarget)
             {
                int TSImmune = GetIsTimeStopImmune(oNearestC);
                if((oNearestC != OBJECT_SELF) && !TSImmune)
                {
                    // Start the <span class="highlight">TimeStop</span> effects
                    DelayCommand(0.75,TSEffects(oNearestC,oTarget));
                }
                else if((oNearestC != OBJECT_SELF) && TSImmune)
                {
                   SendTSImmuneMessageToPCs(oNearestC);
                }

             }
         // Get the next creature in the fDist meter radius and continue loop
         oNearestC = GetNextObjectInShape(SHAPE_SPHERE, fDist, GetLocation(oTarget), FALSE, OBJECT_TYPE_CREATURE);
         }
}
// Begin Main Function
void main()
{
    //Sorcerer Anti timestop spam code.  (referred to in j_inc_generic_ai)
    //Thanks to Valve O' Leen
      if(!GetIsPC(OBJECT_SELF) && !GetIsDM(OBJECT_SELF))
      {
         SetLocalInt(OBJECT_SELF, "SPELL_TS_CAST", TRUE);
         DelayCommand(fDur + iInterval, DeleteLocalInt(OBJECT_SELF, "SPELL_TS_CAST"));
      }
      //Signal event to start the <span class="highlight">TimeStop</span>
      SignalEvent(OBJECT_SELF, EventSpellCastAt(OBJECT_SELF, SPELL_TIME_STOP, FALSE));
      TimeStop(OBJECT_SELF);
      ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_TIME_STOP), GetSpellTargetLocation());
}