// vamp_death - vampire death for a vampire PC
// modified 06/16/2004 Jeremy Greene
// modified 04/26/2005 Deva Winblood
#include "x2_inc_itemprop"
#include "hos_respawn_h"
#include "prc_inc_skin"

void fnFleeToCoffin();
void fnTrueDeath();
void fnDieInTwoHours();

////////////////////////////////////////////////////////////////////// MAIN
void main()
{
    object oMe=OBJECT_SELF;
    object oKiller=GetLastKiller();
    object oCoffin=GetLocalObject(oMe,"oCoffin");
    int bIsDay=GetIsDay();
    object oNear=GetNearestObjectByTag("RTS_SURFACE",oMe,1);
    SetLocalObject(oMe,"oKiller",oKiller);
    SetIsTemporaryFriend(oKiller,oMe,TRUE,20.0);
    if (oCoffin!=OBJECT_INVALID)
    {
      if (bIsDay==TRUE&&oNear!=OBJECT_INVALID) fnTrueDeath();
      else { fnFleeToCoffin(); DelayCommand(HoursToSeconds(2),fnDieInTwoHours());}
    }
    else { fnTrueDeath(); }
}
///////////////////////////////////////////////////////////////////// MAIN

void fnDieInTwoHours()
{
  if (GetLocalInt(OBJECT_SELF,"nVampMist")==TRUE)
  { // you have died
    SendMessageToPC(OBJECT_SELF,"You failed to make it back to your coffin within 2 hours and have died the true death.");
    AssignCommand(OBJECT_SELF,fnTrueDeath());
  } // you have died
} // fnDieInTwoHours()


void Raise(object oPlayer)
{
        effect eVisual = EffectVisualEffect(VFX_IMP_RESTORATION);

        effect eBad = GetFirstEffect(oPlayer);
        ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectResurrection(),oPlayer);
        ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectHeal(GetMaxHitPoints(oPlayer)), oPlayer);

        //Search for negative effects
        while(GetIsEffectValid(eBad))
        {
            if (GetEffectType(eBad) == EFFECT_TYPE_ABILITY_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_AC_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_ATTACK_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_SAVING_THROW_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_SKILL_DECREASE ||
                GetEffectType(eBad) == EFFECT_TYPE_BLINDNESS ||
                GetEffectType(eBad) == EFFECT_TYPE_DEAF ||
                GetEffectType(eBad) == EFFECT_TYPE_PARALYZE ||
                GetEffectType(eBad) == EFFECT_TYPE_NEGATIVELEVEL)
                {
                    //Remove effect if it is negative.
                    RemoveEffect(oPlayer, eBad);
                }
            eBad = GetNextEffect(oPlayer);
        }
        //Fire cast spell at event for the specified target
        SignalEvent(oPlayer, EventSpellCastAt(OBJECT_SELF, SPELL_RESTORATION, FALSE));
        ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, oPlayer);
}

void fnGhost()
{
  object oMe=OBJECT_SELF;
  effect eCutsceneDominated=EffectInvisibility(INVISIBILITY_TYPE_IMPROVED);
  effect eCutsceneGhost=EffectCutsceneGhost();
  effect eInvis=EffectVisualEffect(VFX_DUR_GHOST_TRANSPARENT);
  effect eFast=EffectMovementSpeedIncrease(99);
  effect eMist=EffectVisualEffect(VFX_DUR_GHOST_SMOKE_2);
  effect eSanctuary=EffectSanctuary(1000);
  effect eDamage;
  effect eSilence=EffectSilence();
  effect eConcealment=EffectConcealment(100);
  if (GetLocalInt(oMe,"nVampMist")==TRUE)
  { // remain mist
    if (GetLocalInt(oMe,"nAppearance")==0)
    { // change appearance
       SetLocalInt(oMe,"nAppearance",GetAppearanceType(oMe));
       SetCreatureAppearanceType(oMe,298);
    } // change appearance
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eCutsceneDominated,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eCutsceneGhost,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eInvis,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eFast,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eMist,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eSanctuary,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_ACID);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_BLUDGEONING);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_COLD);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_DIVINE);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_ELECTRICAL);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_FIRE);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_MAGICAL);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_NEGATIVE);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_PIERCING);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_POSITIVE);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_SLASHING);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    eDamage=EffectDamageDecrease(1000,DAMAGE_TYPE_SONIC);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eDamage,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eSilence,oMe,10.2);
    ApplyEffectToObject(DURATION_TYPE_TEMPORARY,eConcealment,oMe,10.2);
    SetPlotFlag(oMe,TRUE);
    DelayCommand(9.0,SetPlotFlag(oMe,FALSE));
    DelayCommand(10.0,fnGhost());
  } // remain mist
  else
  { // return to your own form
    SetCreatureAppearanceType(oMe,GetLocalInt(oMe,"nAppearance"));
    DeleteLocalInt(oMe,"nAppearance");
  } // return to your own form
} // fnGhost()

