//::///////////////////////////////////////////////
//:: User Defined OnHitCastSpell code
//:: prc_onhitcast
//:://////////////////////////////////////////////
/*
    This file holds all the OnHitCastSpell events
    used by PRC.
    It was created to replace x2_s3_onhitcast so that
    it wouldn't override module-specific onhitcast events.

    Add your own entries after the previous ones. Try to
    keep variable scope as little as possible. ie, no top-
    level variables if you just can avoid it.
    If your entry is long (over 20 lines), consider placing
    the guts of it outside the main to improve readability
    for the rest of us :D


    Please remember to comment your entry.
    At least mention what class ability / spell / whatever
    it is part of.
*/
//:://////////////////////////////////////////////
//:: Created By: Various people
//:://////////////////////////////////////////////

#include "psi_inc_onhit"
#include "inc_rend"
#include "psi_inc_ac_const"
#include "prc_inc_onhit"
#include "tob_inc_tobfunc"
#include "prc_inc_sp_tch"

void SetRancorVar(object oPC);
void SetImprovedRicochetVar(object oPC);
void DoImprovedRicochet(object oPC, object oTarget);

object GetProperTarget(object oPC, object oTarget)
{
    location lTarget = GetLocation(oPC);
    // Use the function to get the closest creature as a target
    object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lTarget, TRUE, OBJECT_TYPE_CREATURE);
    while(GetIsObjectValid(oAreaTarget))
    {
        if(oAreaTarget != oPC && // Not you. 
           GetIsEnemy(oPC, oAreaTarget) && // Enemies only, please
           GetIsInMeleeRange(oPC, oAreaTarget)) // They must be in melee range
        {
			return oAreaTarget;
        }
    //Select the next target within the spell shape.
    oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lTarget, TRUE, OBJECT_TYPE_CREATURE);
    }
    
    return oTarget;
}

