296 lines
11 KiB
Plaintext
296 lines
11 KiB
Plaintext
//::///////////////////////////////////////////////
|
|
//:: Spell Hook Include File
|
|
//:: x2_inc_spellhook
|
|
//:: Copyright (c) 2003 Bioware Corp.
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
|
|
This file acts as a hub for all code that
|
|
is hooked into the nwn spellscripts'
|
|
|
|
If you want to implement material components
|
|
into spells or add restrictions to certain
|
|
spells, this is the place to do it.
|
|
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:: Created By: Georg Zoeller
|
|
//:: Created On: 2003-06-04
|
|
//:: Updated On: 2003-10-25
|
|
//:://////////////////////////////////////////////
|
|
//:: Modified By: Deva Winblood
|
|
//:: Modified Date: January 15th-16th, 2008
|
|
//:://////////////////////////////////////////////
|
|
//:: Modified By: Community Patch 1.70, 17.9.2008
|
|
//:: Removed horse library, check for getishorsemounted rescripted by GetPhenoType
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Modified to insure no shapeshifting spells are castable upon
|
|
mounted targets. This prevents problems that can occur due
|
|
to dismounting after shape shifting, or other issues that can
|
|
occur due to preserved appearances getting out of synch.
|
|
|
|
This can additional check can be disabled by setting the variable
|
|
X3_NO_SHAPESHIFT_SPELL_CHECK to 1 on the module object. If this
|
|
variable is set then this script will function as it did prior to
|
|
this modification.
|
|
|
|
*/
|
|
|
|
//#include "x2_inc_itemprop" - Inherited from x2_inc_craft
|
|
#include "x2_inc_craft"
|
|
|
|
|
|
const int X2_EVENT_CONCENTRATION_BROKEN = 12400;
|
|
|
|
|
|
// Use Magic Device Check.
|
|
// Returns TRUE if the Spell is allowed to be cast, either because the
|
|
// character is allowed to cast it or he has won the required UMD check
|
|
// Only active on spell scroll
|
|
int X2UseMagicDeviceCheck();
|
|
|
|
|
|
// This function holds all functions that are supposed to run before the actual
|
|
// spellscript gets run. If this functions returns FALSE, the spell is aborted
|
|
// and the spellscript will not run
|
|
int X2PreSpellCastCode();
|
|
|
|
|
|
// check if the spell is prohibited from being cast on items
|
|
// returns FALSE if the spell was cast on an item but is prevented
|
|
// from being cast there by its corresponding entry in des_crft_spells
|
|
// oItem - pass PRCGetSpellTargetObject in here
|
|
int X2CastOnItemWasAllowed(object oItem);
|
|
|
|
// Sequencer Item Property Handling
|
|
// Returns TRUE (and charges the sequencer item) if the spell
|
|
// ... was cast on an item AND
|
|
// ... the item has the sequencer property
|
|
// ... the spell was non hostile
|
|
// ... the spell was not cast from an item
|
|
// in any other case, FALSE is returned an the normal spellscript will be run
|
|
// oItem - pass PRCGetSpellTargetObject in here
|
|
int X2GetSpellCastOnSequencerItem(object oItem);
|
|
|
|
int X2RunUserDefinedSpellScript();
|
|
|
|
|
|
|
|
int X2UseMagicDeviceCheck()
|
|
{
|
|
int nRet = ExecuteScriptAndReturnInt("x2_pc_umdcheck",OBJECT_SELF);
|
|
return nRet;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// GZ: This is a filter I added to prevent spells from firing their original spell
|
|
// script when they were cast on items and do not have special coding for that
|
|
// case. If you add spells that can be cast on items you need to put them into
|
|
// des_crft_spells.2da
|
|
//------------------------------------------------------------------------------
|
|
int X2CastOnItemWasAllowed(object oItem)
|
|
{
|
|
int bAllow = (Get2DAString(X2_CI_CRAFTING_SP_2DA,"CastOnItems",GetSpellId()) == "1");
|
|
if (!bAllow)
|
|
{
|
|
FloatingTextStrRefOnCreature(83453, OBJECT_SELF); // not cast spell on item
|
|
}
|
|
return bAllow;
|
|
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Execute a user overridden spell script.
|
|
//------------------------------------------------------------------------------
|
|
int X2RunUserDefinedSpellScript()
|
|
{
|
|
// See x2_inc_switches for details on this code
|
|
string sScript = GetModuleOverrideSpellscript();
|
|
if (sScript != "")
|
|
{
|
|
ExecuteScript(sScript,OBJECT_SELF);
|
|
if (GetModuleOverrideSpellScriptFinished() == TRUE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Created Brent Knowles, Georg Zoeller 2003-07-31
|
|
// Returns TRUE (and charges the sequencer item) if the spell
|
|
// ... was cast on an item AND
|
|
// ... the item has the sequencer property
|
|
// ... the spell was non hostile
|
|
// ... the spell was not cast from an item
|
|
// in any other case, FALSE is returned an the normal spellscript will be run
|
|
//------------------------------------------------------------------------------
|
|
int X2GetSpellCastOnSequencerItem(object oItem)
|
|
{
|
|
|
|
if (!GetIsObjectValid(oItem))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
int nMaxSeqSpells = IPGetItemSequencerProperty(oItem); // get number of maximum spells that can be stored
|
|
if (nMaxSeqSpells <1)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (GetIsObjectValid(PRCGetSpellCastItem())) // spell cast from item?
|
|
{
|
|
// we allow scrolls
|
|
int nBt = GetBaseItemType(PRCGetSpellCastItem());
|
|
if ( nBt !=BASE_ITEM_SPELLSCROLL && nBt != 105)
|
|
{
|
|
FloatingTextStrRefOnCreature(83373, OBJECT_SELF);
|
|
return TRUE; // wasted!
|
|
}
|
|
}
|
|
|
|
// Check if the spell is marked as hostile in spells.2da
|
|
int nHostile = StringToInt(Get2DAString("spells","HostileSetting",GetSpellId()));
|
|
if(nHostile ==1)
|
|
{
|
|
FloatingTextStrRefOnCreature(83885,OBJECT_SELF);
|
|
return TRUE; // no hostile spells on sequencers, sorry ya munchkins :)
|
|
}
|
|
|
|
int nNumberOfTriggers = GetLocalInt(oItem, "X2_L_NUMTRIGGERS");
|
|
// is there still space left on the sequencer?
|
|
if (nNumberOfTriggers < nMaxSeqSpells)
|
|
{
|
|
// success visual and store spell-id on item.
|
|
effect eVisual = EffectVisualEffect(VFX_IMP_BREACH);
|
|
nNumberOfTriggers++;
|
|
//NOTE: I add +1 to the SpellId to spell 0 can be used to trap failure
|
|
int nSID = GetSpellId()+1;
|
|
SetLocalInt(oItem, "X2_L_SPELLTRIGGER" + IntToString(nNumberOfTriggers), nSID);
|
|
SetLocalInt(oItem, "X2_L_NUMTRIGGERS", nNumberOfTriggers);
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVisual, OBJECT_SELF);
|
|
FloatingTextStrRefOnCreature(83884, OBJECT_SELF);
|
|
}
|
|
else
|
|
{
|
|
FloatingTextStrRefOnCreature(83859,OBJECT_SELF);
|
|
}
|
|
|
|
return TRUE; // in any case, spell is used up from here, so do not fire regular spellscript
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// * This is our little concentration system for black blade of disaster
|
|
// * if the mage tries to cast any kind of spell, the blade is signaled an event to die
|
|
//------------------------------------------------------------------------------
|
|
void X2BreakConcentrationSpells()
|
|
{
|
|
// * At the moment we got only one concentration spell, black blade of disaster
|
|
|
|
object oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED);
|
|
if (GetIsObjectValid(oAssoc) && GetIsPC(OBJECT_SELF)) // only applies to PCS
|
|
{
|
|
if(GetTag(oAssoc) == "x2_s_bblade") // black blade of disaster
|
|
{
|
|
if (GetLocalInt(OBJECT_SELF,"X2_L_CREATURE_NEEDS_CONCENTRATION"))
|
|
{
|
|
SignalEvent(oAssoc,EventUserDefined(X2_EVENT_CONCENTRATION_BROKEN));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// being hit by any kind of negative effect affecting the caster's ability to concentrate
|
|
// will cause a break condition for concentration spells
|
|
//------------------------------------------------------------------------------
|
|
int X2GetBreakConcentrationCondition(object oPlayer)
|
|
{
|
|
effect e1 = GetFirstEffect(oPlayer);
|
|
int nType;
|
|
int bRet = FALSE;
|
|
while (GetIsEffectValid(e1) && !bRet)
|
|
{
|
|
nType = GetEffectType(e1);
|
|
|
|
if (nType == EFFECT_TYPE_STUNNED || nType == EFFECT_TYPE_PARALYZE ||
|
|
nType == EFFECT_TYPE_SLEEP || nType == EFFECT_TYPE_FRIGHTENED ||
|
|
nType == EFFECT_TYPE_PETRIFY || nType == EFFECT_TYPE_CONFUSED ||
|
|
nType == EFFECT_TYPE_DOMINATED || nType == EFFECT_TYPE_POLYMORPH)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
e1 = GetNextEffect(oPlayer);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
void X2DoBreakConcentrationCheck()
|
|
{
|
|
object oMaster = GetMaster();
|
|
if (GetLocalInt(OBJECT_SELF,"X2_L_CREATURE_NEEDS_CONCENTRATION"))
|
|
{
|
|
if (GetIsObjectValid(oMaster))
|
|
{
|
|
// master doing anything that requires attention and breaks concentration
|
|
switch(GetCurrentAction(oMaster))
|
|
{
|
|
case ACTION_DISABLETRAP:
|
|
case ACTION_TAUNT:
|
|
case ACTION_PICKPOCKET:
|
|
case ACTION_ATTACKOBJECT:
|
|
case ACTION_COUNTERSPELL:
|
|
case ACTION_FLAGTRAP:
|
|
case ACTION_CASTSPELL:
|
|
case ACTION_ITEMCASTSPELL:
|
|
case ACTION_EXAMINETRAP: //added in 1.70
|
|
case ACTION_LOCK: //added in 1.70
|
|
case ACTION_OPENLOCK: //added in 1.70
|
|
case ACTION_RECOVERTRAP: //added in 1.70
|
|
case ACTION_SETTRAP: //added in 1.70
|
|
SignalEvent(OBJECT_SELF,EventUserDefined(X2_EVENT_CONCENTRATION_BROKEN));
|
|
return;
|
|
}
|
|
if (X2GetBreakConcentrationCondition(oMaster))
|
|
{
|
|
SignalEvent(OBJECT_SELF,EventUserDefined(X2_EVENT_CONCENTRATION_BROKEN));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// This function will return TRUE if the spell that is cast is a shape shifting
|
|
// spell.
|
|
//------------------------------------------------------------------------------
|
|
int X3ShapeShiftSpell(object oTarget)
|
|
{ // PURPOSE: Return TRUE if a shape shifting spell was cast at oTarget
|
|
int nSpellID=GetSpellId();
|
|
string sUp=GetStringUpperCase(Get2DAString("x3restrict","SHAPESHIFT", nSpellID));
|
|
if (sUp=="YES") return TRUE;
|
|
return FALSE;
|
|
} // X3ShapeShiftSpell()
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Community Patch 1.71: function changed in order to allow modify internal spellhook
|
|
// need to recompile all spellscripts. New internal spellhook is in 70_spelllhook script
|
|
// this library is however still used as include file for new spellhook internal and many
|
|
// old spellscripts
|
|
//------------------------------------------------------------------------------
|
|
int X2PreSpellCastCode()
|
|
{
|
|
DeleteLocalInt(OBJECT_SELF,"X2_L_LAST_RETVAR");
|
|
ExecuteScript("70_spellhook",OBJECT_SELF);
|
|
int nRet = GetLocalInt(OBJECT_SELF,"X2_L_LAST_RETVAR");
|
|
DeleteLocalInt(OBJECT_SELF,"X2_L_LAST_RETVAR");
|
|
return !nRet;
|
|
}
|
|
|