void fnHealAndBecomeMist()
{
  Raise(OBJECT_SELF);
  SetLocalInt(OBJECT_SELF,"nVampMist",TRUE);
  fnGhost();
} // fnHealAndBecomeMist()

void fnRunToCoffin(object oCoffin)
{
  object oMe=OBJECT_SELF;
  float fDist=GetDistanceBetween(oCoffin,oMe);
  if (oCoffin==OBJECT_INVALID) { fnTrueDeath(); }
  else
  { // coffin exists
  if (GetArea(oMe)!=GetArea(oCoffin)||fDist>3.0)
  {
    SendMessageToPC(oMe,"You MUST return to your coffin!");
    DelayCommand(12.0,fnRunToCoffin(oCoffin));
  } // move to coffin
  else
  { // arrived at coffin
    //SetCommandable(TRUE,oMe);
    AssignCommand(oMe,ClearAllActions(TRUE));
    SetLocalInt(oMe,"nVampMist",FALSE);
    SendMessageToPC(oMe,"You safely return to your coffin!");
  } // arrived at coffin
 } // coffin exists
} // run to coffin

void fnFleeToCoffin()
{
  object oMe=OBJECT_SELF;
  object oCoffin=GetLocalObject(oMe,"oCoffin");
  fnHealAndBecomeMist();
  //SetCommandable(FALSE,oMe);
  fnRunToCoffin(oCoffin);
} // fnFleeToCoffin()

void fnDestroySkinProperties(object oSkin)
{ // destroy skin properties
  IPRemoveAllItemProperties(oSkin,DURATION_TYPE_PERMANENT);
} // fnDestroySkinProperties()

void fnDestroySkin(object oSkin)
{
    fnDestroySkinProperties(oSkin);
} // fnDestroySkin()

void fnTrueDeath()
{
  object oPC=OBJECT_SELF;
  object oItem;
  object oNew;
  object oMod=GetModule();
  object oCloth;
  int nGold=GetGold(oPC);
  int nDeath=GetLocalInt(oPC,"nDied");
  int nC;
  string sTag;
  object oHench=GetAssociate(ASSOCIATE_TYPE_HENCHMAN,oPC,1);
  effect eEffect;
  object oKiller=GetLocalObject(oPC,"oKiller");
  object oKilledBy=oKiller;
  // adjust undead hunter reputation
  oNew=GetObjectByTag("undeadhunter_dummy");
  if (oNew!=OBJECT_INVALID)
  { // found place holder
    AdjustReputation(oPC,oNew,60);
  } // found place holder
  oNew=OBJECT_INVALID;
  // end adjust
  SetLocalInt(oPC,"nVampMist",FALSE);
  if (GetIsObjectValid(oHench)==TRUE) fnRemoveHenchman(oHench,oPC);
  if (GetIsPC(oKiller)==FALSE)
  { // check
    if (GetMaster(oKiller)!=OBJECT_INVALID) oKiller=GetMaster(oKiller);
    else
    {
      sTag=GetLocalString(oKiller,"sTeamID");
      if (GetStringLength(sTag)>2) oKiller=GetLocalObject(oMod,"oTeamLead"+sTag);
      sTag="";
    }
  } // check
  if (GetIsPC(oKiller)==TRUE)
  { // give experience
    GiveXPToCreature(oPC,500); // 500 XP
  } // give experience
   SetLocalInt(oPC,"nDied",1);
   nC=GetLocalInt(oPC,"nDeaths");
   nC++;
   SetLocalInt(oPC,"nDeaths",nC);
   SetLocalInt(oPC,"nDeadVampire",TRUE);
   SendMessageToPC(oPC,"You have died "+IntToString(nC)+" times in this game.");
   if (GetLocalInt(oMod,"nGameType")==0) DelayCommand(5.5,fnMessageDeath(oPC,oKilledBy));
   SetLocalInt(oPC,"nIsVampire",FALSE);
   SetLocalInt(oPC,"nCoffinPlaced",FALSE);
   if (GetLocalObject(oPC,"oCoffin")!=OBJECT_INVALID) DestroyObject(GetLocalObject(oPC,"oCoffin"));
   DeleteLocalObject(oPC,"oCoffin");
   DeleteLocalInt(oPC,"nBloodPool");
   DeleteLocalInt(oPC,"nVampireXP");
   //oItem=GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
   oItem = GetPCSkin(oPC);
   if (oItem!=OBJECT_INVALID) fnDestroySkin(oItem);
   AssignCommand(oPC,RespawnPlayer(oPC));
} // fnTrueDeath()