void main()
{
    object oSpellOrigin = OBJECT_SELF; // On a weapon: The one wielding the weapon. On an armor: The one wearing an armor

    // Call the normal OnHitCastSpell: Unique script
    if (DEBUG) DoDebug("prc_onhitcast: entered, executing normal onhitcastspell unique power script x2_s3_onhitcast for "+GetName(oSpellOrigin));
    ExecuteScript("x2_s3_onhitcast", oSpellOrigin);

    // motu99: setting a local int, so that onhitcast impact spell scripts can find out, whether they were called from prc_onhitcast
    // or from somewhere else (presumably the aurora engine). This local int will be deleted just before we exit prc_onhitcast
    // Note that any scripts that are called by a DelayCommand (or AssignCommand) from prc_onhitcast will not find this local int
    SetLocalInt(oSpellOrigin, "prc_ohc", TRUE);

    object oSpellTarget = PRCGetSpellTargetObject(oSpellOrigin); // On a weapon: The one being hit. On an armor: The one hitting the armor
    
    // Make sure you don't hit yourself. Some idiot didn't check that.
    if (oSpellOrigin == oSpellTarget)
    	oSpellTarget = GetProperTarget(oSpellOrigin, oSpellTarget);    

    // motu99: replacing call to Bioware's GetSpellCastItem with new PRC wrapper function
    // will ensure that we retrieve a valid item when we are called from scripted combat (prc_inc_combat) or
    object oItem = PRCGetSpellCastItem(oSpellOrigin); // The item casting triggering this spellscript
    int iItemBaseType = GetBaseItemType(oItem);


// DEBUG code, remove
    if (DEBUG)
    {
        if(!GetIsOnHitCastSpell(oSpellTarget, oItem, oSpellOrigin))
            DoDebug("prc_onhitcast: Warning, the currently running instance of prc_onhitcast was not recognized as an onhitcastspell");
    }
// DEBUG code, remove

    if (DEBUG) DoDebug("prc_onhitcast: now executing prc specific routines with item = "+ GetName(oItem)+", target = "+GetName(oSpellTarget)+", caller = "+GetName(oSpellOrigin)+", item type = "+IntToString(iItemBaseType));

   // int nBArcher;        // Blood Archer level
    int nFoeHunter = GetLevelByClass(CLASS_TYPE_FOE_HUNTER, oSpellOrigin);    // Foe Hunter Level
    //int bItemIsWeapon;

    //nBArcher   = GetLevelByClass(CLASS_TYPE_BLARCHER, oSpellOrigin);

    //// Swashbuckler Weakening and Wounding Criticals
    if(GetHasFeat(INSIGHTFUL_STRIKE, oSpellOrigin))
        ExecuteScript("prc_swashweak", oSpellOrigin);

    //// Champion of Corellon damage healing for sneak/critical immune creatures
    if(GetHasFeat(FEAT_COC_ELEGANT_STRIKE, oSpellOrigin))
        ExecuteScript("prc_coc_heal", oSpellOrigin);

    //// Stormlord Shocking & Thundering Spear

    if(GetHasFeat(FEAT_THUNDER_WEAPON, oSpellOrigin))
        ExecuteScript("ft_shockweap", oSpellOrigin);

    if(GetHasSpellEffect(TEMPUS_ENCHANT_WEAPON, oItem))
    {
        int nRace = MyPRCGetRacialType(oSpellTarget);
        if((GetLocalInt(oSpellOrigin, "WeapEchant1") == TEMPUS_ABILITY_VICIOUS &&
             nRace == GetLocalInt(oSpellOrigin,"WeapEchantRace1")) ||
           (GetLocalInt(oSpellOrigin,"WeapEchant2")==TEMPUS_ABILITY_VICIOUS &&
             nRace == GetLocalInt(oSpellOrigin,"WeapEchantRace2")) ||
           (GetLocalInt(oSpellOrigin,"WeapEchant3")==TEMPUS_ABILITY_VICIOUS &&
             nRace == GetLocalInt(oSpellOrigin,"WeapEchantRace3"))
          )
            ApplyEffectToObject(DURATION_TYPE_INSTANT,EffectDamage(d6()),oSpellOrigin);
    }

    if (GetIsPC(oSpellOrigin))
        SetLocalInt(oSpellOrigin,"DmgDealt",GetTotalDamageDealt());

    /// Vassal of Bahamut Dragonwrack
    if(GetLevelByClass(CLASS_TYPE_VASSAL, oSpellOrigin) > 3)
    {
        if (iItemBaseType == BASE_ITEM_ARMOR)
            ExecuteScript("prc_vb_dw_armor", oSpellOrigin);
        else
            ExecuteScript("prc_vb_dw_weap", oSpellOrigin);
    }
/*    /// Blood Archer Acidic Blood
    if (nBArcher >= 2)
    {
        if(iItemBaseType == BASE_ITEM_ARMOR)
            ExecuteScript("prc_bldarch_ab", oSpellOrigin);
    }

    // Blood Archer Poison Blood
    if (nBArcher > 0 && iItemBaseType != BASE_ITEM_ARMOR)
    {
        // poison number based on archer level
        // gives proper DC for poison
        int iPoison = 104 + nBArcher;
        effect ePoison = EffectPoison(iPoison);
        ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoison, oSpellTarget);
    }*/

    // Frenzied Berserker Auto Frenzy
    if(iItemBaseType == BASE_ITEM_ARMOR && GetHasFeat(FEAT_FRENZY, oSpellOrigin))
    {
        if(!GetHasFeatEffect(FEAT_FRENZY, oSpellOrigin))
        {
            DelayCommand(0.01, ExecuteScript("prc_fb_auto_fre", oSpellOrigin) );
        }
        else if(GetCurrentHitPoints(oSpellOrigin) == 1 && GetHasFeat(FEAT_DEATHLESS_FRENZY, oSpellOrigin))
        {
            DelayCommand(0.01, ExecuteScript("prc_fb_deathless", oSpellOrigin) );
        }
    }

    // Warsling Sniper Improved Ricochet
    if (iItemBaseType == BASE_ITEM_BULLET
        && GetLevelByClass(CLASS_TYPE_HALFLING_WARSLINGER, oSpellOrigin) > 5
        && GetLocalInt(oSpellOrigin, "CanRicochet") != 2)
    {
        // Deactivates Ability
        SetLocalInt(oSpellOrigin, "CanRicochet", 2);

        DoImprovedRicochet(oSpellOrigin, oSpellTarget);

        // Prevents the heartbeat script from running multiple times
        if(GetLocalInt(oSpellOrigin, "ImpRicochetVarRunning") != 1)
        {
            DelayCommand(6.0, SetImprovedRicochetVar(oSpellOrigin) );
            SetLocalInt(oSpellOrigin, "ImpRicochetVarRunning", 1);
        }
    }

    // Warchief Devoted Bodyguards
    if(iItemBaseType == BASE_ITEM_ARMOR && GetLevelByClass(CLASS_TYPE_WARCHIEF, oSpellOrigin) > 7)
    {
        // Warchief must make a reflex save
        if(!GetLocalInt(oSpellOrigin, "WarChiefDelay"))
        {
            // Done this way for formatting reasons in game
            if(ReflexSave(oSpellOrigin, 15))
                DelayCommand(0.01, ExecuteScript("prc_wchf_bodygrd", oSpellOrigin));

            // He can only do this once a round, so put a limit on it
            SetLocalInt(oSpellOrigin, "WarChiefDelay", TRUE);
            DelayCommand(6.0, DeleteLocalInt(oSpellOrigin, "WarChiefDelay"));
        }
    }

    // Foe Hunter Damage Resistance
    if(iItemBaseType == BASE_ITEM_ARMOR && nFoeHunter > 1)
    {
        DelayCommand(0.01, ExecuteScript("prc_fh_dr",oSpellOrigin) );
    }

    // Foe Hunter Rancor Attack
    if(iItemBaseType != BASE_ITEM_ARMOR && nFoeHunter > 0)
    {
        if( GetLocalInt(oSpellOrigin, "PRC_CanUseRancor") != 2
            && GetLocalInt(oSpellOrigin, "HatedFoe") == MyPRCGetRacialType(oSpellTarget) )
        {
            int iFHLevel = GetLevelByClass(CLASS_TYPE_FOE_HUNTER, oSpellOrigin);
            int iRancorDice = FloatToInt( (( iFHLevel + 1.0 ) /2) );

            int iDamage = d6(iRancorDice);
            int iDamType = GetWeaponDamageType(oItem);
            int iDamPower = GetDamagePowerConstant(oItem, oSpellTarget, oSpellOrigin);

            effect eDam = EffectDamage(iDamage, iDamType, iDamPower);

            string sMess = "*Rancor Attack*";
            FloatingTextStringOnCreature(sMess, oSpellOrigin, FALSE);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oSpellTarget);

            // Deactivates Ability
            SetLocalInt(oSpellOrigin, "PRC_CanUseRancor", 2);

            // Prevents the heartbeat script from running multiple times
            if(GetLocalInt(oSpellOrigin, "PRC_RancorVarRunning") != 1)
            {
                DelayCommand(6.0, SetRancorVar(oSpellOrigin) );
                SetLocalInt(oSpellOrigin, "PRC_RancorVarRunning", 1);
            }
        }
    }

    //Creatures with a necrotic cyst take +1d6 damage from natural attacks of undead
    if(GetHasNecroticCyst(oSpellOrigin) && iItemBaseType == BASE_ITEM_ARMOR)
    {
        //if enemy is undead
        if(MyPRCGetRacialType(oSpellTarget) == RACIAL_TYPE_UNDEAD)
        {
            //and unarmed
            if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oSpellTarget)) &&
                !GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oSpellTarget)))

                {
                effect eDam = EffectDamage(d6(1), DAMAGE_TYPE_MAGICAL);
                SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oSpellOrigin);
            }
         }
     }

    /*//////////////////////////////////////////////////
    //////////////// PSIONICS //////////////////////////
    //////////////////////////////////////////////////*/

    // SweepingStrike OnHit
    if(iItemBaseType != BASE_ITEM_ARMOR && GetLocalInt(oItem, "SweepingStrike"))
    {
        SweepingStrike(oSpellOrigin, oSpellTarget);
    }

    // Mind Stab OnHit
    if(iItemBaseType != BASE_ITEM_ARMOR && GetLocalInt(oSpellOrigin, "ShadowMindStab") && !GetLocalInt(oSpellOrigin, "MindStabDelay"))
    {
    	//FloatingTextStringOnCreature("MindStab Stage 1", oSpellOrigin, FALSE);
        // Only works when able to sneak attack a target
        if (GetCanSneakAttack(oSpellTarget, oSpellOrigin))
        {
        	//FloatingTextStringOnCreature("MindStab Stage 2", oSpellOrigin, FALSE);
            MindStab(oSpellOrigin, oSpellTarget);
            // Only once per round
            SetLocalInt(oSpellOrigin, "MindStabDelay", TRUE);
            DelayCommand(6.0, DeleteLocalInt(oSpellOrigin, "MindStabDelay"));
        }
    }

    // Astral Construct's Poison Touch special ability
    if(GetLocalInt(oSpellOrigin, ASTRAL_CONSTRUCT_POISON_TOUCH))
    {
        ExecuteScript("psi_ast_con_ptch", oSpellOrigin);
    }

    // Pyrokineticist bonus damage
    int nPyroLevel = GetLevelByClass(CLASS_TYPE_PYROKINETICIST, oSpellOrigin);
    if(nPyroLevel)
    {
        int iElement = GetPersistantLocalInt(oSpellOrigin, "PyroDamageType");
        int nDam1 = 0;
        int nDam2 = 0;
        int nDam = 0;
        int nDice = 0;

        if(iItemBaseType == BASE_ITEM_ARMOR)
        {   //Nimbus Onhit
            if(nPyroLevel >= 5 && GetHasSpellEffect(SPELL_NIMBUS, oSpellOrigin))
            {
                nDice = 2;
                nDam = (iElement == DAMAGE_TYPE_SONIC) ? d4(nDice) : d6(nDice);    //reduced damage dice
                if((iElement == DAMAGE_TYPE_COLD) || (iElement == DAMAGE_TYPE_ELECTRICAL) || (iElement == DAMAGE_TYPE_ACID))
                    nDam = max(nDice, nDam - nDice);   //minimum of 1 per die
            }
        }
        else
        {   //Assume unarmed/weapon damage
            if(nPyroLevel >= 2)
            {
                nDice = (GetLevelByClass(CLASS_TYPE_PYROKINETICIST, oSpellOrigin) >= 8) ? 4 : 2;
                nDam1 = (iElement == DAMAGE_TYPE_SONIC) ? d4(nDice) : d6(nDice);    //reduced damage dice
                if((iElement == DAMAGE_TYPE_COLD) || (iElement == DAMAGE_TYPE_ELECTRICAL) || (iElement == DAMAGE_TYPE_ACID))
                    nDam1 = max(nDice, nDam1 - nDice);   //minimum of 1 per die
            }
            if(GetTag(oItem) == "PRC_PYRO_LASH_WHIP")
            {   //Extra damage from whip
                nDam2 += (iElement == DAMAGE_TYPE_SONIC) ? d6(1) : d8(1);   //reduced damage dice
                if((iElement == DAMAGE_TYPE_COLD) || (iElement == DAMAGE_TYPE_ELECTRICAL) || (iElement == DAMAGE_TYPE_ACID))
                    nDam2 = max(1, nDam2 - 1);   //minimum of 1
            }
            nDam = nDam1 + nDam2;
        }
        if(nDam > 0)
        {
            SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDam, iElement), oSpellTarget);
            SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(GetPersistantLocalInt(oSpellOrigin, "PyroImpactVFX")), oSpellTarget);
        }
    }

    /*//////////////////////////////////////////////////
    //////////////// END PSIONICS //////////////////////
    //////////////////////////////////////////////////*/

    /*//////////////////////////////////////////////////
    //////////////// Blade Magic ///////////////////////
    //////////////////////////////////////////////////*/

    // Martial Spirit
    if(GetHasSpellEffect(MOVE_DS_MARTIAL_SPIRIT, oSpellOrigin) && GetBaseItemType(oItem) != BASE_ITEM_ARMOR && GetObjectType(oSpellTarget) == OBJECT_TYPE_CREATURE && !GetIsDead(oSpellTarget))
    {
        object oHealTarget = GetCrusaderHealTarget(oSpellOrigin, 30.0);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(2), oHealTarget);
        ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEALING_L_LAW), oHealTarget);
    }

    // Blood in the Water
    if(GetHasSpellEffect(MOVE_TC_BLOOD_WATER, oSpellOrigin) && GetBaseItemType(oItem) != BASE_ITEM_ARMOR && !GetIsImmune(oSpellTarget, IMMUNITY_TYPE_CRITICAL_HIT))
    {
        // Fake critical hit check
        if(d20() >= GetWeaponCriticalRange(oSpellOrigin, oItem))
        {
            effect eBuff = EffectLinkEffects(EffectAttackIncrease(1), EffectDamageIncrease(DAMAGE_BONUS_1, DAMAGE_TYPE_SLASHING));
            DelayCommand(0.0, ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBuff, oSpellOrigin, TurnsToSeconds(1)));
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_BLOOD_CRT_YELLOW_HEAD), oSpellOrigin);
        }
    }

    // Fire Riposte
    if(GetHasSpellEffect(MOVE_DW_FIRE_RIPOSTE, oSpellOrigin) && GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
    {
        int nTouchAttack = PRCDoMeleeTouchAttack(oSpellTarget);
        if(nTouchAttack > 0)
        {
                // Apply the damage and VFX
                ApplyTouchAttackDamage(oSpellOrigin, oSpellTarget, nTouchAttack, d6(4), DAMAGE_TYPE_FIRE);
                effect eVis = EffectVisualEffect(VFX_COM_HIT_FIRE);
                SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oSpellTarget);
                FloatingTextStringOnCreature("Fire Riposte Hit", oSpellOrigin, FALSE);
                // Clean up
                PRCRemoveSpellEffects(MOVE_DW_FIRE_RIPOSTE, oSpellOrigin, oSpellOrigin);
        }
    }

    // Holocaust Cloak
    if(GetHasSpellEffect(MOVE_DW_HOLOCAUST_CLOAK, oSpellOrigin) && GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
    {
        if(GetIsInMeleeRange(oSpellOrigin, oSpellTarget))
        {
                // Apply the damage and VFX
                effect eVis = EffectVisualEffect(VFX_COM_HIT_FIRE);
                effect eDam = EffectDamage(5, DAMAGE_TYPE_FIRE);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oSpellTarget);
                SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oSpellTarget);
                FloatingTextStringOnCreature("Holocaust Cloak Hit", oSpellOrigin, FALSE);
        }
    }
    // Defensive Rebuke
    if(GetHasSpellEffect(MOVE_DS_DEFENSIVE_REBUKE, oSpellOrigin) && GetBaseItemType(oItem) != BASE_ITEM_ARMOR)
    {
        SetLocalObject(oSpellTarget, "DefensiveRebuke", oSpellOrigin);
        DelayCommand(3.0, ExecuteScript("tob_dvsp_defrbka", oSpellTarget));
    }
    // Defensive Rebuke
    if(GetHasSpellEffect(MOVE_DM_PEARL_BLACK_DOUBT, oSpellOrigin) && GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
    {
        // Will reset to 0.
        DeleteLocalInt(oSpellOrigin, "PearlOfBlackDoubtBonus");
    }
    // Tactics of the Wolf
    if(GetHasSpellEffect(MOVE_WR_TACTICS_WOLF, oSpellOrigin) && GetBaseItemType(oItem) != BASE_ITEM_ARMOR)
    {
        if (GetIsFlanked(oSpellTarget, oSpellOrigin))
        {
            int nWolfDam = GetLocalInt(oSpellOrigin, "TacticsWolf");
            ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nWolfDam), oSpellTarget);
        }
    }

    // Aura of Triumph
    if(GetHasSpellEffect(MOVE_DS_AURA_TRIUMPH, oSpellOrigin) && GetBaseItemType(oItem) != BASE_ITEM_ARMOR)
    {
        // Heal both
        object oHealTarget = GetLocalObject(oSpellOrigin, "DSTriumph");
        // Must be within 10 feet
        if (10.0 >= FeetToMeters(GetDistanceBetween(oSpellOrigin, oSpellOrigin)))
        {
            SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(4), oHealTarget);
        SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEALING_L_LAW), oHealTarget);
    }
        SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectHeal(4), oSpellOrigin);
    SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEALING_L_LAW), oSpellOrigin);
    }

    // Immortal Fortitude
    if(GetHasSpellEffect(MOVE_DS_IMMORTAL_FORTITUDE, oSpellOrigin) && GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
    {
        // He's immortal, so now we run a script to see if he should/would have died (Saving, etc)
    if(GetCurrentHitPoints(oSpellOrigin) == 1)
        {
            DelayCommand(0.01, ExecuteScript("tob_dvsp_imfrtoh", oSpellOrigin));
        }
    }
    // Immortal Fortitude
    if(GetHasSpellEffect(MOVE_WR_CLARION_CALL, oSpellOrigin) && GetBaseItemType(oItem) != BASE_ITEM_ARMOR)
    {
        // Check to see if the target is dead, triggers each time
    if(GetIsDead(oSpellTarget))
        {
            location lTarget = GetLocation(oSpellOrigin);
            object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), lTarget, TRUE, OBJECT_TYPE_CREATURE);
            while(GetIsObjectValid(oAreaTarget))
            {
                if(GetIsFriend(oAreaTarget, oSpellOrigin))
                {
                    // Apply extra attack for one round
                    ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectModifyAttacks(1)), oAreaTarget, 6.0);
                }
                oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), lTarget, TRUE, OBJECT_TYPE_CREATURE);
            }
        }
    }

    /*//////////////////////////////////////////////////
    //////////////// End Blade Magic ///////////////////
    //////////////////////////////////////////////////*/

    if(iItemBaseType != BASE_ITEM_ARMOR && GetLocalInt(oSpellOrigin,"doarcstrike"))
    {
        int nDice = GetLocalInt(oSpellOrigin,"curentspell");
        int nDamage = d4(nDice);
        effect eDam = EffectDamage(nDamage);
        ApplyEffectToObject(DURATION_TYPE_INSTANT,eDam,oSpellTarget);
    }

    //spellsword & arcane archer
    //will also fire for other OnHit:UniquePower items that have a SpellSequencer property (such as Duskblade)
    if(GetLocalInt(oItem, "X2_L_NUMCHANNELTRIGGERS"))
    {
        if (DEBUG) DoDebug("prc_onhitcast: Triggering Sequencer Discharge");
        SetLocalObject(oSpellOrigin, "ChannelSpellTarget", oSpellTarget);
        ExecuteScript("x2_s3_sequencer", oSpellOrigin);
    }

    // Handle Rend. Creature weapon damage + 1.5x STR bonus.
    // Only happens when attacking with a creature weapon
    if(GetIsCreatureWeaponType(iItemBaseType) && (GetHasFeat(FEAT_REND, oSpellOrigin) || GetLevelByClass(CLASS_TYPE_BLACK_BLOOD_CULTIST, oSpellOrigin) >= 6))
    {
        DoRend(oSpellTarget, oSpellOrigin, oItem);
    }
    
    // Handle Frostrager Rend. 2d8 damage + 1.5x STR bonus.
    // Only happens when attacking with a creature weapon
    if(GetIsCreatureWeaponType(iItemBaseType) && (GetLevelByClass(CLASS_TYPE_FROSTRAGER, oSpellOrigin) > 4))
    {
        DoFrostRend(oSpellTarget, oSpellOrigin, oItem);
    }   
    
    // Handle Spine Rend. 2d6 damage + 1.5x STR bonus.
    // Only happens when attacking with a skarn spine
    if(GetTag(oItem) == "skarn_spine" && (GetLevelByClass(CLASS_TYPE_SPINEMELD_WARRIOR, oSpellOrigin) >= 5))
    {
        DoSpineRend(oSpellTarget, oSpellOrigin, oItem);
    }     

    // now cycle through all onhitcast spells on the item
    // we must exclude unique power (which is associated with prc_onhitcast), because otherwise we would get infinite recursions
    // it is of utmost importance to devise a *safe* way to cycle through all onhitcast spells on the item. The safe way is provided
    // by the function ApplyAllOnHitCastSpellsOnItemExcludingSubType defined in prc_inc_spells

    // There are two ways to call this function: Either with all necessary parameters passed explicitly to the function
    // or with no parameters passed to the function (in this case default values are used, which also works, at least in prc_onhitcast)

    // VERSION 1:
    // generally it is more efficient to call ApplyAllOnHitCastSpellsOnItemExcludingSubType by explicitly passing the parameters to the function
    // this will set up the overrides in the PRC-wrappers for the spell information functions, which generally is much faster
    // ApplyAllOnHitCastSpellsOnItemExcludingSubType(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, oSpellTarget, oItem, oSpellOrigin);

    // VERSION 2:
    // motu99: It might be safer to call this only with defaults in order disallow overrides being set.
    // (they could have been set beforehand, though - in fact they *are* if we were called from prc_inc_combat)
    // VERSION 2 has also been tested to work; however, if Bioware changes its implementation the code below is more likely to break
    ApplyAllOnHitCastSpellsOnItemExcludingSubType(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER);

    // ONLY FOR TESTING
    // if(GetPRCSwitch(PRC_TIMESTOP_LOCAL)) CastSpellAtLocation(SPELL_FIREBALL, GetLocation(oSpellTarget) /*, METAMAGIC_ANY, GetLevelByTypeArcane(oSpellOrigin), CLASS_TYPE_WIZARD */);
    // if(GetPRCSwitch(PRC_PNP_TRUESEEING)) CastSpellAtObject(SPELL_FIREBALL, oSpellTarget /*, METAMAGIC_ANY, GetLevelByTypeArcane(oSpellOrigin), CLASS_TYPE_WIZARD */);
