Files
Anphillia_PRC8/_module/nss/spell_weapon.nss
Jaysyn904 00d2c183e8 Update for PRC8 parity
Update for PRC8 parity.  Full compile.
2025-02-08 14:10:00 -05:00

313 lines
13 KiB
Plaintext

#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));
}