#include "nw_i0_spells" //#include "x2_i0_spells" #include "prc_inc_spells" #include "x2_inc_spellhook" #include "x2_inc_toollib" #include "util_inc" object GetTargetCreature() { object oTarget = GetSpellTargetObject(); if (GetObjectType(oTarget) == OBJECT_TYPE_CREATURE) return oTarget; else if (GetObjectType(oTarget) == OBJECT_TYPE_ITEM) return GetItemPossessor(oTarget); else return OBJECT_INVALID; } object GetTargetWeapon() { object oTarget = GetSpellTargetObject(); object oWeapon; if (GetObjectType(oTarget) == OBJECT_TYPE_ITEM) { oWeapon = oTarget; } else { oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget); if (oWeapon == OBJECT_INVALID || !util_IsWeapon(oWeapon)) { oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget); } if (oWeapon == OBJECT_INVALID || !util_IsWeapon(oWeapon)) { oWeapon = GetItemInSlot(INVENTORY_SLOT_ARMS, oTarget); } if (oWeapon == OBJECT_INVALID || !util_IsWeapon(oWeapon)) { oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oTarget); } if (oWeapon == OBJECT_INVALID || !util_IsWeapon(oWeapon)) { oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oTarget); } if (oWeapon == OBJECT_INVALID || !util_IsWeapon(oWeapon)) { oWeapon = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oTarget); } } if (!util_IsWeapon(oWeapon)) { oWeapon = OBJECT_INVALID; } return oWeapon; } float GetSpellDuration() { int nSpellID = GetSpellId(); int nCasterLvl = GetCasterLevel(OBJECT_SELF); int nMetaMagic = GetMetaMagicFeat(); float fDuration; switch (nSpellID) { case SPELL_MAGIC_WEAPON: case SPELL_GREATER_MAGIC_WEAPON: case SPELL_DARKFIRE: case SPELL_FLAME_WEAPON: fDuration = TurnsToSeconds(2*nCasterLvl); break; case SPELL_BLADE_THIRST: fDuration = RoundsToSeconds(2*nCasterLvl); break; case SPELL_KEEN_EDGE: fDuration = TurnsToSeconds(10*nCasterLvl); break; case SPELL_BLESS_WEAPON: fDuration = RoundsToSeconds(2*nCasterLvl); break; case SPELL_HOLY_SWORD: fDuration = RoundsToSeconds(nCasterLvl); break; default: return 0.0; } if (nMetaMagic == METAMAGIC_EXTEND) fDuration *= 2; return fDuration; } void AddGreaterEnhancementEffectToWeapon(object oMyWeapon, float fDuration, int nBonus) { IPSafeAddItemProperty(oMyWeapon,ItemPropertyEnhancementBonus(nBonus), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE); return; } void AddKeenEffectToWeapon(object oMyWeapon, float fDuration) { IPSafeAddItemProperty(oMyWeapon,ItemPropertyKeen(), fDuration, X2_IP_ADDPROP_POLICY_KEEP_EXISTING ,TRUE,TRUE); return; } void AddBlessEffectToWeapon(object oTarget, float fDuration) { // If the spell is cast again, any previous enhancement boni are kept IPSafeAddItemProperty(oTarget, ItemPropertyEnhancementBonus(1), fDuration, X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE); // Replace existing temporary anti undead boni IPSafeAddItemProperty(oTarget, ItemPropertyDamageBonusVsRace(IP_CONST_RACIALTYPE_UNDEAD, IP_CONST_DAMAGETYPE_DIVINE, IP_CONST_DAMAGEBONUS_2d6), fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING ); IPSafeAddItemProperty(oTarget, ItemPropertyVisualEffect(ITEM_VISUAL_HOLY), fDuration,X2_IP_ADDPROP_POLICY_REPLACE_EXISTING,FALSE,TRUE ); return; } void AddHolyAvengerEffectToWeapon(object oMyWeapon, float fDuration) { //IPSafeAddItemProperty(oMyWeapon,ItemPropertyEnhancementBonus(2), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING ,FALSE,TRUE); IPSafeAddItemProperty(oMyWeapon,ItemPropertyHolyAvenger(), fDuration, X2_IP_ADDPROP_POLICY_KEEP_EXISTING,TRUE,TRUE); return; } void AddItemEnhancementEffect(object oItem, float fDuration, int nEnhancementBonus) { int nBaseItemType = GetBaseItemType(oItem); // Ranged weapons and bracers/gauntlets can only gain attac bonuses if ( nBaseItemType == BASE_ITEM_LONGBOW || nBaseItemType == BASE_ITEM_HEAVYCROSSBOW || nBaseItemType == BASE_ITEM_GLOVES || nBaseItemType == BASE_ITEM_SHORTBOW || nBaseItemType == BASE_ITEM_SLING || nBaseItemType == BASE_ITEM_LIGHTCROSSBOW) IPSafeAddItemProperty(oItem, ItemPropertyAttackBonus(nEnhancementBonus), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); // Ranged ammunition can only gain damage bonuses else if ( nBaseItemType == BASE_ITEM_ARROW || nBaseItemType == BASE_ITEM_BOLT || nBaseItemType == BASE_ITEM_BULLET) IPSafeAddItemProperty(oItem, ItemPropertyDamageBonus(nBaseItemType == BASE_ITEM_BULLET ? IP_CONST_DAMAGETYPE_BLUDGEONING : IP_CONST_DAMAGETYPE_PIERCING,nEnhancementBonus), fDuration, X2_IP_ADDPROP_POLICY_IGNORE_EXISTING, FALSE, TRUE); // All other weapons can gain enhancement bonuses else if ( nBaseItemType == BASE_ITEM_ARMOR) IPSafeAddItemProperty(oItem, ItemPropertyACBonus(nEnhancementBonus), fDuration, X2_IP_ADDPROP_POLICY_IGNORE_EXISTING, FALSE, TRUE); // All other weapons can gain enhancement bonuses else if (util_IsWeapon(oItem)) IPSafeAddItemProperty(oItem, ItemPropertyEnhancementBonus(nEnhancementBonus), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); } void AddItemEnergyEffect(object oItem, float fDuration, int nDamageType, int nDamageBonus) { // Abort for non-weapons int nBaseItemType = GetBaseItemType(oItem); if (util_IsWeapon(oItem) || nBaseItemType == BASE_ITEM_GLOVES) { itemproperty ip = GetFirstItemProperty(oItem); while (GetIsItemPropertyValid(ip)) { if (GetItemPropertyTag(ip) == "SPELL_ENERGY_EFFECT") { FloatingTextStringOnCreature("You override an existing enchantment", OBJECT_SELF, FALSE); RemoveItemProperty(oItem, ip); } ip = GetNextItemProperty(oItem); } IPSafeAddItemProperty(oItem, TagItemProperty(ItemPropertyDamageBonus(nDamageType, nDamageBonus), "SPELL_ENERGY_EFFECT"), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, FALSE); int nItemVisual = -1; switch (nDamageType) { case IP_CONST_DAMAGETYPE_ACID: nItemVisual = ITEM_VISUAL_ACID; break; case IP_CONST_DAMAGETYPE_COLD: nItemVisual = ITEM_VISUAL_COLD; break; case IP_CONST_DAMAGETYPE_DIVINE: switch (GetAlignmentGoodEvil(OBJECT_SELF)) { case ALIGNMENT_GOOD: nItemVisual = ITEM_VISUAL_HOLY; break; case ALIGNMENT_NEUTRAL: nItemVisual = ITEM_VISUAL_SONIC; break; case ALIGNMENT_EVIL: nItemVisual = ITEM_VISUAL_EVIL; break; } break; case IP_CONST_DAMAGETYPE_ELECTRICAL: nItemVisual = ITEM_VISUAL_ELECTRICAL; break; case IP_CONST_DAMAGETYPE_FIRE: nItemVisual = ITEM_VISUAL_FIRE; break; case IP_CONST_DAMAGETYPE_MAGICAL: nItemVisual = ITEM_VISUAL_SONIC; break; case IP_CONST_DAMAGETYPE_NEGATIVE: nItemVisual = ITEM_VISUAL_EVIL; break; case IP_CONST_DAMAGETYPE_POSITIVE: nItemVisual = ITEM_VISUAL_HOLY; break; case IP_CONST_DAMAGETYPE_SONIC: nItemVisual = ITEM_VISUAL_SONIC; break; } // Add the item visual only if needed if (nItemVisual != -1) IPSafeAddItemProperty(oItem, ItemPropertyVisualEffect(nItemVisual), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE); } } void main() { int nSpellID = GetSpellId(); object oCaster = OBJECT_SELF; object oCreature = GetTargetCreature(); object oWeapon = GetTargetWeapon(); object oOffHand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature); float fDuration = GetSpellDuration(); int nCasterLvl = GetCasterLevel(oCaster); int nRemainingSpellUses = GetHasSpell(nSpellID, oCaster); if (fDuration <= 0.0 || oWeapon == OBJECT_INVALID) { FloatingTextStringOnCreature("Your spell did not take hold", oCaster, FALSE); return; } int nApplyToOffHand = FALSE; if (GetSpellTargetObject() == oCreature && GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature) == oWeapon && util_IsWeapon(oOffHand) && nRemainingSpellUses > 0) { DecrementRemainingSpellUses(oCaster, nSpellID); nApplyToOffHand = TRUE; } //Declare major variables effect eVis; switch (nSpellID) { case SPELL_HOLY_SWORD: eVis = EffectVisualEffect(VFX_IMP_GOOD_HELP); break; default: eVis = EffectVisualEffect(VFX_IMP_SUPER_HEROISM); } effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE); ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oCreature); ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDur, oCreature, fDuration); switch (nSpellID) { case SPELL_MAGIC_WEAPON: AddItemEnhancementEffect(oWeapon, fDuration, 1); if (nApplyToOffHand) AddItemEnhancementEffect(oOffHand, fDuration, 1); break; case SPELL_GREATER_MAGIC_WEAPON: AddItemEnhancementEffect(oWeapon, fDuration, PRCMin(nCasterLvl/3, 3)); if (nApplyToOffHand) AddItemEnhancementEffect(oOffHand, fDuration, PRCMin(nCasterLvl/3, 3)); break; case SPELL_KEEN_EDGE: AddKeenEffectToWeapon(oWeapon, fDuration); if (nApplyToOffHand) AddKeenEffectToWeapon(oOffHand, fDuration); break; case SPELL_BLESS_WEAPON: AddBlessEffectToWeapon(oWeapon, fDuration); if (nApplyToOffHand) AddBlessEffectToWeapon(oOffHand, fDuration); break; case SPELL_HOLY_SWORD: TLVFXPillar(VFX_IMP_GOOD_HELP, GetLocation(GetSpellTargetObject()), 4, 0.0f, 6.0f); AddHolyAvengerEffectToWeapon(oWeapon, fDuration); if (nApplyToOffHand) AddHolyAvengerEffectToWeapon(oOffHand, fDuration); break; case SPELL_BLADE_THIRST: // If we targeted a creature that's dual wielding, apply +2 to both if (GetSpellTargetObject() == oCreature && GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature) == oWeapon && util_IsWeapon(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature))) { AddItemEnhancementEffect(oWeapon, fDuration, 2); AddItemEnhancementEffect(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature), fDuration, 2); } else { AddItemEnhancementEffect(oWeapon, fDuration, 3); } break; case SPELL_FLAME_WEAPON: case SPELL_DARKFIRE: { int nDamageType = GetLocalInt(oCaster, "SPELL_DAMAGE_TYPE"); if (nDamageType == 0) { SendMessageToPC(oCaster, "No damage type selected, defaulting to fire. Type '/dmg [f|c|l|a]' to select"); nDamageType = IP_CONST_DAMAGETYPE_FIRE; } AddItemEnergyEffect(oWeapon, fDuration, nDamageType, IP_CONST_DAMAGEBONUS_1d6); if (nApplyToOffHand) AddItemEnergyEffect(oOffHand, fDuration, nDamageType, IP_CONST_DAMAGEBONUS_1d6); } break; default: return; } string sItemName = GetName(oWeapon); if (nApplyToOffHand) { string sOffHandName = GetName(oOffHand); if (sItemName == sOffHandName) sItemName += " (Right Hand) and " + sOffHandName + " (Left Hand)"; else sItemName += " and " + GetName(oOffHand); } if (GetIsObjectValid(oCreature) && oCreature != oCaster) { DelayCommand(1.0, FloatingTextStringOnCreature("You enchanted " + GetName(oCreature) + "'s " + sItemName, oCaster, FALSE)); DelayCommand(1.0, FloatingTextStringOnCreature(GetName(oCaster) + " enchanted your " + sItemName, oCreature, FALSE)); } else if (oCreature == oCaster) DelayCommand(1.0, FloatingTextStringOnCreature("You enchanted your " + sItemName, oCaster, FALSE)); else DelayCommand(1.0, FloatingTextStringOnCreature("You enchanted the targeted " + sItemName, oCaster, FALSE)); }