/*
// motu99: This is the old (unsafe) way to cycle through the onhitcast spells.
// This method fails, whenever one of the called impact spell script cycles through the item properties of the SpellCastItem on its own
// (or calls a function that cycles through the item properties - such as PRCGetMetaMagicFeat)
// The safe way to do things is to use the functions ApplyAllOnHitCastSpells* to be found in prc_inc_spells
// Left the piece of code here as an example and a warning, how perfectly reasonable code can break without the fault of the scripter
// Such an "error" can easily happen to any of us. It is quite difficult to spot an error, caused by nested loops
// over item properties in *different* scripts. Runtime behavior is erratic. If you are lucky, you get an
// infinite recursion (then you will notice that something is wrong). If you are not lucky, the loop will just skip over
// some item properties. And this simply because you put a completely harmless looking function like PRCGetMetaMagicFeat
// into your Spell script. How could you possibly know that you just broke your script, because of an unsafe implementation
// in a *different* script (here: prc_onhitcast)? You might not even know, that this different scripts exists.

    //handle other OnHit:CastSpell properties
DoDebug("prc_onhitcast: now doing other OnHitCastSpell properties on item = "+GetName(oItem));
    itemproperty ipTest = GetFirstItemProperty(oItem);
    while(GetIsItemPropertyValid(ipTest))
    {
        if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_ONHITCASTSPELL)
        {
            int nIPSpell = GetItemPropertySubType(ipTest);
            if(nIPSpell == 125)
            {
                ipTest = GetNextItemProperty(oItem);
                continue; //abort if its OnHit:CastSpell:UniquePower otherwise it would TMI.
            }
            int nSpell   = StringToInt(Get2DACache("iprp_onhitspell", "SpellIndex", nIPSpell));
            // int nLevel   = GetItemPropertyCostTableValue(ipTest);
            string sScript = Get2DACache("spells", "ImpactScript", nSpell);
DoDebug("prc_onhitcast: Now executing Impact spell script "+sScript);
            // motu99: Never execute complicated scripts within an GetFirst* / GetNext* loop !!!
            // The code will break, whenever the script does a loop over item properties (or effects) on its own
            // rather store all found scripts in a local array, and execute the scripts in a separate loop
            ExecuteScript(sScript,oSpellOrigin);
        }
        ipTest = GetNextItemProperty(oItem);
    }
*/

    /*//////////////////////////////////////////////////
    ///////////////////  SPELLFIRE  ////////////////////
    //////////////////////////////////////////////////*/

    int nSpellfire = GetLevelByClass(CLASS_TYPE_SPELLFIRE, oSpellOrigin);
    if(nSpellfire && (iItemBaseType == BASE_ITEM_ARMOR))
    {
        int nStored = GetPersistantLocalInt(oSpellOrigin, "SpellfireLevelStored");
        int nCON = GetAbilityScore(oSpellOrigin, ABILITY_CONSTITUTION);
        int nFlare = 0;
        int bFlare = FALSE;
        if(nStored > 4 * nCON)
        {
            nFlare = d6(2);
            bFlare = TRUE;
        }
        else if(nStored > 3 * nCON)
        {
            nFlare = d6();
            bFlare = TRUE;
        }
        else if(nStored > 2 * nCON)
            nFlare = d4();
        else if(nStored > nCON)
            nFlare = 1;
        if(nFlare)
        {
            nStored -= nFlare;
            if(nStored < 0) nStored = 0;
            SetPersistantLocalInt(oSpellOrigin, "SpellfireLevelStored", nStored);
        }
        if(bFlare)
        {
            int nDC = 10 + nFlare;
            location lTarget = GetLocation(oSpellOrigin);
            object oFlareTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE);
            while(GetIsObjectValid(oFlareTarget))
            {
                if(spellsIsTarget(oFlareTarget, SPELL_TARGET_STANDARDHOSTILE, oSpellOrigin))
                {
                    if(!PRCDoResistSpell(oSpellOrigin, oFlareTarget, nSpellfire))
                    {
                        if (PRCMySavingThrow(SAVING_THROW_FORT, oFlareTarget, nDC))
                        {
                if (GetHasMettle(oFlareTarget, SAVING_THROW_FORT))
                // This script does nothing if it has Mettle, bail
                    return;
                            SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_S), oFlareTarget);
                            ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectDazzle(), oFlareTarget, 60.0);
                        }
                    }
                }
                oFlareTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE);
            }
        }
        if(GetLocalInt(oSpellOrigin, "SpellfireCrown"))  //melts non-magical melee weapons
        {   //can't really get which weapon hit you, so...
            object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oSpellTarget);
            if(GetIsObjectValid(oWeapon))
            {
                if(IPGetIsMeleeWeapon(oWeapon) && !GetIsMagicItem(oWeapon))
                {
                    DestroyObject(oWeapon);
                    FloatingTextStringOnCreature("*Your weapon has melted!*", oSpellTarget);
                }
            }
            else
            {
                oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oSpellTarget);
                if(GetIsObjectValid(oWeapon))
                {
                    if(IPGetIsMeleeWeapon(oWeapon) && !GetIsMagicItem(oWeapon))
                    {
                        DestroyObject(oWeapon);
                        FloatingTextStringOnCreature("*Your weapon has melted!*", oSpellTarget);
                    }
                }
                else    //You're putting your arms and legs through something that melts weapons?
                {       //Silly monk/brawler/fool with molten weapons!
                    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d20()), oSpellTarget);
                    ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d20(), DAMAGE_TYPE_FIRE), oSpellTarget);
                }
            }
        }
    }

    /*//////////////////////////////////////////////////
    ////////////////// END SPELLFIRE ///////////////////
    //////////////////////////////////////////////////*/

    // Handle poisoned weapons
    /*
    if(GetLocalInt(oItem, "pois_wpn_uses"))
    {
        ExecuteScript("poison_wpn_onhit", OBJECT_SELF);
    }
    */
    // Execute scripts hooked to this event for the player triggering it
    if (DEBUG) DoDebug("prc_onhitcast: executing all scripts hooked to onhit events of attacker and item");
    ExecuteAllScriptsHookedToEvent(oSpellOrigin, EVENT_ONHIT);
    ExecuteAllScriptsHookedToEvent(oItem, EVENT_ITEM_ONHIT);

    DeleteLocalInt(oSpellOrigin, "prc_ohc");

}

