forked from Jaysyn/PRC8
Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
180 lines
8.5 KiB
Plaintext
180 lines
8.5 KiB
Plaintext
#include "prc_inc_combat"
|
|
|
|
void ResonanceHit(object oTarget) // Called when hitting a target
|
|
{
|
|
int nHits = GetLocalInt(oTarget, "ResonanceHits"); // Check hits
|
|
SetLocalInt(oTarget, "ResonanceHits", nHits+1); // Store the hits
|
|
}
|
|
|
|
void ResonanceAdd(object oPC, object oTarget) // Called on heartbeat to add resonance to a target
|
|
{
|
|
int nClass = GetLevelByClass(CLASS_TYPE_SERENE_GUARDIAN, oPC);
|
|
int nRes = GetLocalInt(oTarget, "Resonance");
|
|
int nHits = GetLocalInt(oTarget, "ResonanceHits"); // Check hits
|
|
|
|
// Get 2 resonance if you're level 5+ and hit 3 times in a round
|
|
if (nHits > 2 && nClass > 4)
|
|
SetLocalInt(oTarget, "Resonance", nRes+2);
|
|
else if (nHits > 1) //Otherwise, normal resonance gain
|
|
SetLocalInt(oTarget, "Resonance", nRes+1);
|
|
|
|
FloatingTextStringOnCreature(GetName(oTarget)+" has "+IntToString(GetLocalInt(oTarget, "Resonance"))+ " resonance", oPC, FALSE);
|
|
}
|
|
|
|
void ResonanceCheck(object oPC)
|
|
{
|
|
location lLoc = GetLocation(oPC);
|
|
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(100.0), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
|
|
|
while(GetIsObjectValid(oTarget))
|
|
{
|
|
if (GetLocalInt(oTarget, "ResonanceHits") > 0) // Make sure they were hit
|
|
{
|
|
ResonanceAdd(oPC, oTarget);
|
|
DeleteLocalInt(oTarget, "ResonanceHits"); // Clean up
|
|
}
|
|
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(100.0), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
|
}
|
|
}
|
|
|
|
void main()
|
|
{
|
|
int nEvent = GetRunningEvent();
|
|
if(DEBUG) DoDebug("prc_sereneguard running, event: " + IntToString(nEvent));
|
|
|
|
// Get the PC. This is event-dependent
|
|
object oPC;
|
|
switch(nEvent)
|
|
{
|
|
case EVENT_ITEM_ONHIT: oPC = OBJECT_SELF; break;
|
|
case EVENT_ONPLAYEREQUIPITEM: oPC = GetItemLastEquippedBy(); break;
|
|
case EVENT_ONPLAYERUNEQUIPITEM: oPC = GetItemLastUnequippedBy(); break;
|
|
case EVENT_ONHEARTBEAT: oPC = OBJECT_SELF; break;
|
|
|
|
default:
|
|
oPC = OBJECT_SELF;
|
|
}
|
|
|
|
object oSkin = GetPCSkin(oPC);
|
|
object oItem;
|
|
object oAmmo;
|
|
int nClass = GetLevelByClass(CLASS_TYPE_SERENE_GUARDIAN, oPC);
|
|
|
|
// We aren't being called from any event, instead from EvalPRCFeats
|
|
if(nEvent == FALSE)
|
|
{
|
|
if(nClass >= 7) IPSafeAddItemProperty(oSkin, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_FEAR), 99999.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
|
|
// Hook in the events, needed from level 1 for Resonance
|
|
if(DEBUG) DoDebug("prc_sereneguard: Adding eventhooks");
|
|
AddEventScript(oPC, EVENT_ONPLAYEREQUIPITEM, "prc_sereneguard", TRUE, FALSE);
|
|
AddEventScript(oPC, EVENT_ONPLAYERUNEQUIPITEM, "prc_sereneguard", TRUE, FALSE);
|
|
AddEventScript(oPC, EVENT_ONHEARTBEAT, "prc_sereneguard", TRUE, FALSE);
|
|
}
|
|
// We're being called from the OnHit eventhook, so add resonance
|
|
else if(nEvent == EVENT_ITEM_ONHIT)
|
|
{
|
|
oItem = GetSpellCastItem();
|
|
object oTarget = PRCGetSpellTargetObject();
|
|
if(DEBUG) DoDebug("prc_sereneguard: OnHit:\n"
|
|
+ "oPC = " + DebugObject2Str(oPC) + "\n"
|
|
+ "oItem = " + DebugObject2Str(oItem) + "\n"
|
|
+ "oTarget = " + DebugObject2Str(oTarget) + "\n"
|
|
);
|
|
|
|
// Only applies to weapons
|
|
if(( GetWeaponRanged(oItem) || IPGetIsProjectile(oItem) || IPGetIsMeleeWeapon(oItem)) ) // oItem is the ammo in the case of bows and crossbows
|
|
{
|
|
ResonanceHit(oTarget); //Count the hits
|
|
}// end if - Item is a weapon
|
|
}// end if - Running OnHit event
|
|
// We are called from the OnPlayerEquipItem eventhook. Add OnHitCast: Unique Power to oPC's weapon
|
|
else if(nEvent == EVENT_ONPLAYEREQUIPITEM)
|
|
{
|
|
oPC = GetItemLastEquippedBy();
|
|
oItem = GetItemLastEquipped();
|
|
if(DEBUG) DoDebug("prc_sereneguard - OnEquip\n"
|
|
+ "oPC = " + DebugObject2Str(oPC) + "\n"
|
|
+ "oItem = " + DebugObject2Str(oItem) + "\n"
|
|
);
|
|
|
|
// Only applies to weapons
|
|
// IPGetIsMeleeWeapon is bugged and returns true on items it should not
|
|
if(oItem == GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC) ||
|
|
(oItem == GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oPC) && !GetIsShield(oItem)) ||
|
|
GetWeaponRanged(oItem))
|
|
{
|
|
|
|
if (DEBUG)
|
|
{
|
|
if (IPGetIsMeleeWeapon(oItem)) DoDebug("IPGetIsMeleeWeapon: TRUE");
|
|
if (GetWeaponRanged(oItem)) DoDebug("GetWeaponRanged: TRUE");
|
|
}
|
|
|
|
if (GetWeaponRanged(oItem))
|
|
{
|
|
// Add eventhook to the ranged weapons like darts
|
|
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, "prc_sereneguard", TRUE, FALSE);
|
|
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC);
|
|
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, "prc_sereneguard", TRUE, FALSE);
|
|
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC);
|
|
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, "prc_sereneguard", TRUE, FALSE);
|
|
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC);
|
|
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, "prc_sereneguard", TRUE, FALSE);
|
|
|
|
}
|
|
else if (IPGetIsMeleeWeapon(oItem))
|
|
{
|
|
// Add eventhook to the item
|
|
AddEventScript(oItem, EVENT_ITEM_ONHIT, "prc_sereneguard", TRUE, FALSE);
|
|
|
|
// Add the OnHitCastSpell: Unique needed to trigger the event
|
|
// Makes sure to get ammo if its a ranged weapon
|
|
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 99999.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
|
|
}
|
|
|
|
}
|
|
}
|
|
// We are called from the OnPlayerUnEquipItem eventhook. Remove OnHitCast: Unique Power from oPC's weapon
|
|
else if(nEvent == EVENT_ONPLAYERUNEQUIPITEM)
|
|
{
|
|
oPC = GetItemLastUnequippedBy();
|
|
oItem = GetItemLastUnequipped();
|
|
if(DEBUG) DoDebug("prc_sereneguard - OnUnEquip\n"
|
|
+ "oPC = " + DebugObject2Str(oPC) + "\n"
|
|
+ "oItem = " + DebugObject2Str(oItem) + "\n"
|
|
);
|
|
|
|
// Only applies to weapons
|
|
if(IPGetIsMeleeWeapon(oItem) || GetWeaponRanged(oItem))
|
|
{
|
|
// Add eventhook to the item
|
|
RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "prc_sereneguard", TRUE, FALSE);
|
|
|
|
// Remove the temporary OnHitCastSpell: Unique
|
|
// Makes sure to get ammo if its a ranged weapon
|
|
RemoveSpecificProperty(oItem, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
|
|
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_BOLTS, oPC);
|
|
RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
|
|
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_BULLETS, oPC);
|
|
RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
|
|
|
|
oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oPC);
|
|
RemoveSpecificProperty(oAmmo, ITEM_PROPERTY_ONHITCASTSPELL, IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 0, 1, "", -1, DURATION_TYPE_TEMPORARY);
|
|
}
|
|
}
|
|
// This is used to run the actual loop to apply resonance
|
|
else if(nEvent == EVENT_ONHEARTBEAT)
|
|
{
|
|
ResonanceCheck(oPC);
|
|
}
|
|
}
|