Jaysyn904 e641b42f84 Exalted update
Updated Vow of Poverty. Added Sanctify Ki Strike, Holy Strike, Fist of Heavens, Vow of Abstinence, Vow of Chastity & Gift of Faith.  (@fenac).  Turned off the Taunt & Parry skills.  Re-disabled AC & save bonuses from Tumble & Spellcraft.   Updated min() & max() to PRCmin() & PRCmax() to not conflict with similarly named NUI adjacent functions.  Set Point Blank Shot to 30' per PnP.  Added icon for Chosen of Evil.  Started work on Hidden Talent.  Created Psionics function cheatsheet.  Updated release archive.
2025-01-29 22:46:38 -05:00

765 lines
34 KiB
Plaintext

//::///////////////////////////////////////////////
//:: Binding events
//:: bnd_events
//::///////////////////////////////////////////////
/** @file
Does all Binding content that require event scripting.
@author Stratovarius
@date Created - 2021.02.03
*/
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "bnd_inc_bndfunc"
#include "prc_inc_unarmed"
#include "prc_inc_fork"
//////////////////////////////////////////////////
/* Internal Functions */
//////////////////////////////////////////////////
void CheckIsDropped(object oBinder, object oItem)
{
if(DEBUG) DoDebug("bnd_events: CheckIsDropped()");
if(GetItemPossessor(oItem) == oBinder)
{
if(DEBUG) DoDebug("bnd_events:GetItemPosessor(oItem) == oBinder");
// No check for commandability here. Let's not break any cutscenes
// If cheating does occur, set the char to commandable first here.
//And remember to restore the setting.
AssignCommand(oBinder, ClearAllActions());
AssignCommand(oBinder, ActionPutDownItem(oItem));
DelayCommand(2.0, CheckIsDropped(oBinder, oItem));
}
}
//////////////////////////////////////////////////
/* Content Functions */
//////////////////////////////////////////////////
void AymHaloOfFire(object oBinder, object oTarget)
{
if (GetDistanceBetween(oBinder, oTarget) <= FeetToMeters(10.0f))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(1), DAMAGE_TYPE_FIRE), oTarget);
}
}
void NaberiusHeal(object oBinder)
{
int nCount = GetLocalInt(oBinder, "NaberiusCount");
//FloatingTextStringOnCreature("Naberius heal has spell effect, nCount: "+IntToString(nCount), oBinder, FALSE);
if (nCount == 20) // Default timer is 2 real world minutes to an hour
{
RecoverUnHealableAbilityDamage(oBinder, ABILITY_STRENGTH, 1);
RecoverUnHealableAbilityDamage(oBinder, ABILITY_DEXTERITY, 1);
RecoverUnHealableAbilityDamage(oBinder, ABILITY_CONSTITUTION, 1);
RecoverUnHealableAbilityDamage(oBinder, ABILITY_INTELLIGENCE, 1);
RecoverUnHealableAbilityDamage(oBinder, ABILITY_WISDOM, 1);
RecoverUnHealableAbilityDamage(oBinder, ABILITY_CHARISMA, 1);
// Reset the number
nCount -= 20;
}
effect eEffect = GetFirstEffect(oBinder);
while(GetIsEffectValid(eEffect) && !GetLocalInt(oBinder, "NaberiusHealLock"))
{
// Is it an ability decrease?
if(GetEffectType(eEffect) == EFFECT_TYPE_ABILITY_DECREASE)
{
string sTag = GetEffectTag(eEffect);
//FloatingTextStringOnCreature("Effect tag is "+sTag, oBinder, FALSE);
int nAbil = StringToInt(GetSubString(sTag, 0, 1));
//FloatingTextStringOnCreature("Effect ability is "+IntToString(nAbil), oBinder, FALSE);
int nAmount = StringToInt(GetSubString(sTag, 1, 2));
//FloatingTextStringOnCreature("Effect ability is "+IntToString(nAmount), oBinder, FALSE);
SetLocalInt(oBinder, "NaberiusHealLock", TRUE);
DelayCommand(nAmount * 6.0, RemoveEffect(oBinder, eEffect));
DelayCommand(nAmount * 6.0, DeleteLocalInt(oBinder, "NaberiusHealLock"));
//DelayCommand(nAmount * 6.0, FloatingTextStringOnCreature("Naberius heal removed nAmount: "+IntToString(nAmount), oBinder, FALSE));
}
eEffect = GetNextEffect(oBinder);
}
SetLocalInt(oBinder, "NaberiusCount", nCount+1);
}
void HaagentiTrans(object oBinder)
{
effect eEffect = GetFirstEffect(oBinder);
while(GetIsEffectValid(eEffect))
{
// Is it poly or petr
if(GetEffectType(eEffect) == EFFECT_TYPE_PETRIFY || GetEffectType(eEffect) == EFFECT_TYPE_POLYMORPH)
RemoveEffect(oBinder, eEffect);
eEffect = GetNextEffect(oBinder);
}
}
void AndrasInfluence(object oBinder)
{
int nCombat = GetIsInCombat(oBinder);
int nCount = GetLocalInt(oBinder, "AndrasCombat");
if (nCombat)
{
nCount += 1;
SetLocalInt(oBinder, "AndrasCombat", nCount);
if (nCount >= 10)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectExhausted()), oBinder, HoursToSeconds(1));
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectFrightened()), oBinder, RoundsToSeconds(d4()));
}
}
else
DeleteLocalInt(oBinder, "AndrasCombat");
}
void EurynomePoisonBloodDelay(object oBinder, object oTarget, int nDC)
{
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_POISON))
{
int nDice = PRCMin(5, GetBinderLevel(oBinder, VESTIGE_EURYNOME)/3);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_ACID_S), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(nDice), DAMAGE_TYPE_ACID), oTarget);
}
}
void EurynomePoisonBlood(object oBinder, object oTarget)
{
// Enemy in vaguely melee range, wolves and other long creatures can actually hit outside of 10.0
if (GetDistanceBetween(oBinder, oTarget) <= FeetToMeters(15.0f))
{
// No weapon equipped, and the target has a bite attack
if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget)) && GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oTarget)))
{
int nDC = GetBinderDC(oBinder, VESTIGE_EURYNOME);
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_POISON))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_ACID_S), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(), DAMAGE_TYPE_ACID), oTarget);
}
DelayCommand(60.0, EurynomePoisonBloodDelay(oBinder, oTarget, nDC));
}
}
}
void TenebrousVoid(object oBinder, object oTarget)
{
if (!GetLocalInt(oBinder, "TenebrousVoidStrike"))
{
int nDice = 1 + (GetBinderLevel(oBinder, VESTIGE_TENEBROUS)-7)/4;
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d8(nDice), DAMAGE_TYPE_COLD), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FROST_L), oTarget);
SetLocalInt(oBinder, "TenebrousVoidStrike", TRUE);
DelayCommand(4.5, DeleteLocalInt(oBinder, "TenebrousVoidStrike"));
}
}
void ReapplyTenebrous(object oBinder)
{
SetLocalInt(GetModule(), PRC_SPELL_TARGET_OBJECT_OVERRIDE, TRUE);
SetLocalObject(GetModule(), PRC_SPELL_TARGET_OBJECT_OVERRIDE, oBinder);
DoBindingCheck(oBinder, 18);
DelayCommand(0.1, ApplyVestige(oBinder, VESTIGE_TENEBROUS)); // Tenebrous vestiges.2da rowid
DelayCommand(1.0, DeleteLocalInt(GetModule(), PRC_SPELL_TARGET_OBJECT_OVERRIDE));
DelayCommand(1.0, DeleteLocalObject(GetModule(), PRC_SPELL_TARGET_OBJECT_OVERRIDE));
}
void SavnokInfluence(object oBinder, object oItem)
{
if (GetItemACValue(oItem) && !GetLocalInt(oBinder, "SavnokDelay"))
{
int nBase = GetBaseItemType(oItem);
AssignCommand(oBinder, ClearAllActions());
if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD)
AssignCommand(oBinder, ActionEquipItem(oItem, INVENTORY_SLOT_LEFTHAND));
if (nBase == BASE_ITEM_ARMOR)
AssignCommand(oBinder, ActionEquipItem(oItem, INVENTORY_SLOT_CHEST));
SetLocalInt(oBinder, "SavnokDelay", TRUE);
DelayCommand(0.5, DeleteLocalInt(oBinder, "SavnokDelay"));
DelayCommand(0.5, ExecuteScript("prc_speed", oBinder));
}
}
void ExpelledVestigeCleanup(object oBinder)
{
if (!GetHasSpellEffect(VESTIGE_ANDROMALIUS, oBinder))
{
DeleteLocalInt(oBinder, "AndroSneak");
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oBinder));
}
if (!GetHasSpellEffect(VESTIGE_MALPHAS, oBinder))
{
DeleteLocalInt(oBinder, "MalphasSneak");
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oBinder));
}
if (!GetHasSpellEffect(VESTIGE_FOCALOR, oBinder))
{
PRCRemoveSpellEffects(VESTIGE_FOCALOR_AURA_SADNESS, oBinder, oBinder);
PRCRemoveSpellEffects(VESTIGE_FOCALOR_AURA_SADNESS, oBinder, oBinder);
}
if (!GetHasSpellEffect(VESTIGE_RONOVE, oBinder))
{
DeleteLocalInt(oBinder, "RonovesFists");
}
if (!GetHasSpellEffect(VESTIGE_SAVNOK, oBinder) && GetIsObjectValid(GetItemPossessedBy(oBinder, "SavnokCallArmor")))
{
object oArmor = GetItemPossessedBy(oBinder, "SavnokCallArmor");
SetPlotFlag(oArmor, FALSE);
DestroyObject(oArmor);
}
if (!GetHasSpellEffect(VESTIGE_EURYNOME, oBinder) && GetIsObjectValid(GetItemPossessedBy(oBinder, "bnd_eury_hammer")))
{
object oHammer = GetItemPossessedBy(oBinder, "bnd_eury_hammer");
SetPlotFlag(oHammer, FALSE);
AssignCommand(oHammer, SetIsDestroyable(TRUE, TRUE, TRUE));
DestroyObject(oHammer);
}
// Using Disguise Self strips the hide of all the vestige feats, this reapplies them
// Checks for having naberius, but not the disguise self feat
if (GetHasSpellEffect(VESTIGE_NABERIUS, oBinder) && !GetHasFeat(9033, oBinder))
{
int i;
for(i = VESTIGE_AMON; i <= VESTIGE_ABYSM; i++)
{
if(GetHasSpellEffect(i, oBinder))
{
ApplyVestige(oBinder, i);
//FloatingTextStringOnCreature("Applying vestige "+IntToString(i), oBinder, FALSE);
}
}
}
if (!GetHasSpellEffect(VESTIGE_ACERERAK, oBinder)) DeleteLocalInt(oBinder, "AcererakHealing");
if (!GetHasSpellEffect(VESTIGE_ARETE, oBinder))
{
PRCRemoveSpellEffects(VESTIGE_ARETE_RESIST, oBinder, oBinder);
GZPRCRemoveSpellEffects(VESTIGE_ARETE_RESIST, oBinder, FALSE);
}
}
void ChupoclopsEth(object oBinder)
{
// Check to see if the WP is valid
string sWPTag = "bnd_eventsWP_" + GetName(oBinder);
object oTestWP = GetWaypointByTag(sWPTag);
if (!GetIsObjectValid(oTestWP))
{
// Create waypoint for the movement
CreateObject(OBJECT_TYPE_WAYPOINT, "nw_waypoint001", GetLocation(oBinder), FALSE, sWPTag);
if(DEBUG) DoDebug("bnd_events: Chupoclops WP for " + DebugObject2Str(oBinder) + " 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(oBinder, 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(oBinder), FALSE, sWPTag);
if(DEBUG) DoDebug("bnd_events: Moved enough: " + DebugBool2String(fDist >= fCheck));
// Moved too far or in combat
if (fDist >= fCheck || GetIsInCombat(oBinder))
{
PRCRemoveSpellEffects(VESTIGE_CHUPOCLOPS_ETHEREAL_WATCHER, oBinder, oBinder);
GZPRCRemoveSpellEffects(VESTIGE_CHUPOCLOPS_ETHEREAL_WATCHER, oBinder, FALSE);
BindAbilCooldown(oBinder, VESTIGE_CHUPOCLOPS_ETHEREAL_WATCHER, VESTIGE_CHUPOCLOPS);
}
}
}
void ShaxStormStrike(object oBinder, object oTarget)
{
if (!GetLocalInt(oBinder, "ShaxStormStrike"))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(), DAMAGE_TYPE_SONIC), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SONIC), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(), DAMAGE_TYPE_ELECTRICAL), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SPARKS), oTarget);
SetLocalInt(oBinder, "ShaxStormStrike", TRUE);
DelayCommand(4.5, DeleteLocalInt(oBinder, "ShaxStormStrike"));
}
}
void VanusDisdain(object oBinder, object oTarget)
{
if (GetHitDice(oBinder) > GetHitDice(oTarget))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(), DAMAGE_TYPE_DIVINE), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SPARKS), oTarget);
}
}
void VanusInfluence(object oBinder)
{
if (!GetLocalInt(oBinder, "PactQuality"+IntToString(VESTIGE_VANUS)))
{
int nCombat = GetLocalInt(oBinder, "VanusInfluence");
int nCurrent = GetIsInCombat(oBinder);
// We just left combat
if (nCurrent == FALSE && nCombat == TRUE)
{
SetCutsceneMode(oBinder, TRUE);
FloatingTextStringOnCreature("Victory over my enemies!", oBinder);
AssignCommand(oBinder, ActionPlayAnimation(ANIMATION_LOOPING_TALK_LAUGHING, 1.0, 6.0));
DelayCommand(6.0, SetCutsceneMode(oBinder, FALSE));
}
//FloatingTextStringOnCreature("Vanus Combat State "+IntToString(nCurrent), oBinder);
SetLocalInt(oBinder, "VanusInfluence", nCurrent);
}
}
void CityDweller(object oBinder)
{
object oArea = GetArea(oBinder);
// Urban environment, so not natural and aboveground
if (GetIsAreaNatural(oArea) != AREA_NATURAL && GetIsAreaAboveGround(oArea) == AREA_ABOVEGROUND)
{
SetLocalInt(oBinder, "DesharisSpeed", TRUE);
ExecuteScript("prc_speed", oBinder);
}
else
{
DeleteLocalInt(oBinder, "DesharisSpeed");
ExecuteScript("prc_speed", oBinder);
}
}
void EligorChromatic(object oBinder, object oTarget)
{
if (!GetLocalInt(oBinder, "EligorStrikeTimer"))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(), GetLocalInt(oBinder, "EligorStrike")), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FAERIE_FIRE), oTarget);
SetLocalInt(oBinder, "EligorStrikeTimer", TRUE);
DelayCommand(4.5, DeleteLocalInt(oBinder, "EligorStrikeTimer"));
}
}
void MarchosiasRetribution(object oBinder, object oTarget)
{
// Skirmish or sneak attack
if (GetLevelByClass(CLASS_TYPE_SCOUT, oTarget) || GetTotalSneakAttackDice(oTarget))
{
if (GetDistanceBetween(oBinder, oTarget) < FeetToMeters(30.0))
{
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(3), DAMAGE_TYPE_FIRE), oTarget);
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_SPARKS), oTarget);
}
}
}
/*
All of this below here is for the Karsite suppress item ability
*/
void SuppressItem(object oTrueSpeaker, object oTarget, int nBeats);
object GetChest(object oCreature)
{
object oChest = GetObjectByTag("npf_chest" + ObjectToString(oCreature));
if(oChest == OBJECT_INVALID)
{
object oWP = GetWaypointByTag("npf_wp_chest_sp");
oChest = CreateObject(OBJECT_TYPE_PLACEABLE, "npf_keep_chest", GetLocation(oWP), FALSE,
"npf_chest" + ObjectToString(oCreature));
}
return oChest;
}
void RemoveAllProperties(object oItem, object oPC)
{
if(DEBUG) DoDebug("ture_utr_supitem: About to remove properties from item: " + DebugObject2Str(oItem));
if(oItem == OBJECT_INVALID)
return;
int nType = GetBaseItemType(oItem);
if(nType == BASE_ITEM_TORCH
|| nType == BASE_ITEM_TRAPKIT
|| nType == BASE_ITEM_HEALERSKIT
|| nType == BASE_ITEM_GRENADE
|| nType == BASE_ITEM_THIEVESTOOLS
|| nType == BASE_ITEM_CRAFTMATERIALMED
|| nType == BASE_ITEM_CRAFTMATERIALSML
|| nType == 112)//craftbase
return;
object oWP = GetWaypointByTag("npf_wp_chest_sp");
// Generate UID
int nKey = GetLocalInt(GetModule(), "PRC_NullPsionicsField_Item_UID_Counter") + 1;
SetLocalInt(GetModule(), "PRC_NullPsionicsField_Item_UID_Counter", nKey);
string sKey = IntToString(nKey);
if(DEBUG) DoDebug("prc_pow_npfent: Removing itemproperties from item " + DebugObject2Str(oItem) + " with key value of '" + sKey + "' of creature " + DebugObject2Str(oPC));
//object oChest = GetChest(oPC);
//object oCopy = CopyObject(oItem, GetLocation(oChest), oChest);
// copying original item to a secluded waypoint in the area
// and giving it a tag that contains the key string
object oCopy = CopyObject(oItem, GetLocation(oWP), OBJECT_INVALID, "npf_item" + sKey);
//storing the key value on the original item (key value would point to the copy item)
SetLocalString(oItem, "PRC_NullPsionicsField_Item_UID", sKey);
//SetLocalObject(oItem, "ITEM_CHEST", oChest); // so the chest can be found
//SetLocalObject(oChest, sKey, oCopy); // and referenced in the chest
// Stripping original item from all properties
itemproperty ip = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ip))
{
RemoveItemProperty(oItem, ip);
ip = GetNextItemProperty(oItem);
}
}
void RestoreAllProperties(object oItem, object oPC, int nSlot = -1)
{
if(DEBUG) DoDebug("psi_pow_npfext: Attempting to restore itemproperties to: " + DebugObject2Str(oItem));
if(oPC != OBJECT_INVALID) // this is a pc object that has an item in inventory slot or normal inventory
{
if(oItem == OBJECT_INVALID)
oItem = GetItemInSlot(nSlot, oPC);
if(oItem == OBJECT_INVALID)
return;
}
//object oChest = GetLocalObject(oItem, "ITEM_CHEST");
// getting the key value - this points to the tag of the copy item
string sKey = GetLocalString(oItem, "PRC_NullPsionicsField_Item_UID");
// retrieving the copy item that is in this area
object oOriginalItem = GetObjectByTag("npf_item" + sKey);
if(DEBUG) DoDebug("psi_pow_npfext: Restoring itemproperties to item: " + DebugObject2Str(oItem) + " with key value of '" + sKey + "' for creature " + DebugObject2Str(oPC));
//object oOriginalItem = GetLocalObject(oChest, sKey);
object oNewItem;
if(oOriginalItem != OBJECT_INVALID) // item has not been restored yet
{
// replace current item with original
IPCopyItemProperties(oOriginalItem, oItem);
DestroyObject(oOriginalItem); // destroy dup item on player
//DeleteLocalObject(oChest, GetResRef(oItem)); // so it won't be restored again
DeleteLocalString(oItem, "PRC_NullPsionicsField_Item_UID");
}
}
void SuppressItem(object oTrueSpeaker, object oTarget, int nBeats)
{
// Break if they fail concentration or it runs out
if (GetBreakConcentrationCheck(oTrueSpeaker) || nBeats == 0) return;
// Remove and restore the properties
RemoveAllProperties(oTarget, GetItemPossessor(oTarget));
// Has to run before RemoveAll is called again
DelayCommand(5.8, RestoreAllProperties(oTarget, GetItemPossessor(oTarget)));
// Apply VFX
effect eImp = EffectVisualEffect(VFX_IMP_PULSE_BOMB);
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eImp, GetItemPossessor(oTarget));
DelayCommand(6.0, SuppressItem(oTrueSpeaker, oTarget, nBeats - 1));
}
void KarsiteOnHit(object oBinder, object oTarget)
{
// If the target succeeds, bail
if(PRCMySavingThrow(SAVING_THROW_WILL, oTarget, 10 + GetAbilityModifier(ABILITY_CHARISMA, oBinder), SAVING_THROW_TYPE_NONE)) return;
object oItem;
// If the right hand isn't suppressed, that gets priority
if (!GetLocalInt(oTarget, "KarsiteSuppressRight"))
{
oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
SuppressItem(oBinder, oItem, 1);
SetLocalInt(oTarget, "KarsiteSuppressRight", TRUE);
DelayCommand(5.8, DeleteLocalInt(oTarget, "KarsiteSuppressRight"));
}
else if (!GetLocalInt(oTarget, "KarsiteSuppressChest"))
{
oItem = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
SuppressItem(oBinder, oItem, 1);
SetLocalInt(oTarget, "KarsiteSuppressChest", TRUE);
DelayCommand(5.8, DeleteLocalInt(oTarget, "KarsiteSuppressChest"));
}
else if (!GetLocalInt(oTarget, "KarsiteSuppressLeft"))
{
oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
SuppressItem(oBinder, oItem, 1);
SetLocalInt(oTarget, "KarsiteSuppressLeft", TRUE);
DelayCommand(5.8, DeleteLocalInt(oTarget, "KarsiteSuppressLeft"));
}
}
//////////////////////////////////////////////////
/* Void Main and Event Triggers */
//////////////////////////////////////////////////
void main()
{
int nEvent = GetRunningEvent();
if(DEBUG) DoDebug("bnd_events running, event: " + IntToString(nEvent));
// Get the PC. This is event-dependent
object oBinder;
switch(nEvent)
{
case EVENT_ITEM_ONHIT: oBinder = OBJECT_SELF; break;
case EVENT_ONPLAYEREQUIPITEM: oBinder = GetItemLastEquippedBy(); break;
case EVENT_ONPLAYERUNEQUIPITEM: oBinder = GetItemLastUnequippedBy(); break;
case EVENT_ONHEARTBEAT: oBinder = OBJECT_SELF; break;
case EVENT_ONPLAYERREST_FINISHED: oBinder = GetLastBeingRested(); break;
case EVENT_ONACQUIREITEM: oBinder = GetModuleItemAcquiredBy(); break;
default:
oBinder = OBJECT_SELF;
}
object oItem;
object oSkin = GetPCSkin(oBinder);
// We aren't being called from any event, instead from EvalPRCFeats
if(nEvent == FALSE)
{
// Hook in the events
if(DEBUG) DoDebug("bnd_events: Adding eventhooks");
AddEventScript(oBinder, EVENT_ONPLAYEREQUIPITEM, "bnd_events", TRUE, FALSE);
AddEventScript(oBinder, EVENT_ONPLAYERUNEQUIPITEM, "bnd_events", TRUE, FALSE);
AddEventScript(oBinder, EVENT_ONHEARTBEAT, "bnd_events", TRUE, FALSE);
AddEventScript(oBinder, EVENT_ONPLAYERREST_FINISHED, "bnd_events", TRUE, FALSE);
AddEventScript(oBinder, EVENT_ONACQUIREITEM , "bnd_events", TRUE, FALSE);
if (GetHasSpellEffect(VESTIGE_RONOVE, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_RONOVE_FISTS))
{
SetLocalInt(oBinder, CALL_UNARMED_FEATS, TRUE);
SetLocalInt(oBinder, CALL_UNARMED_FISTS, TRUE);
}
}
else if(nEvent == EVENT_ITEM_ONHIT)
{
oItem = GetSpellCastItem();
object oTarget = PRCGetSpellTargetObject();
if(DEBUG) DoDebug("bnd_events: OnHit:\n"
+ "oBinder = " + DebugObject2Str(oBinder) + "\n"
+ "oItem = " + DebugObject2Str(oItem) + "\n"
+ "oTarget = " + DebugObject2Str(oTarget) + "\n"
);
if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
{
if (GetHasSpellEffect(VESTIGE_AYM, oBinder) && GetLevelByClass(CLASS_TYPE_BINDER, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_AYM_HALO_FIRE))
AymHaloOfFire(oBinder, oTarget);
if (GetHasSpellEffect(VESTIGE_EURYNOME, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_EURYNOME_POISON))
EurynomePoisonBlood(oBinder, oTarget);
}
else // This is always a weapon
{
if (GetHasSpellEffect(VESTIGE_VANUS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_VANUS_DISDAIN)) VanusDisdain(oBinder, oTarget);
if (GetHasSpellEffect(VESTIGE_MARCHOSIAS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_MARCHOSIAS_RETRIBUTION)) MarchosiasRetribution(oBinder, oTarget);
}
// Melee weapon checks
if(IPGetIsMeleeWeapon(oItem))
{
if (GetHasSpellEffect(VESTIGE_TENEBROUS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_TENEBROUS_TOUCH_VOID)) TenebrousVoid(oBinder, oTarget);
if (GetHasSpellEffect(VESTIGE_SHAX, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_SHAX_STORM_STRIKE)) ShaxStormStrike(oBinder, oTarget);
if (GetHasSpellEffect(VESTIGE_ELIGOR, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_ELIGOR_STRIKE)) EligorChromatic(oBinder, oTarget);
if (GetRacialType(oBinder) == RACIAL_TYPE_KARSITE) KarsiteOnHit(oBinder, oTarget);
}
}// end if - Running OnHit event
else if(nEvent == EVENT_ONPLAYEREQUIPITEM)
{
oItem = GetItemLastEquipped();
if(DEBUG) DoDebug("bnd_events - OnEquip\n"
+ "oBinder = " + DebugObject2Str(oBinder) + "\n"
+ "oItem = " + DebugObject2Str(oItem) + "\n"
);
if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
{
// Can't get Aym from Bind Vestige feat
if (GetHasSpellEffect(VESTIGE_AYM, oBinder) && GetLevelByClass(CLASS_TYPE_BINDER, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_AYM_HALO_FIRE) ||
(GetHasSpellEffect(VESTIGE_EURYNOME, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_EURYNOME_POISON)) )
{
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
AddEventScript(oItem, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
}
}
// Melee weapon checks
if(IPGetIsMeleeWeapon(oItem))
{
if (GetHasSpellEffect(VESTIGE_AYM, oBinder) && GetLevelByClass(CLASS_TYPE_BINDER, oBinder) && GetBinderLevel(oBinder, VESTIGE_AYM) >= 10 && !GetIsVestigeExploited(oBinder, VESTIGE_AYM_RUINOUS_ATTACK))
{
IPSafeAddItemProperty(oItem, ItemPropertyAttackBonus(5), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
IPSafeAddItemProperty(oItem, ItemPropertyAttackPenalty(5), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
}
if (GetHasSpellEffect(VESTIGE_RONOVE, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_RONOVE_COLD_IRON))
{
int nBonus = 1;
if (GetBinderLevel(oBinder, VESTIGE_RONOVE) >= 7) nBonus = 3;
IPSafeAddItemProperty(oItem, ItemPropertyAttackBonus(nBonus), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
IPSafeAddItemProperty(oItem, ItemPropertyAttackPenalty(nBonus), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
}
if ((GetHasSpellEffect(VESTIGE_VANUS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_VANUS_DISDAIN)) ||
(GetHasSpellEffect(VESTIGE_MARCHOSIAS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_MARCHOSIAS_RETRIBUTION)) ||
(GetRacialType(oBinder) == RACIAL_TYPE_KARSITE))
{
AddEventScript(oItem, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
}
// Any weapon
if (GetIsWeapon(oItem))
{
if (GetLevelByClass(CLASS_TYPE_KNIGHT_SACRED_SEAL, oBinder))
{
IPSafeAddItemProperty(oItem, ItemPropertyAttackBonus(3), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
IPSafeAddItemProperty(oItem, ItemPropertyAttackPenalty(3), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
}
}
if (GetWeaponRanged(oItem))
{
if ((GetHasSpellEffect(VESTIGE_VANUS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_VANUS_DISDAIN)) ||
(GetHasSpellEffect(VESTIGE_MARCHOSIAS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_MARCHOSIAS_RETRIBUTION)) )
{
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
AddEventScript(oItem, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oBinder);
IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
AddEventScript(oAmmo, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS, oBinder);
IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
AddEventScript(oAmmo, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oBinder);
IPSafeAddItemProperty(oAmmo, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
AddEventScript(oAmmo, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
}
}
}
// We are called from the OnPlayerUnEquipItem eventhook. Remove OnHitCast: Unique Power from oBinder's weapon
else if(nEvent == EVENT_ONPLAYERUNEQUIPITEM)
{
oItem = GetItemLastUnequipped();
if(DEBUG) DoDebug("bnd_events - OnUnEquip\n"
+ "oBinder = " + DebugObject2Str(oBinder) + "\n"
+ "oItem = " + DebugObject2Str(oItem) + "\n"
);
if (GetHasSpellEffect(VESTIGE_SAVNOK, oBinder) && !GetLocalInt(oBinder, "PactQuality"+IntToString(VESTIGE_SAVNOK)))
{
SavnokInfluence(oBinder, oItem);
}
// Only applies to armours
if(GetBaseItemType(oItem) == BASE_ITEM_ARMOR)
{
// Remove the temporary OnHitCastSpell: Unique
RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", 1, DURATION_TYPE_TEMPORARY);
}
// Clean up weapons
if(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);
RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "bnd_events", TRUE, FALSE);
RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
object oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oBinder);
RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS, oBinder);
RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oBinder);
RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
}
}
else if(nEvent == EVENT_ONHEARTBEAT)
{
ExpelledVestigeCleanup(oBinder);
if (GetHasSpellEffect(VESTIGE_NABERIUS, oBinder) && GetLevelByClass(CLASS_TYPE_BINDER, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_NABERIUS_ABILITY_HEALING)) NaberiusHeal(oBinder);
if (GetHasSpellEffect(VESTIGE_HAAGENTI, oBinder)) HaagentiTrans(oBinder);
if (GetHasSpellEffect(VESTIGE_PAIMON, oBinder) && GetLevelByClass(CLASS_TYPE_BINDER, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_PAIMON_BLADES))
{
int nType = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oBinder));
if (nType == BASE_ITEM_RAPIER || nType == BASE_ITEM_SHORTSWORD)
IPSafeAddItemProperty(oSkin, ItemPropertyBonusFeat(IP_CONST_FEAT_WEAPON_FINESSE), 5.999, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING);
}
if (GetHasSpellEffect(VESTIGE_ANDRAS, oBinder) && !GetLocalInt(oBinder, "PactQuality"+IntToString(VESTIGE_ANDRAS))) AndrasInfluence(oBinder);
if (GetHasSpellEffect(VESTIGE_TENEBROUS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_TENEBROUS_SEE_DARKNESS)) ActionCastSpellOnSelf(SPELL_DARKVISION);
if (GetHasSpellEffect(VESTIGE_GERYON, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_GERYON_DARKNESS)) ActionCastSpellOnSelf(SPELL_DARKVISION);
if (GetIsPatronVestigeBound(oBinder) && GetLevelByClass(CLASS_TYPE_KNIGHT_SACRED_SEAL, oBinder) >= 5)
{
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectDamageReduction(10, DAMAGE_POWER_PLUS_ONE), oBinder, 6.0);
IPSafeAddItemProperty(oSkin, ItemPropertyBonusFeat(IP_CONST_FEAT_OUTSIDER_RACIAL_TYPE), 5.999, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
}
if (GetHasSpellEffect(VESTIGE_CHUPOCLOPS_ETHEREAL_WATCHER, oBinder)) ChupoclopsEth(oBinder);
if (GetHasSpellEffect(VESTIGE_VANUS, oBinder)) VanusInfluence(oBinder);
if (GetHasSpellEffect(VESTIGE_DESHARIS, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_DESHARIS_CITY_DWELLER)) CityDweller(oBinder);
}
else if(nEvent == EVENT_ONPLAYERREST_FINISHED)
{
if (GetHasFeat(FEAT_RAPID_PACT_MAKING, oBinder)) DeleteLocalInt(oBinder, "RapidPactMaking");
// Naberius's Skills
int i;
for(i = 0; i < 40 ; i++)
DeleteLocalInt(oBinder, "NaberiusSkill"+IntToString(i));
DeleteLocalInt(oBinder, "RonovesFists");
DeleteLocalInt(oBinder, "AndrasMount");
DeleteLocalInt(oBinder, "AmonRam");
DeleteLocalInt(oBinder, "ExploitVestige");
if (GetLevelByClass(CLASS_TYPE_ANIMA_MAGE, oBinder))
{
SetLocalInt(oBinder, "BinderRested", TRUE);
DelayCommand(30.0, DeleteLocalInt(oBinder, "BinderRested"));
}
DeleteLocalInt(oBinder, "PRC_WoLUses" + IntToString(VESTIGE_KARSUS_DISPEL));
DeleteLocalInt(oBinder, "PRC_WoLUses" + IntToString(VESTIGE_TENEBROUS_FLICKER));
DeleteLocalInt(oBinder, "PRC_WoLUses" + IntToString(VESTIGE_DANTALION_TRAVEL_SPELL));
DeleteLocalInt(oBinder, "PRC_WoLUses" + IntToString(VESTIGE_THE_TRIAD_SMITE));
DeleteLocalInt(oBinder, "PRC_WoLUses" + IntToString(19139));
DeleteLocalInt(oBinder, "ZceryllTS");
if (GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oBinder)) ReapplyTenebrous(oBinder);
}
else if(nEvent == EVENT_ONACQUIREITEM)
{
oItem = GetModuleItemAcquired();
if(DEBUG) DoDebug("bnd_events - OnAcquire\n"
+ "oBinder = " + DebugObject2Str(oBinder) + "\n"
+ "oItem = " + DebugObject2Str(oItem) + "\n"
);
if (GetHasSpellEffect(VESTIGE_ANDROMALIUS, oBinder) && !GetLocalInt(oBinder, "PactQuality"+IntToString(VESTIGE_ANDROMALIUS)))
{
if (GetStolenFlag(oItem))
{
FloatingTextStringOnCreature("Andromalius prevents you from taking a stolen item!", oBinder, FALSE);
AssignCommand(oBinder, ActionPutDownItem(oItem));
DelayCommand(2.0, CheckIsDropped(oBinder, oItem));
}
}
if (GetHasSpellEffect(VESTIGE_KARSUS, oBinder) && GetLevelByClass(CLASS_TYPE_BINDER, oBinder) && !GetIsVestigeExploited(oBinder, VESTIGE_KARSUS_WILL))
{
int nType = GetBaseItemType(oItem);
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND || nType == BASE_ITEM_MAGICSTAFF || nType == BASE_ITEM_CRAFTED_STAFF || nType == BASE_ITEM_BLANK_WAND || nType == BASE_ITEM_MAGICROD || nType == BASE_ITEM_CRAFTED_ROD)
{
IPSafeAddItemProperty(oItem, ItemPropertyLimitUseByClass(CLASS_TYPE_BINDER), HoursToSeconds(24), X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
}
}
}
}