void SetRancorVar(object oPC)
{
    // Turn Rancor on
    SetLocalInt(oPC, "PRC_CanUseRancor", 1);
    //FloatingTextStringOnCreature("Rancor Attack Possible", oPC, FALSE);

    int iMain = GetMainHandAttacks(oPC);
    float fDelay = 6.0 / IntToFloat(iMain);

    // Turn Rancor off after one attack is made
    DelayCommand(fDelay, SetLocalInt(oPC, "PRC_CanUseRancor", 2));
    //DelayCommand((fDelay + 0.01), FloatingTextStringOnCreature("Rancor Attack Not Possible", oPC, FALSE));

    // Call again if the character is still in combat.
    // this allows the ability to keep running even if the
    // player does not score a rancor hit during the allotted time
    if( PRCGetIsFighting() )
    {
        DelayCommand(6.0, SetRancorVar(oPC) );
    }
    else
    {
        DelayCommand(2.0, SetLocalInt(oPC, "PRC_CanUseRancor", 1));
        DelayCommand(2.1, SetLocalInt(oPC, "PRC_RancorVarRunning", 2));
        //DelayCommand(2.2, FloatingTextStringOnCreature("Rancor Enabled After Combat", oPC, FALSE));
    }
}

void DoImprovedRicochet(object oPC, object oTarget)
{
    int nTargetsLeft = 1;
    effect eVis = EffectVisualEffect(VFX_IMP_DUST_EXPLOSION);

    location lTarget = GetLocation(oTarget);
    //Declare the spell shape, size and the location.  Capture the first target object in the shape.
    object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lTarget, TRUE, OBJECT_TYPE_CREATURE);

    //Cycle through the targets within the spell shape until you run out of targets.
    while (GetIsObjectValid(oAreaTarget) && nTargetsLeft > 0)
    {
        if (spellsIsTarget(oAreaTarget, SPELL_TARGET_SELECTIVEHOSTILE, OBJECT_SELF) && oAreaTarget != OBJECT_SELF && oAreaTarget != oTarget)
        {
            PerformAttack(oAreaTarget, oPC, eVis, 0.0, -2, 0, 0, "*Improved Ricochet Hit*", "*Improved Ricochet Missed*");
             // Use up a target slot only if we actually did something to it
            nTargetsLeft -= 1;
        }

    //Select the next target within the spell shape.
    oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_LARGE, lTarget, TRUE, OBJECT_TYPE_CREATURE);
    }
}

void SetImprovedRicochetVar(object oPC)
{
    // Turn Retort on
    SetLocalInt(oPC, "CanRicochet", 1);

    // Turn Retort off after one attack is made
    DelayCommand(0.01, SetLocalInt(oPC, "CanRicochet", 0));

    // Call again if the character is still in combat.
    // this allows the ability to keep running even if the
    // player does not score a retort hit during the allotted time
    if( PRCGetIsFighting() )
    {
        DelayCommand(6.0, SetImprovedRicochetVar(oPC));
    }
    else
    {
        DelayCommand(2.0, SetLocalInt(oPC, "CanRicochet", 1));
        DelayCommand(2.1, SetLocalInt(oPC, "ImpRicochetVarRunning", 2));
    }
}
