PRC8/nwn/nwnprc/trunk/include/prc_sp_func.nss
Jaysyn904 6ec137a24e Updated AMS marker feats
Updated AMS marker feats.  Removed arcane & divine marker feats.  Updated Dread Necromancer for epic progression. Updated weapon baseitem models.  Updated new weapons for crafting & npc equip.
 Updated prefix.  Updated release archive.
2024-02-11 14:01:05 -05:00

342 lines
14 KiB
Plaintext

/*
prc_sp_func
Additional spell functions for holding the
charge (also works for psionics)
By: Flaming_Sword
Created: January 31, 2006 *complete rewrite
Modified: May 27, 2006
From Player's Handbook 3.5ed p141:
Holding the Charge: If you don't discharge the
spell in the round when you cast the sepll,
you can hold the discharge of the spell
(hold the charge) indefinitely. You can
continue to make touch attacks round after
round. You can touch one friend as a standard
action or up to six friends as a full-round
action. If you touch anything or anyone while
holding a charge, even unintentionally, the
spell discharges. If you cast another spell,
the touch spell dissipates. Alternatively, you
may make a normal unarmed attack (or an attack
with a natural weapon) while holding a charge.
In this case you aren't considered armed and you
provoke attacks of opportunity as normal for
the attack. (If your unarmed attacks or natural
weapon attack doesn't provoke attacks of
opportunity, neither dies this attack. If the
attack hits, you deal normal damage for your
unarmed attack or natural weapon and the spell
discharges. If the attack misses, you are still
holding the charge.
Conclusion:
Holy crap! Charges stay if your touch attacks miss!
*/
// need declaration for this here
int IsTouchSpell(int nSpellID);
void CleanSpellVariables(object oPC);
void SetLocalSpellVariables(object oCaster, int nCharges = 1, int nSpellIDOverride = -1);
void DecrementSpellCharges(object oPC);
void RunSpellScript(object oPC, int nSpellID, int nEventType);
void RunImpactScript(object oPC, int nSpellID, int nEventType);
int IsCure(int nSpellID);
int IsMassCure(int nSpellID);
int IsMassInflict(int nSpellID);
int IsHeal(int nSpellID);
int IsMassHealHarm(int nSpellID);
int CheckRemoveEffects(int nSpellID, int nEffectType);
int IsRaySpell(int nSpell);
//constant declarations in case they change
const string PRC_SPELL_CHARGE_COUNT = "PRC_SPELL_CHARGE_COUNT";
const string PRC_SPELL_CHARGE_SPELLID = "PRC_SPELL_CHARGE_SPELLID";
const string PRC_SPELL_CHARGE_LEVEL = "PRC_SPELL_CHARGE_LEVEL";
const string PRC_SPELL_CONC_TARGET = "PRC_SPELL_CONC_TARGET";
const string PRC_SPELL_METAMAGIC = "PRC_SPELL_METAMAGIC";
const string PRC_POWER_HOLD_MANIFESTATION = "PRC_POWER_HOLD_MANIFESTATION";
const string PRC_SPELL_EVENT = "PRC_SPELL_EVENT";
const string PRC_SPELL_HOLD = "PRC_SPELL_HOLD";
const int PRC_SPELL_EVENT_NONE = 0;
const int PRC_SPELL_EVENT_ATTACK = 1;
const int PRC_SPELL_EVENT_CONCENTRATION = 2;
const int FEAT_SPELLS_TOUCH_ATTACK = 4092;
const int FEAT_SPELLS_RANGED_ATTACK = 4093;
const int FEAT_SPELLS_CONCENTRATION_TARGET = 4094;
const int FEAT_SPELLS_HOLD_CHARGE_TOGGLE = 4095;
const int SPELLS_SPELLS_TOUCH_ATTACK = 3042;
const int SPELLS_SPELLS_RANGED_ATTACK = 3043;
const int SPELLS_SPELLS_CONCENTRATION_TARGET = 3044;
const int SPELLS_SPELLS_HOLD_CHARGE_TOGGLE = 3045;
#include "prc_alterations"
#include "prc_inc_unarmed"
//#include "psi_inc_manifest"
//#include "spinc_common"
//#include "prc_spell_const"
//#include "prc_inc_combat"
//Deletes local variables used for spell functions
// To be called (or copied) on rest, from spellhook
void CleanSpellVariables(object oPC)
{
DeleteLocalInt(oPC, PRC_SPELL_CHARGE_COUNT);
DeleteLocalInt(oPC, PRC_SPELL_CHARGE_SPELLID);
DeleteLocalInt(oPC, PRC_SPELL_CHARGE_LEVEL);
DeleteLocalObject(oPC, PRC_SPELL_CONC_TARGET);
DeleteLocalInt(oPC, PRC_SPELL_HOLD);
DeleteLocalInt(oPC, PRC_SPELL_METAMAGIC);
DeleteLocalManifestation(oPC, PRC_POWER_HOLD_MANIFESTATION);
DeleteLocalMystery(oPC, "MYST_HOLD_MYST");
}
//Returns whether a spell is a touch spell
// nSpellID, the spell id (row in spells.2da) of the spell
int IsTouchSpell(int nSpellID)
{
return (Get2DACache("spells", "Range", nSpellID) == "T");
}
//Sets local variables for the new spell functions
// object oCaster, the caster of the spell
// int nCharges, the number of charges for a spell
// int nSpellIDOverride, for overriding a SpellID
void SetLocalSpellVariables(object oCaster, int nCharges = 1, int nSpellIDOverride = -1)
{
int nTemp = (nSpellIDOverride == -1) ? PRCGetSpellId() : nSpellIDOverride;
SetLocalInt(oCaster, PRC_SPELL_CHARGE_SPELLID, nTemp);
SetLocalInt(oCaster, PRC_SPELL_CHARGE_COUNT, nCharges);
SetLocalInt(oCaster, PRC_SPELL_CHARGE_LEVEL, PRCGetCasterLevel(oCaster));
SetLocalInt(oCaster, PRC_SPELL_METAMAGIC, PRCGetMetaMagicFeat());
FloatingTextStringOnCreature("*Holding the Charge*", oCaster);
object oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCaster);
if (GetIsPRCCreatureWeapon(oItem)) {
RemoveEventScript(oItem, EVENT_ITEM_ONHIT, "prc_sp_event", TRUE, FALSE);
// Add eventhook to the item
AddEventScript(oItem, EVENT_ITEM_ONHIT, "prc_sp_event", TRUE, FALSE);
// Add the OnHitCastSpell: Unique needed to trigger the event
IPSafeAddItemProperty(oItem, ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1), 91234.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
}
//Decrements the number of spell charges
// object oPC, the subject losing a charge
void DecrementSpellCharges(object oPC)
{
int nCharges= GetLocalInt(oPC, PRC_SPELL_CHARGE_COUNT);
SetLocalInt(oPC, PRC_SPELL_CHARGE_COUNT, nCharges - 1);
FloatingTextStringOnCreature("Charges Remaining: " + IntToString(nCharges - 1), oPC);
}
//Called from scripts, will run a spell script with local int for flags
// NOTE: Flags must be interpreted by the spell script
// This lets spell scripts handle events the way they want
//
// object oPC, the subject running the script
// int nSpellID, the spellid of the spell to run
// int nEventType, an integer containing flags defining events to use
void RunSpellScript(object oPC, int nSpellID, int nEventType)
{
ClearAllActions(); //clears queue to prevent exploits
SetLocalInt(oPC, PRC_SPELL_EVENT, nEventType);
ActionCastSpell(nSpellID, 0, 0, 0, GetLocalInt(oPC, PRC_SPELL_METAMAGIC));
DelayCommand(3.0, DeleteLocalInt(oPC, PRC_SPELL_EVENT));
}
//Called from scripts, will run a spell script with local int for flags
// NOTE: This directly executes the impactscript of the spell, which mean
// the spellid of any effect that get applied will be wrong.
// Only use this when you are sure no effect will be apllied,
// or if you really need to bypass the action queue.
void RunImpactScript(object oPC, int nSpellID, int nEventType)
{
// we dont want to be running a 'fake' spellscript, as that will
// use ActionCastSpell, which is exactly what we are trying to avoid
int nRealSpell = GetPowerFromSpellID(nSpellID);
if (nRealSpell == -1)
nRealSpell = nSpellID;
SetLocalInt(oPC, PRC_SPELL_EVENT, nEventType);
SetLocalInt(oPC, PRC_SPELLID_OVERRIDE, nRealSpell);
string sScript = Get2DACache("spells", "ImpactScript", nRealSpell);
ExecuteScript(sScript, oPC);
DeleteLocalInt(oPC, PRC_SPELL_EVENT);
DeleteLocalInt(oPC, PRC_SPELLID_OVERRIDE);
}
//Returns true if the spell is one of the cure spells
int IsCure(int nSpellID)
{
return ((nSpellID >= SPELL_CURE_CRITICAL_WOUNDS) && (nSpellID <= SPELL_CURE_SERIOUS_WOUNDS));
}
//Returns true if the spell is one of the mass cure spells
int IsMassCure(int nSpellID)
{
return ((nSpellID >= SPELL_MASS_CURE_LIGHT) && (nSpellID <= SPELL_MASS_CURE_CRITICAL));
}
//Returns true if the spell is one of the mass inflict spells
int IsMassInflict(int nSpellID)
{
return ((nSpellID >= SPELL_MASS_INFLICT_LIGHT) && (nSpellID <= SPELL_MASS_INFLICT_CRITICAL));
}
//Returns true for the spell Heal
int IsHeal(int nSpellID)
{
return nSpellID == SPELL_HEAL
|| nSpellID == SPELL_MASS_HEAL;
}
//Returns true for the Mass Heal spell (Mass Harm if it ever gets made)
int IsMassHealHarm(int nSpellID)
{
return nSpellID == SPELL_MASS_HEAL
|| nSpellID == SPELL_MASS_HARM;
}
//Returns whether an effect should be removed
int CheckRemoveEffects(int nSpellID, int nEffectType)
{
switch(nSpellID)
{
case SPELL_GREATER_RESTORATION:
{
return(nEffectType == EFFECT_TYPE_ABILITY_DECREASE ||
nEffectType == EFFECT_TYPE_AC_DECREASE ||
nEffectType == EFFECT_TYPE_ATTACK_DECREASE ||
nEffectType == EFFECT_TYPE_DAMAGE_DECREASE ||
nEffectType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||
nEffectType == EFFECT_TYPE_SAVING_THROW_DECREASE ||
nEffectType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||
nEffectType == EFFECT_TYPE_SKILL_DECREASE ||
nEffectType == EFFECT_TYPE_BLINDNESS ||
nEffectType == EFFECT_TYPE_DEAF ||
nEffectType == EFFECT_TYPE_CURSE ||
nEffectType == EFFECT_TYPE_DISEASE ||
nEffectType == EFFECT_TYPE_POISON ||
nEffectType == EFFECT_TYPE_PARALYZE ||
nEffectType == EFFECT_TYPE_CHARMED ||
nEffectType == EFFECT_TYPE_DOMINATED ||
nEffectType == EFFECT_TYPE_DAZED ||
nEffectType == EFFECT_TYPE_CONFUSED ||
nEffectType == EFFECT_TYPE_FRIGHTENED ||
nEffectType == EFFECT_TYPE_NEGATIVELEVEL ||
nEffectType == EFFECT_TYPE_SLOW ||
nEffectType == EFFECT_TYPE_STUNNED);
}
case SPELL_RESTORATION:
{
return(nEffectType == EFFECT_TYPE_ABILITY_DECREASE ||
nEffectType == EFFECT_TYPE_AC_DECREASE ||
nEffectType == EFFECT_TYPE_ATTACK_DECREASE ||
nEffectType == EFFECT_TYPE_DAMAGE_DECREASE ||
nEffectType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||
nEffectType == EFFECT_TYPE_SAVING_THROW_DECREASE ||
nEffectType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||
nEffectType == EFFECT_TYPE_SKILL_DECREASE ||
nEffectType == EFFECT_TYPE_BLINDNESS ||
nEffectType == EFFECT_TYPE_DEAF ||
nEffectType == EFFECT_TYPE_PARALYZE ||
nEffectType == EFFECT_TYPE_NEGATIVELEVEL);
break;
}
case SPELL_LESSER_RESTORATION:
{
return(nEffectType == EFFECT_TYPE_ABILITY_DECREASE ||
nEffectType == EFFECT_TYPE_AC_DECREASE ||
nEffectType == EFFECT_TYPE_ATTACK_DECREASE ||
nEffectType == EFFECT_TYPE_DAMAGE_DECREASE ||
nEffectType == EFFECT_TYPE_DAMAGE_IMMUNITY_DECREASE ||
nEffectType == EFFECT_TYPE_SAVING_THROW_DECREASE ||
nEffectType == EFFECT_TYPE_SPELL_RESISTANCE_DECREASE ||
nEffectType == EFFECT_TYPE_SKILL_DECREASE);
break;
}
case SPELL_REMOVE_BLINDNESS_AND_DEAFNESS:
{
return nEffectType == EFFECT_TYPE_BLINDNESS
|| nEffectType == EFFECT_TYPE_DEAF;
}
case SPELL_REMOVE_CURSE:
{
return nEffectType == EFFECT_TYPE_CURSE;
}
case SPELL_CALM_EMOTIONS:
{
return nEffectType == EFFECT_TYPE_FRIGHTENED
|| nEffectType == EFFECT_TYPE_CONFUSED;
}
case SPELLABILITY_REMOVE_DISEASE:
case SPELL_REMOVE_DISEASE:
{
return (nEffectType == EFFECT_TYPE_DISEASE ||
(GetPRCSwitch(PRC_BIOWARE_REMOVE_DISEASE) &&
nEffectType == EFFECT_TYPE_ABILITY_DECREASE));
}
case SPELL_NEUTRALIZE_POISON:
{
return (nEffectType == EFFECT_TYPE_POISON ||
nEffectType == EFFECT_TYPE_DISEASE ||
(GetPRCSwitch(PRC_BIOWARE_NEUTRALIZE_POISON) &&
nEffectType == EFFECT_TYPE_ABILITY_DECREASE));
}
case SPELL_PANACEA:
{
return (EFFECT_TYPE_BLINDNESS == nEffectType ||
EFFECT_TYPE_CONFUSED == nEffectType ||
EFFECT_TYPE_DAZED == nEffectType ||
EFFECT_TYPE_DEAF == nEffectType ||
EFFECT_TYPE_DISEASE == nEffectType ||
EFFECT_TYPE_FRIGHTENED == nEffectType ||
EFFECT_TYPE_PARALYZE == nEffectType ||
EFFECT_TYPE_POISON == nEffectType ||
EFFECT_TYPE_SLEEP == nEffectType ||
EFFECT_TYPE_STUNNED == nEffectType);
}
}
return FALSE;
}
int IsRaySpell(int nSpell)
{
int nRealSpell = GetPowerFromSpellID(nSpell);
if (nRealSpell != -1)
nSpell = nRealSpell;
return nSpell == SPELL_AVASCULAR_MASS // avascular mass
|| nSpell == SPELL_AVASCULATE // avasculate
|| nSpell == SPELL_DIMENSIONAL_ANCHOR // dimensional anchor
|| nSpell == SPELL_DISINTEGRATE // disintegrate
|| nSpell == SPELL_POLAR_RAY // polar ray
|| nSpell == SPELL_SLASHING_DARKNESS // slashing darkness
|| nSpell == SPELL_RAY_OF_FROST // ray of frost
|| nSpell == SPELL_ENERGY_DRAIN // energy drain
|| nSpell == SPELL_ENERVATION // enervate
|| nSpell == SPELL_RAY_OF_ENFEEBLEMENT // ray of enfeeblement
|| nSpell == SPELL_NEGATIVE_ENERGY_RAY // negative energy ray
|| nSpell == SPELL_SEARING_LIGHT // searing light
|| nSpell == SPELL_SEEKING_RAY // seeking ray
|| nSpell == SPELL_SCORCHING_RAY // scorching ray
|| nSpell == SPELL_PRISMATIC_RAY // prismatic ray
|| nSpell == SPELL_ELECTRIC_JOLT // Electric Jolt
// || nSpell == 0) //
;
}