// Written by WodahsEht.
// Calculates the total sneak attack damage die given by all classes,
// and applies the resulting bonuses to the skin.  KNOWN ISSUE:
// Sneak attack feats of the same type can appear twice on the character sheet.
// For instance, Rogue +3d6 appears alongside Rogue +10d6.  They do not stack.
// The damage is 10d6.
//
// Compatibility with old PRC's is maintained.

// Updated by Strat
// Replaced the cleaning code because it was leaving multiple iterations of some feats
// It's brute force, but it works

#include "prc_alterations"
#include "prc_inc_sneak"

void CleanSneak(object oPC, object oSkin)
{
    // Rogue Sneak Attacks
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_1D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_1D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_2D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_2D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_3D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_3D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_4D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_4D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_5D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_5D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_6D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_6D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_7D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_7D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_8D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_8D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_9D6,  oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_9D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_10D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_10D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_11D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_11D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_12D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_12D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_13D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_13D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_14D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_14D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_15D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_15D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_16D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_16D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_17D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_17D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_18D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_18D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_19D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_19D6));
    if (GetHasFeat(FEAT_ROGUE_SNEAK_ATTACK_20D6,  oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_ROGUE_SA_20D6));
    
    // Blackguard Sneak
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_1D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_1D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_2D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_2D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_3D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_3D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_4D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_4D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_5D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_5D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_6D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_6D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_7D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_7D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_8D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_8D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_9D6, oPC))  DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_9D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_10D6, oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_10D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_11D6, oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_11D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_12D6, oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_12D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_13D6, oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_13D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_14D6, oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_14D6));    
    if (GetHasFeat(FEAT_BLACKGUARD_SNEAK_ATTACK_15D6, oPC)) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT,IP_CONST_FEAT_BG_SA_15D6));    
}

void ApplySneakToSkin(object oPC, int iRogueSneak, int iBlackguardSneak)
{
   object oSkin = GetPCSkin(oPC);

   int iRogueSneakFeat = 0;
   int iBlackguardSneakFeat = 0;
   int iPreviousSneakFeat = 0;

   //Rogue Sneaks, in increasing order, from iprp_feat.2da:
   //1-3: 32-34, 4: 301, 5: 39, 6-20: 302-316
   if (iRogueSneak > 20) return;  //Error, should never happen.

   if ((iRogueSneak >= 1) && (iRogueSneak < 4)) iRogueSneakFeat = iRogueSneak + 31;
   else if (iRogueSneak == 4) iRogueSneakFeat = 301;
   else if (iRogueSneak == 5) iRogueSneakFeat = 39;
   else if (iRogueSneak >  5) iRogueSneakFeat = iRogueSneak + 296;

   //Blackguard Sneaks
   //1-15: 276-290
   if (iBlackguardSneak > 15) return; //Error, should never happen.

   if (iBlackguardSneak) iBlackguardSneakFeat = iBlackguardSneak + 275;

   // This is basically to always readd the sneaks on every event PRCEvalFeats is called...
   CleanSneak(oPC, oSkin);
   iPreviousSneakFeat = GetLocalInt(oSkin,"RogueSneakDice");
   if (iPreviousSneakFeat) DelayCommand(0.1, RemoveSpecificProperty(oSkin,
                           ITEM_PROPERTY_BONUS_FEAT,iPreviousSneakFeat));

   iPreviousSneakFeat = GetLocalInt(oSkin,"BlackguardSneakDice");
   if (iPreviousSneakFeat) DelayCommand(0.1, RemoveSpecificProperty(oSkin,
                           ITEM_PROPERTY_BONUS_FEAT,iPreviousSneakFeat));

   SetLocalInt(oSkin,"RogueSneakDice",iRogueSneakFeat);
   SetLocalInt(oSkin,"BlackguardSneakDice",iBlackguardSneakFeat);

   if (iRogueSneak) DelayCommand(0.2, AddItemProperty(DURATION_TYPE_PERMANENT,
                           PRCItemPropertyBonusFeat(iRogueSneakFeat), oSkin));
   if (iBlackguardSneak) DelayCommand(0.2, AddItemProperty(DURATION_TYPE_PERMANENT,
                           PRCItemPropertyBonusFeat(iBlackguardSneakFeat), oSkin));
                           
    if(iRogueSneak)
        DelayCommand(0.2, IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(iRogueSneakFeat), 0.0f,
                                                X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE));
    if(iBlackguardSneak)
        DelayCommand(0.2, IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(iBlackguardSneakFeat), 0.0f,
                                                X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE));
}


void main()
{
   object oPC = OBJECT_SELF;
   object oSkin = GetPCSkin(oPC);

   int iRogueSneakDice = GetRogueSneak(oPC);
   int iBlackguardSneakDice = GetBlackguardSneak(oPC);

   // Special case in case someone multiclasses Telflammar Shadowlord and Assassin -- These are the only
   // two classes that use Assassin Death Attack, and normally they would not stack.
   if((GetLevelByClass(CLASS_TYPE_SHADOWLORD) >= 6) && (GetLevelByClass(CLASS_TYPE_ASSASSIN)))
      iRogueSneakDice++;

   int iFinalSneakDice = iRogueSneakDice + iBlackguardSneakDice;

   if(iRogueSneakDice > 20)        //Basically, if the total sneaks spill over the rogue limit,
   {                               //Add it to the Blackguard sneaks.  Only possible with a Rog39/PA1 ATM.
      iBlackguardSneakDice += iRogueSneakDice - 20;
      iRogueSneakDice = 20;
   }
   if(iBlackguardSneakDice > 15)   //Same as above, handles BG spillover.  Not really possible, but...
   {
      iRogueSneakDice += iBlackguardSneakDice - 15;
      iBlackguardSneakDice = 15;
   }
   if(iRogueSneakDice > 20)
   {
      //Keep in mind we are not considering the Assassin's Death Attack or Improved
      //Sneak Attack.  If we hit more than +35d6 there is something wrong with the
      //character or the above code.
      SendMessageToPC(oPC,"Fatal error: +35d6 Rogue/Blackguard Sneak Attack exceeded!");
      return;
   }

   // code to remove sneak attack feats if they had them before, but not now.
   // mainly used for classes whose sneak is based on using a certain weapon
   // such as the blood archer, peerless archer, and halfling warslinger.
   int iPreviousSneak = GetLocalInt(oSkin,"RogueSneakDice");
   if(!iFinalSneakDice && iPreviousSneak) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, iPreviousSneak));

   iPreviousSneak = GetLocalInt(oSkin,"BlackguardSneakDice");
   if(!iFinalSneakDice && iPreviousSneak) DelayCommand(0.1, RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, iPreviousSneak));

   if(iFinalSneakDice) ApplySneakToSkin(oPC,iRogueSneakDice,iBlackguardSneakDice);
}