//:://///////////////////////////////////////////// //:: Tome of Battle feats //:: tob_feats //:://///////////////////////////////////////////// /** @file Does all ToB feats that require event scripting. @author Stratovarius @date Created - 2018.9.22 */ //::////////////////////////////////////////////// //::////////////////////////////////////////////// #include "tob_inc_tobfunc" #include "psi_inc_psifunc" #include "prc_inc_combmove" #include "x0_i0_modes" ////////////////////////////////////////////////// /* Feat Functions */ ////////////////////////////////////////////////// // Called on Heartbeat void ShadowBlade(object oInitiator) { // Needs an active Shadow Hands stance int nStance = GetHasActiveStance(oInitiator); int nDisc = GetDisciplineByManeuver(nStance); int nDex = GetAbilityModifier(ABILITY_DEXTERITY, oInitiator); object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator); int nWeap = GetIsDisciplineWeapon(oWeapon, DISCIPLINE_SHADOW_HAND); // Must be a shadow hand weapon while a stance is active if (nDisc == DISCIPLINE_SHADOW_HAND && nWeap) { int nDamageType = GetWeaponDamageType(oWeapon); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectDamageIncrease(IPGetDamageBonusConstantFromNumber(nDex), nDamageType)), oInitiator, 6.0); SetLocalInt(oInitiator, "ShadowBladeDam", nDex); DelayCommand(6.0, DeleteLocalInt(oInitiator, "ShadowBladeDam")); } } // Called on Heartbeat void RapidAssault(object oInitiator) { int nCombat = GetIsInCombat(oInitiator); int nLast = GetLocalInt(oInitiator, "RapidAssault"); // Must must be in combat this round but not last round if (nCombat == TRUE && nLast == FALSE) { object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator); int nDamageType = GetWeaponDamageType(oWeapon); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectDamageIncrease(DAMAGE_BONUS_1d6, nDamageType)), oInitiator, 6.0); } SetLocalInt(oInitiator, "RapidAssault", nCombat); } // Called on heartbeat void DesertWindDodge(object oInitiator) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(1, AC_DODGE_BONUS)), oInitiator, 6.0); object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator); int nWeap = GetIsDisciplineWeapon(oWeapon, DISCIPLINE_DESERT_WIND); if (nWeap) ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectDamageIncrease(DAMAGE_BONUS_1, DAMAGE_TYPE_FIRE)), oInitiator, 6.0); } // Called on heartbeat void DesertFire(object oInitiator) { SetLocalInt(oInitiator, "DesertFire", TRUE); DelayCommand(5.9, DeleteLocalInt(oInitiator, "DesertFire")); } // Called on heartbeat void DesertWind(object oInitiator) { // Check to see if the WP is valid string sWPTag = "PRC_DWDWP_" + GetName(oInitiator); object oTestWP = GetWaypointByTag(sWPTag); if (!GetIsObjectValid(oTestWP)) { // Create waypoint for the movement CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oInitiator), FALSE, sWPTag); if(DEBUG) DoDebug("tob_feats: Desert Wind Dodge WP for " + DebugObject2Str(oInitiator) + " didn't exist, creating. Tag: " + sWPTag); } else // We have a test waypoint, now to check the distance { // Distance moved in the last round float fDist = GetDistanceBetween(oInitiator, oTestWP); // Distance needed to move float fCheck = FeetToMeters(10.0); // Now clean up the WP and create a new one for next round's check DestroyObject(oTestWP); CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oInitiator), FALSE, sWPTag); if(DEBUG) DoDebug("tob_feats: Moved enough: " + DebugBool2String(fDist >= fCheck)); // Moved the distance if (fDist >= fCheck) { if(GetHasFeat(FEAT_DESERT_WIND_DODGE, oInitiator)) DesertWindDodge(oInitiator); if(GetHasFeat(FEAT_DESERT_FIRE, oInitiator)) DesertFire(oInitiator); } } } // Called on False void BladeMeditation(object oInitiator) { int nDisc = BladeMeditationFeat(oInitiator); object oSkin = GetPCSkin(oInitiator); int nSkill = GetDisciplineSkill(nDisc); SetCompositeBonus(oSkin, "BladeMeditation", 2, ITEM_PROPERTY_SKILL_BONUS, nSkill); } // Called on Heartbeat void IronheartAura(object oInitiator) { int nDisc = GetDisciplineByManeuver(GetHasActiveStance(oInitiator)); if (nDisc == DISCIPLINE_IRON_HEART) { location lTarget = GetLocation(oInitiator); // Use the function to get the closest creature as a target object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); while(GetIsObjectValid(oAreaTarget)) { if(oAreaTarget != oInitiator && // Not you GetIsInMeleeRange(oInitiator, oAreaTarget) && // They must be in melee range GetIsFriend(oAreaTarget, oInitiator)) // Only allies { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectSavingThrowIncrease(SAVING_THROW_ALL, 2, SAVING_THROW_TYPE_ALL)), oAreaTarget, 6.0); } //Select the next target within the spell shape. oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); } } } // Called on heartbeat void ShadowTrickster(object oInitiator) { // Needs an active Shadow Hands stance int nStance = GetHasActiveStance(oInitiator); int nDisc = GetDisciplineByManeuver(nStance); if (nDisc == DISCIPLINE_SHADOW_HAND) { SetLocalInt(oInitiator, "ShadowTrickster", TRUE); } else DeleteLocalInt(oInitiator, "ShadowTrickster"); } // Called on Heartbeat void WhiteRavenDefense(object oInitiator) { int nDisc = GetDisciplineByManeuver(GetHasActiveStance(oInitiator)); object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator); int nWeap = GetIsDisciplineWeapon(oWeapon, DISCIPLINE_WHITE_RAVEN); int nAlly = FALSE; if (nDisc == DISCIPLINE_WHITE_RAVEN) { location lTarget = GetLocation(oInitiator); // Use the function to get the closest creature as a target object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); while(GetIsObjectValid(oAreaTarget)) { if(oAreaTarget != oInitiator && // Not you GetIsInMeleeRange(oInitiator, oAreaTarget) && // They must be in melee range GetIsFriend(oAreaTarget, oInitiator)) // Only allies { if (nWeap) ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(1)), oAreaTarget, 6.0); nAlly = TRUE; } //Select the next target within the spell shape. oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); } } if (nAlly) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(1)), oInitiator, 6.0); } } void DevotedBulwark(object oInitiator, object oTarget) { //only trigger if it was a melee weapon if(GetIsInMeleeRange(oInitiator, oTarget)) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectACIncrease(1), oInitiator, 6.0f); } } void SnapKick(object oInitiator, object oTarget) { if (GetLocalInt(oInitiator, "SnapKickDelay") == TRUE) return; //Once a round only else { SetLocalInt(oInitiator, "SnapKickDelay", TRUE); DelayCommand(6.0, DeleteLocalInt(oInitiator, "SnapKickDelay")); } object oWeap = GetItemInSlot(INVENTORY_SLOT_ARMS, oInitiator); // It's an unarmed attack, so we get the gloves int nAttack = GetAttackRoll(oTarget, oInitiator, oWeap); if (nAttack > 0) // We hit { FloatingTextStringOnCreature("Snap Kick Hit", oInitiator, FALSE); int nCrit = FALSE; if (nAttack == 2) nCrit = TRUE; effect eDam = GetAttackDamage(oTarget, oInitiator, oWeap, GetWeaponBonusDamage(oWeap, oTarget), GetMagicalBonusDamage(oInitiator, oTarget), 1, 0, nCrit); //off-hand attack to get 1/2 strength bonus ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget); } else FloatingTextStringOnCreature("Snap Kick Miss", oInitiator, FALSE); } void ThreeMountains(object oInitiator, object oTarget) { // Check for a first hit int nHit = GetLocalInt(oTarget, "ThreeMountains"); if (!nHit) { SetLocalInt(oTarget, "ThreeMountains", TRUE); DelayCommand(6.0, DeleteLocalInt(oTarget, "ThreeMountains")); } else // Hit them twice in six seconds { int nDC = 10 + GetHitDice(oInitiator)/2 + GetAbilityModifier(ABILITY_STRENGTH, oInitiator); if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_NONE, oInitiator)) { effect eLink = EffectLinkEffects(EffectSpellFailure(), EffectAttackDecrease(20)); SetBaseAttackBonus(1, oTarget); effect eLink2 = EffectLinkEffects(EffectVisualEffect(VFX_IMP_DISEASE_S), EffectVisualEffect(VFX_IMP_REDUCE_ABILITY_SCORE_RED)); DelayCommand(6.0, RestoreBaseAttackBonus(oTarget)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eLink), oTarget, RoundsToSeconds(1)); ApplyEffectToObject(DURATION_TYPE_INSTANT, eLink2, oTarget); } DeleteLocalInt(oTarget, "ThreeMountains"); } } void VaeSchool(object oInitiator, object oTarget) { if (GetLocalInt(oInitiator, "VaeSchool") == TRUE) return; //Once a round only else { SetLocalInt(oInitiator, "VaeSchool", TRUE); DelayCommand(6.0, DeleteLocalInt(oInitiator, "VaeSchool")); } DoTrip(oInitiator, oTarget, 0, FALSE, FALSE, TRUE); } void InlindlSchool(object oInitiator) { if (GetIsLightWeapon(oInitiator) && GetLocalInt(oInitiator, "InlindlSchool")) { int nShield = GetItemACValue(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator)); effect eLink = EffectLinkEffects(EffectACDecrease(nShield), EffectAttackIncrease(nShield/2)); eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_ARMOR_OF_DARKNESS)); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(eLink), oInitiator, 6.0); } } void XaniqosSchool(object oInitiator, object oTarget, object oItem, int nEvent) { int nType = GetBaseItemType(oItem); if(nEvent == EVENT_ITEM_ONHIT) { if(GetLocalInt(oInitiator, "XaniqosSchool") && IPGetIsProjectile(oItem)) // oItem is the ammo, since it's only applies to crossbows { effect eDam = EffectDamage(d6(), DAMAGE_TYPE_PIERCING); ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget); } } else if(nEvent == EVENT_ONPLAYEREQUIPITEM) { if (nType == BASE_ITEM_LIGHTCROSSBOW || nType == BASE_ITEM_HEAVYCROSSBOW) { object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oInitiator); IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oAmmo, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } else if(nEvent == EVENT_ONPLAYERUNEQUIPITEM) { if (nType == BASE_ITEM_LIGHTCROSSBOW || nType == BASE_ITEM_HEAVYCROSSBOW) { object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oInitiator); RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY); RemoveEventScript(oAmmo, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } else if(nEvent == EVENT_ONHEARTBEAT) { // Check to see if the WP is valid string sWPTag = "XaniqosWP_" + GetName(oInitiator); object oTestWP = GetWaypointByTag(sWPTag); if (!GetIsObjectValid(oTestWP)) { // Create waypoint for the movement CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oInitiator), FALSE, sWPTag); if(DEBUG) DoDebug("tob_feats: Xaniqos WP for " + DebugObject2Str(oInitiator) + " didn't exist, creating. Tag: " + sWPTag); } else // We have a test waypoint, now to check the distance { // Distance moved in the last round float fDist = GetDistanceBetween(oInitiator, oTestWP); // Distance needed to move float fCheck = FeetToMeters(10.0); // Now clean up the WP and create a new one for next round's check DestroyObject(oTestWP); CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oInitiator), FALSE, sWPTag); if(DEBUG) DoDebug("tob_feats: Moved enough: " + DebugBool2String(fDist >= fCheck)); // Moved the distance if (fDist >= fCheck) { // We have moved far enough SetLocalInt(oInitiator, "XaniqosSchool", TRUE); // Only lasts for a round DelayCommand(6.0, DeleteLocalInt(oInitiator, "XaniqosSchool")); } } } } void ShieldWall(object oInitiator) { int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator)); if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD) { location lTarget = GetLocation(oInitiator); // Use the function to get the closest creature as a target object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); while(GetIsObjectValid(oAreaTarget)) { if(oAreaTarget != oInitiator && // Not you GetIsInMeleeRange(oInitiator, oAreaTarget) && // They must be in melee range GetIsFriend(oAreaTarget, oInitiator)) // Only allies { int nBase2 = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oAreaTarget)); if (nBase2 == BASE_ITEM_SMALLSHIELD || nBase2 == BASE_ITEM_LARGESHIELD || nBase2 == BASE_ITEM_TOWERSHIELD) //Ally must have a shield { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(2, AC_SHIELD_ENCHANTMENT_BONUS)), oAreaTarget, 6.0); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(2, AC_SHIELD_ENCHANTMENT_BONUS)), oInitiator, 6.0); } } //Select the next target within the spell shape. oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); } } } void CrossbowSniper(object oInitiator, object oItem, int nEvent) { int nType = GetBaseItemType(oItem); int nDex = GetAbilityModifier(ABILITY_DEXTERITY, oInitiator); if(nEvent == EVENT_ONPLAYEREQUIPITEM) { if ((nType == BASE_ITEM_LIGHTCROSSBOW && GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oInitiator)) || (nType == BASE_ITEM_HEAVYCROSSBOW && GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oInitiator))) { object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oInitiator); IPSafeAddItemProperty(oAmmo, ItemPropertyDamageBonus(DAMAGE_TYPE_PIERCING, nDex/2), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); } } else if(nEvent == EVENT_ONPLAYERUNEQUIPITEM) { if ((nType == BASE_ITEM_LIGHTCROSSBOW && GetHasFeat(FEAT_WEAPON_FOCUS_LIGHT_CROSSBOW, oInitiator)) || (nType == BASE_ITEM_HEAVYCROSSBOW && GetHasFeat(FEAT_WEAPON_FOCUS_HEAVY_CROSSBOW, oInitiator))) { object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oInitiator); RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_DAMAGE_BONUS, DAMAGE_TYPE_PIERCING, nDex/2, 1, "", -1, DURATION_TYPE_TEMPORARY); } } } void ExpeditiousDodge(object oInitiator) { // Check to see if the WP is valid string sWPTag = "ExpeditiousWP_" + GetName(oInitiator); object oTestWP = GetWaypointByTag(sWPTag); if (!GetIsObjectValid(oTestWP)) { // Create waypoint for the movement CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oInitiator), FALSE, sWPTag); if(DEBUG) DoDebug("tob_feats: Expeditious WP for " + DebugObject2Str(oInitiator) + " didn't exist, creating. Tag: " + sWPTag); } else // We have a test waypoint, now to check the distance { // Distance moved in the last round float fDist = GetDistanceBetween(oInitiator, oTestWP); // Distance needed to move float fCheck = FeetToMeters(40.0); // Now clean up the WP and create a new one for next round's check DestroyObject(oTestWP); CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oInitiator), FALSE, sWPTag); if(DEBUG) DoDebug("tob_feats: Moved enough: " + DebugBool2String(fDist >= fCheck)); // Moved the distance if (fDist >= fCheck) { // We have moved far enough ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(2, AC_DODGE_BONUS)), oInitiator, 6.0); } } } void CrescentMoon(object oInitiator, object oTarget) { int nRight = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator)); int nLeft = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator)); if (nLeft == BASE_ITEM_DAGGER && (nRight == BASE_ITEM_SCIMITAR || nRight == BASE_ITEM_LONGSWORD || nRight == BASE_ITEM_BASTARDSWORD || nRight == BASE_ITEM_SHORTSWORD)) { int nHits = GetLocalInt(oTarget, "CrescentMoon"); // Check hits if (nHits == 2) { nHits = 0; // Free disarm attempt, once a round, per target if (!GetLocalInt(oTarget, "CrescentMoonDelay")) { DoDisarm(oInitiator, oTarget); SetLocalInt(oTarget, "CrescentMoonDelay", TRUE); DelayCommand(6.0, DeleteLocalInt(oTarget, "CrescentMoonDelay")); } } else nHits++; SetLocalInt(oTarget, "CrescentMoon", nHits); // Store the hits } } void QuickStaff(object oInitiator) { // Only applies when using expertise if(GetModeActive(ACTION_MODE_EXPERTISE) || GetActionMode(oInitiator, ACTION_MODE_EXPERTISE) || GetLastAttackMode(oInitiator) == COMBAT_MODE_EXPERTISE || GetModeActive(ACTION_MODE_IMPROVED_EXPERTISE) || GetActionMode(oInitiator, ACTION_MODE_IMPROVED_EXPERTISE) || GetLastAttackMode(oInitiator) == COMBAT_MODE_IMPROVED_EXPERTISE) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectACIncrease(2), oInitiator, 6.0); } } void BearFangGrapple(object oInitiator, object oTarget) { DoGrapple(oInitiator, oTarget, 0, FALSE, TRUE); } void BearFang(object oInitiator, object oTarget) { int nRight = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator)); int nLeft = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator)); if (nLeft == BASE_ITEM_DAGGER && (nRight == BASE_ITEM_BATTLEAXE || nRight == BASE_ITEM_HANDAXE || nRight == BASE_ITEM_DWARVENWARAXE)) { int nHits = GetLocalInt(oTarget, "BearFang"); // Check hits if (nHits == 2) { SetLocalInt(oInitiator, "BearFangGrapple", TRUE); ForceUnequip(oInitiator, GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator), INVENTORY_SLOT_RIGHTHAND); DelayCommand(0.6, BearFangGrapple(oInitiator, oTarget)); DeleteLocalInt(oInitiator, "BearFang"); } else nHits++; SetLocalInt(oTarget, "BearFang", nHits); // Store the hits } } void BearFangHB(object oInitiator) { // Resets every round DeleteLocalInt(oInitiator, "BearFang"); } void ImprovedRapidShot(object oInitiator) { // Only applies when using Rapid Shot if(GetModeActive(ACTION_MODE_RAPID_SHOT) || GetActionMode(oInitiator, ACTION_MODE_RAPID_SHOT) || GetLastAttackMode(oInitiator) == COMBAT_MODE_RAPID_SHOT) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAttackIncrease(2), oInitiator, 6.0); } } void DireFlailSmash(object oInitiator, object oTarget) { // Check for a first hit int nHit = GetLocalInt(oTarget, "DireFlailSmash"); if (!nHit) { SetLocalInt(oTarget, "DireFlailSmash", TRUE); DelayCommand(6.0, DeleteLocalInt(oTarget, "DireFlailSmash")); } else // Hit them twice in six seconds { int nDC = 10 + GetHitDice(oInitiator)/2 + GetAbilityModifier(ABILITY_STRENGTH, oInitiator); if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_NONE, oInitiator)) { ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectDazed()), oTarget, RoundsToSeconds(1)); } DeleteLocalInt(oTarget, "DireFlailSmash"); } } void ShieldSpecialization(object oInitiator) { object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator); // Shield specialization if((GetBaseItemType(oItem) == BASE_ITEM_SMALLSHIELD && GetHasFeat(FEAT_SHIELD_SPECIALIZATION_LIGHT, oInitiator)) || (GetBaseItemType(oItem) == BASE_ITEM_LARGESHIELD && GetHasFeat(FEAT_SHIELD_SPECIALIZATION_HEAVY, oInitiator))) { itemproperty ip = GetFirstItemProperty(oItem); int iTemp; while(GetIsItemPropertyValid(ip)) { int iIpType = GetItemPropertyType(ip); if (iIpType == ITEM_PROPERTY_AC_BONUS) { iTemp = GetItemPropertyCostTableValue(ip); break; } ip = GetNextItemProperty(oItem); } //FloatingTextStringOnCreature("Adding Shield Specialization bonus of "+IntToString(iTemp+1), oInitiator, FALSE); IPSafeAddItemProperty(oItem, ItemPropertyACBonus(iTemp+1), 5.95, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); } } void FocusedShield(object oInitiator) { object oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator); int nBase = GetBaseItemType(oItem); if ((nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD) && GetIsPsionicallyFocused(oInitiator)) { itemproperty ip = GetFirstItemProperty(oItem); int iTemp; while(GetIsItemPropertyValid(ip)) { int iIpType = GetItemPropertyType(ip); if (iIpType == ITEM_PROPERTY_AC_BONUS) { iTemp = GetItemPropertyCostTableValue(ip); break; } ip = GetNextItemProperty(oItem); } //FloatingTextStringOnCreature("Adding Focused Shield bonus of "+IntToString(iTemp+1), oInitiator, FALSE); IPSafeAddItemProperty(oItem, ItemPropertyACBonus(iTemp+1), 5.95, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); } } void Shieldmate(object oInitiator) { // Have to be awake and aware to count if (PRCGetHasEffect(EFFECT_TYPE_CONFUSED, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_DOMINATED, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_DAZED, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_PETRIFY, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_PARALYZE, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_SLEEP, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_STUNNED, oInitiator) || PRCGetHasEffect(EFFECT_TYPE_FRIGHTENED, oInitiator) || GetGrapple(oInitiator)) { return; } int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator)); if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD) { location lTarget = GetLocation(oInitiator); // Use the function to get the closest creature as a target object oAreaTarget = MyFirstObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); while(GetIsObjectValid(oAreaTarget)) { if(oAreaTarget != oInitiator && // Not you GetIsInMeleeRange(oInitiator, oAreaTarget) && // They must be in melee range GetIsFriend(oAreaTarget, oInitiator)) // Only allies { int nBonus = 1; if (nBase == BASE_ITEM_TOWERSHIELD) nBonus += 1; if (GetHasFeat(FEAT_IMPROVED_SHIELDMATE, oInitiator)) nBonus += 1; ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectACIncrease(nBonus, AC_SHIELD_ENCHANTMENT_BONUS)), oAreaTarget, 6.0); } //Select the next target within the spell shape. oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_SMALL, lTarget, TRUE, OBJECT_TYPE_CREATURE); } } } void RethDekalaAura(object oInitiator) { location lTarget = GetLocation(oInitiator); // 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 != oInitiator && // Not you. Hits everyone else though, even allies. GetIsInMeleeRange(oInitiator, oAreaTarget)) // They must be in melee range { int nDamage = d6(); int nDC = 10 + GetHitDice(oInitiator)/2 + GetAbilityModifier(ABILITY_CONSTITUTION, oInitiator); if(!PRCMySavingThrow(SAVING_THROW_FORT, oAreaTarget, nDC, SAVING_THROW_TYPE_NONE)) { // Half fire, half acid ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDamage(nDamage/2, DAMAGE_TYPE_FIRE)), oAreaTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_M), oAreaTarget); // The +1 makes acid round up instead of round down, so you don't miss out on odd numbers ApplyEffectToObject(DURATION_TYPE_INSTANT, SupernaturalEffect(EffectDamage((nDamage+1)/2, DAMAGE_TYPE_ACID)), oAreaTarget); ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_ACID_L), oAreaTarget); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, SupernaturalEffect(EffectSickened()), oAreaTarget, 6.0); } } //Select the next target within the spell shape. oAreaTarget = MyNextObjectInShape(SHAPE_SPHERE, RADIUS_SIZE_MEDIUM, lTarget, TRUE, OBJECT_TYPE_CREATURE); } } void HadrimoiPerfectSymmetry(object oInitiator) { int nSize = PRCGetCreatureSize(oInitiator); object oSkin = GetPCSkin(oInitiator); object oItemR = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator); int nWeaponSizeR = GetWeaponSize(oItemR); object oItemL = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator); int nWeaponSizeL = GetWeaponSize(oItemL); // is the size appropriate for a light weapon? if (nWeaponSizeR < nSize && nWeaponSizeL < nSize) { SetLocalInt(oInitiator, "HadrimoiPerfectSymmetry", TRUE); IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_AMBIDEXTROUS), 9999.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_FEAT_TWO_WEAPON_FIGHTING), 9999.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); //int nBAB = GetBaseAttackBonus(oInitiator); SetCompositeAttackBonus(oInitiator, "HadrimoiPerfectSymmetry", 2, ATTACK_BONUS_MISC); /*object oWP = GetObjectToApplyNewEffect("WP_HadrimoiPerfectSymmetry", oInitiator, TRUE); AssignCommand(oWP, ActionDoCommand(ApplyEffectToObject(DURATION_TYPE_PERMANENT, SupernaturalEffect(EffectModifyAttacks(nAttackCount-1)), oInitiator)));*/ } else { DeleteLocalInt(oInitiator, "HadrimoiPerfectSymmetry"); RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, IP_CONST_FEAT_AMBIDEXTROUS, -1, -1, "", -1, DURATION_TYPE_TEMPORARY); RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, IP_CONST_FEAT_TWO_WEAPON_FIGHTING, -1, -1, "", -1, DURATION_TYPE_TEMPORARY); SetCompositeAttackBonus(oInitiator, "HadrimoiPerfectSymmetry", 0, ATTACK_BONUS_MISC); /*object oWP = GetObjectToApplyNewEffect("WP_HadrimoiPerfectSymmetry", oInitiator, TRUE);*/ } } ////////////////////////////////////////////////// /* Void Main and Event Triggers */ ////////////////////////////////////////////////// void main() { int nEvent = GetRunningEvent(); if(DEBUG) DoDebug("tob_feats running, event: " + IntToString(nEvent)); // Get the PC. This is event-dependent object oInitiator; switch(nEvent) { case EVENT_ITEM_ONHIT: oInitiator = OBJECT_SELF; break; case EVENT_ONPLAYEREQUIPITEM: oInitiator = GetItemLastEquippedBy(); break; case EVENT_ONPLAYERUNEQUIPITEM: oInitiator = GetItemLastUnequippedBy(); break; case EVENT_ONHEARTBEAT: oInitiator = OBJECT_SELF; break; default: oInitiator = OBJECT_SELF; } object oItem; object oSkin = GetPCSkin(oInitiator); int nSnap = GetLocalInt(oInitiator, "SnapKick"); // We aren't being called from any event, instead from EvalPRCFeats if(nEvent == FALSE) { if (BladeMeditationFeat(oInitiator) >= 1) BladeMeditation(oInitiator); // Hook in the events if(DEBUG) DoDebug("tob_feats: Adding eventhooks"); AddEventScript(oInitiator, EVENT_ONPLAYEREQUIPITEM, "tob_feats", TRUE, FALSE); AddEventScript(oInitiator, EVENT_ONPLAYERUNEQUIPITEM, "tob_feats", TRUE, FALSE); AddEventScript(oInitiator, EVENT_ONHEARTBEAT, "tob_feats", TRUE, FALSE); } else if(nEvent == EVENT_ITEM_ONHIT) { oItem = GetSpellCastItem(); object oTarget = PRCGetSpellTargetObject(); if(DEBUG) DoDebug("tob_feats: OnHit:\n" + "oInitiator = " + DebugObject2Str(oInitiator) + "\n" + "oItem = " + DebugObject2Str(oItem) + "\n" + "oTarget = " + DebugObject2Str(oTarget) + "\n" ); if (GetHasFeat(FEAT_DEVOTED_BULWARK, oInitiator)) DevotedBulwark(oInitiator, oTarget); if (nSnap == TRUE) SnapKick(oInitiator, oTarget); if (GetHasFeat(FEAT_THREE_MOUNTAINS, oInitiator)) ThreeMountains(oInitiator, oTarget); if (GetHasFeat(FEAT_VAE_SCHOOL, oInitiator) && GetCanSneakAttack(oTarget, oInitiator)) VaeSchool(oInitiator, oTarget); if (GetHasFeat(FEAT_XANIQOS_SCHOOL, oInitiator)) XaniqosSchool(oInitiator, oTarget, oItem, nEvent); if (GetHasFeat(FEAT_CRESCENT_MOON, oInitiator)) CrescentMoon(oInitiator, oTarget); if (GetHasFeat(FEAT_BEAR_FANG, oInitiator)) BearFang(oInitiator, oTarget); if (GetHasFeat(FEAT_DIRE_FLAIL_SMASH, oInitiator)) DireFlailSmash(oInitiator, oTarget); }// end if - Running OnHit event else if(nEvent == EVENT_ONPLAYEREQUIPITEM) { oInitiator = GetItemLastEquippedBy(); oItem = GetItemLastEquipped(); if(DEBUG) DoDebug("tob_feats - OnEquip\n" + "oInitiator = " + DebugObject2Str(oInitiator) + "\n" + "oItem = " + DebugObject2Str(oItem) + "\n" ); // Armor checks if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR) { if (GetHasFeat(FEAT_DEVOTED_BULWARK, oInitiator)) { // Add eventhook to the armor IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } // Weapons for Three Mountains if (GetHasFeat(FEAT_THREE_MOUNTAINS, oInitiator)) { if (oItem == GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator) && (GetBaseItemType(oItem) == BASE_ITEM_MORNINGSTAR || GetBaseItemType(oItem) == BASE_ITEM_HEAVYFLAIL || GetBaseItemType(oItem) == BASE_ITEM_DIREMACE) || GetBaseItemType(oItem) == BASE_ITEM_HEAVY_MACE) { // Add eventhook to the weapon IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } // Weapons for Snap Kick if (oItem == GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator) && IPGetIsMeleeWeapon(oItem) && nSnap == TRUE) { // Add eventhook to the weapon IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } // Weapons for Vae School if (oItem == GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator) && GetBaseItemType(oItem) == BASE_ITEM_WHIP && GetHasFeat(FEAT_VAE_SCHOOL, oInitiator)) { // Add eventhook to the weapon IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } if (GetHasFeat(FEAT_XANIQOS_SCHOOL, oInitiator)) XaniqosSchool(oInitiator, OBJECT_INVALID, oItem, nEvent); if (GetHasFeat(FEAT_CROSSBOW_SNIPER, oInitiator)) CrossbowSniper(oInitiator, oItem, nEvent); // Weapons for Crescent Moon if (GetHasFeat(FEAT_CRESCENT_MOON, oInitiator)) { if (GetBaseItemType(oItem) == BASE_ITEM_SCIMITAR || GetBaseItemType(oItem) == BASE_ITEM_LONGSWORD || GetBaseItemType(oItem) == BASE_ITEM_BASTARDSWORD || GetBaseItemType(oItem) == BASE_ITEM_DAGGER || GetBaseItemType(oItem) == BASE_ITEM_SHORTSWORD) { // Add eventhook to the weapon IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } // Weapons for Bear Fang if (GetHasFeat(FEAT_BEAR_FANG, oInitiator)) { if (GetBaseItemType(oItem) == BASE_ITEM_BATTLEAXE || GetBaseItemType(oItem) == BASE_ITEM_HANDAXE || GetBaseItemType(oItem) == BASE_ITEM_DWARVENWARAXE || GetBaseItemType(oItem) == BASE_ITEM_DAGGER) { // Add eventhook to the weapon IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } // Weapons for Dire Flail Smash if (GetHasFeat(FEAT_DIRE_FLAIL_SMASH, oInitiator)) { if (oItem == GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oInitiator) && GetBaseItemType(oItem) == BASE_ITEM_DIREMACE) { // Add eventhook to the weapon IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); AddEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); } } if (GetHasFeat(FEAT_SHIELDED_CASTING, oInitiator)) { int nBase = GetBaseItemType(oItem); if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD) { IPSafeAddItemProperty(oSkin, PRCItemPropertyBonusFeat(IP_CONST_IMP_CC), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE); } } if (GetRacialType(oInitiator) == RACIAL_TYPE_RETH_DEKALA && GetIsWeapon(oItem)) { IPSafeAddItemProperty(oItem, ItemPropertyAttackBonus(4), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); IPSafeAddItemProperty(oItem, ItemPropertyAttackPenalty(4), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); } if (GetRacialType(oInitiator) == RACIAL_TYPE_HADRIMOI) HadrimoiPerfectSymmetry(oInitiator); } // We are called from the OnPlayerUnEquipItem eventhook. Remove OnHitCast: Unique Power from oInitiator's weapon else if(nEvent == EVENT_ONPLAYERUNEQUIPITEM) { oInitiator = GetItemLastUnequippedBy(); oItem = GetItemLastUnequipped(); if(DEBUG) DoDebug("tob_feats - OnUnEquip\n" + "oInitiator = " + DebugObject2Str(oInitiator) + "\n" + "oItem = " + DebugObject2Str(oItem) + "\n" ); // Only applies to armours if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR) { // Add eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } // Weapons for Snap Kick if (IPGetIsMeleeWeapon(oItem) && nSnap) { // Remove eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } // Weapons for Three Mountains if (GetHasFeat(FEAT_THREE_MOUNTAINS, oInitiator)) { if (GetBaseItemType(oItem) == BASE_ITEM_MORNINGSTAR || GetBaseItemType(oItem) == BASE_ITEM_HEAVYFLAIL || GetBaseItemType(oItem) == BASE_ITEM_DIREMACE || GetBaseItemType(oItem) == BASE_ITEM_HEAVY_MACE) { // Remove eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } } // Weapons for Vae School if (GetBaseItemType(oItem) == BASE_ITEM_WHIP && GetHasFeat(FEAT_VAE_SCHOOL, oInitiator)) { // Remove eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } if (GetHasFeat(FEAT_XANIQOS_SCHOOL, oInitiator)) XaniqosSchool(oInitiator, OBJECT_INVALID, oItem, nEvent); if (GetHasFeat(FEAT_CROSSBOW_SNIPER, oInitiator)) CrossbowSniper(oInitiator, oItem, nEvent); // Weapons for Crescent Moon if (GetHasFeat(FEAT_CRESCENT_MOON, oInitiator)) { if (GetBaseItemType(oItem) == BASE_ITEM_SCIMITAR || GetBaseItemType(oItem) == BASE_ITEM_LONGSWORD || GetBaseItemType(oItem) == BASE_ITEM_BASTARDSWORD || GetBaseItemType(oItem) == BASE_ITEM_DAGGER || GetBaseItemType(oItem) == BASE_ITEM_SHORTSWORD) { // Remove eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } } // Weapons for Bear Fang if (GetHasFeat(FEAT_BEAR_FANG, oInitiator)) { if (GetBaseItemType(oItem) == BASE_ITEM_BATTLEAXE || GetBaseItemType(oItem) == BASE_ITEM_HANDAXE || GetBaseItemType(oItem) == BASE_ITEM_DWARVENWARAXE || GetBaseItemType(oItem) == BASE_ITEM_DAGGER) { // Remove eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } } // Weapons for Dire Flail Smash if (GetHasFeat(FEAT_DIRE_FLAIL_SMASH, oInitiator)) { if (GetBaseItemType(oItem) == BASE_ITEM_DIREMACE) { // Remove eventhook to the item RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "tob_feats", TRUE, FALSE); // Remove the temporary OnHitCastSpell: Unique RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY); } } if (GetHasFeat(FEAT_SHIELDED_CASTING, oInitiator)) { // If you don't have a shield in your left hand, no benefit int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oInitiator)); if (nBase != BASE_ITEM_SMALLSHIELD && nBase != BASE_ITEM_LARGESHIELD && nBase != BASE_ITEM_TOWERSHIELD) { RemoveSpecificProperty(oSkin, ITEM_PROPERTY_BONUS_FEAT, IP_CONST_IMP_CC); } } if (GetRacialType(oInitiator) == RACIAL_TYPE_RETH_DEKALA && GetIsWeapon(oItem)) { // Remove the attack bonus RemoveSpecificProperty(oItem, ITEM_PROPERTY_ATTACK_BONUS, -1, -1, 1, "", -1, DURATION_TYPE_TEMPORARY); RemoveSpecificProperty(oItem, ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER, -1, -1, 1, "", -1, DURATION_TYPE_TEMPORARY); } if (GetRacialType(oInitiator) == RACIAL_TYPE_HADRIMOI) HadrimoiPerfectSymmetry(oInitiator); } else if(nEvent == EVENT_ONHEARTBEAT) { if(GetHasFeat(FEAT_SHADOW_BLADE, oInitiator)) ShadowBlade(oInitiator); if(GetHasFeat(FEAT_RAPID_ASSAULT, oInitiator)) RapidAssault(oInitiator); if(GetHasFeat(FEAT_DESERT_WIND_DODGE, oInitiator) || GetHasFeat(FEAT_DESERT_FIRE, oInitiator)) DesertWind(oInitiator); if(GetHasFeat(FEAT_IRONHEART_AURA, oInitiator)) IronheartAura(oInitiator); if(GetHasFeat(FEAT_SHADOW_TRICKSTER, oInitiator)) ShadowTrickster(oInitiator); if(GetHasFeat(FEAT_WHITE_RAVEN_DEFENSE, oInitiator)) WhiteRavenDefense(oInitiator); if(GetHasFeat(FEAT_INLINDL_SCHOOL, oInitiator)) InlindlSchool(oInitiator); if(GetHasFeat(FEAT_XANIQOS_SCHOOL, oInitiator)) XaniqosSchool(oInitiator, OBJECT_INVALID, oItem, nEvent); if(GetHasFeat(FEAT_EXPEDITIOUS_DODGE, oInitiator)) ExpeditiousDodge(oInitiator); if(GetHasFeat(FEAT_SHIELD_WALL, oInitiator)) ShieldWall(oInitiator); if(GetHasFeat(FEAT_QUICK_STAFF, oInitiator)) QuickStaff(oInitiator); if(GetHasFeat(FEAT_IMPROVED_RAPID_SHOT, oInitiator)) ImprovedRapidShot(oInitiator); if(GetHasFeat(FEAT_BEAR_FANG, oInitiator)) BearFangHB(oInitiator); if(GetHasFeat(FEAT_SHIELD_SPECIALIZATION_LIGHT, oInitiator) || GetHasFeat(FEAT_SHIELD_SPECIALIZATION_HEAVY, oInitiator)) ShieldSpecialization(oInitiator); if(GetHasFeat(FEAT_FOCUSED_SHIELD, oInitiator)) FocusedShield(oInitiator); if(GetHasFeat(FEAT_SHIELDMATE, oInitiator)) Shieldmate(oInitiator); if(GetRacialType(oInitiator) == RACIAL_TYPE_RETH_DEKALA) RethDekalaAura(oInitiator); } }