mirror of
http://prc.nwn.ee:3000/Jaysyn/PRC8.git
synced 2025-12-17 00:07:15 -05:00
Initial upload.
Adding base PRC 4.19a files to repository.
This commit is contained in:
622
trunk/users/Stratovarius/NWNEE Updates/PRC_S_spellb.nss
Normal file
622
trunk/users/Stratovarius/NWNEE Updates/PRC_S_spellb.nss
Normal file
@@ -0,0 +1,622 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: PRC New Spellbooks use conversation
|
||||
//:: prc_s_spellb
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
@todo Primo: Could you write a blurb on what
|
||||
this does and TLKify it?
|
||||
|
||||
|
||||
@author Primogenitor
|
||||
@date Created - yyyy.mm.dd
|
||||
|
||||
last changed by motu99, April 29, 2008:
|
||||
|
||||
Conversation script for setting up spells to be memorized by prepared casters
|
||||
|
||||
This conversation script sets up a persistent array of the spells to be memorized
|
||||
(at the end of the next rest) for any newspellbook prepared caster class.
|
||||
|
||||
It uses the persistent array name prefix "Spellbook", then appends the spell level
|
||||
(converted to a string) to the prefix and lastly appends the class-nr (converted to a string)
|
||||
|
||||
The thus appended prefix is a persistent array name, in which the nSpellbookIDs of the
|
||||
spells to be memorized at the end of the next rest are stored
|
||||
|
||||
the conversation is called by activating the prc_spellbook feat (#1999 in feats.2da)
|
||||
which fires the spellscript prc_spellbook (#1792 in spells.2da), which then calls this
|
||||
conversation script
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
|
||||
// persistant storage format on hide
|
||||
/**
|
||||
MEMORIZED SPELLS FOR PREP CASTERS:
|
||||
All spell levels are all stored in one single array (motu99: very unfortunate, should be changed):
|
||||
sArrayName = "NewSpellbookMem_"+IntToString(nClass)
|
||||
The array is indexed by the spellbookID; the value is the number of spells with that spellbookID still in memory:
|
||||
nNrOfSpellsStillInMemory = sArrayName[nSpellbookID]
|
||||
|
||||
SPELLS TO BE MEMORIZED BY PREP CASTERS
|
||||
They are stored in up to ten arrays, one array for each spell level (or rather spell slot level)
|
||||
sArrayName = "Spellbook"+IntToString(nSpellLevel)+"_"+IntToString(nClass)
|
||||
The array is indexed by the slot number, starting at #0; the value contains the nSpelllbookID of the spell to be memorized
|
||||
nSpellbookID = sArrayName[nSlotNr]
|
||||
|
||||
SPELLS MEMORIZED BY PREP CASTERS - INDEX
|
||||
Array created from "spells to be memorized" in OnRest event. Only unique spellids are stored.
|
||||
sArrayName = "SpellbookIDX"+IntToString(nSpellLevel)+"_"+IntToString(nClass)
|
||||
Serves as "NewSpellbookMem_" index for fast search and delete - allows looping only through memorized SpellbookIDs
|
||||
(archivist - max 56 + bonus slots from high WIS) instead of all SpellbookIDs (archivist - 2400+)
|
||||
Should help reduce instruction count sagnificantly.
|
||||
|
||||
SPELLS KNOWN BY PREP CASTERS:
|
||||
so far prep NSB casters know all spells in their class spellbook; they need not learn spells
|
||||
motu99: This might change, if for instance wizards use the NSB system to gain higher spell slot levels (10+)
|
||||
//for archivist:
|
||||
They are stored in up to ten arrays, one array for each spell level (or rather spell slot level)
|
||||
sArrayName = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(nSpellLevel)
|
||||
|
||||
SPELLS KNOWN BY SPONT CASTERS:
|
||||
The spells known are stored in one single array (the array contains only the non-metamagic versions and only master spells)
|
||||
sArrayName = "Spellbook" + IntToString(nClass);
|
||||
The array is indexed by a counter (the i-th spell learned); the value contains the nSpellbookID of the (non-metamagic master) spell known
|
||||
nSpellbookID = sArrayName[i]
|
||||
|
||||
AVAILABLE SPELL SLOTS FOR SPONT CASTERS:
|
||||
The nr of still available spell slots for a prep caster are all stored in one single array
|
||||
sArrayName = "NewSpellbookMem_" + IntToString(nClass)
|
||||
The array is indexed by the spell (slot) level, the value contains the nr of still available slots at that spell (slot) level
|
||||
nNrOfSpellSlotsAvailable = sArrayName[nSpellSlotLevel]
|
||||
*/
|
||||
|
||||
// spells in the class spellbook of nClass (a spont caster generally will not know all of these spells)
|
||||
/**
|
||||
SPELLS IN THE CLASS SPELLBOOK OF PREP OR SPONT CASTERS:
|
||||
The spells that are potentially learnable by nClass are stored on the prc cache object in up to 10 different tokens.
|
||||
The class spell book ONLY stores the masterspells and ONLY the non-metamagicked version!
|
||||
|
||||
There is one storage token for every spell level (and class); it has the tag name:
|
||||
sTag = "SpellLvl_"+IntToString(nClass)+"_Level_"+IntToString(nSpellLevel);
|
||||
The spells are stored on the token object oToken (defined by the unique sTag) in an array with name sArrayName
|
||||
oToken = GetObjectByTag(sTag)
|
||||
sArrayName = "Lkup"
|
||||
The array is indexed by a counter (the i-th spell of a given level in the class spellbook); the value is the spellbookID
|
||||
nSpellbookID = sArrayName[i]
|
||||
*/
|
||||
|
||||
#include "x2_inc_spellhook"
|
||||
#include "inc_dynconv"
|
||||
#include "inc_sp_gain_mem"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Constant defintions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const int STAGE_SELECT_CLASS = 0;
|
||||
const int STAGE_SELECT_SPELL_LEVEL = 1;
|
||||
const int STAGE_SELECT_SPELL_SLOT = 2;
|
||||
const int STAGE_SELECT_METAMAGIC = 3;
|
||||
const int STAGE_SELECT_SPELL = 4;
|
||||
|
||||
const int CHOICE_RETURN_TO_PREVIOUS = 0xEFFFFFFF;
|
||||
|
||||
|
||||
const string CONV_SPELLB_CLASS = "SpellClass";
|
||||
const string CONV_SPELLB_LEVEL = "SpellLevel";
|
||||
const string CONV_SPELLB_META = "MetaMagic";
|
||||
const string CONV_SPELLB_SLOT = "SpellSlot";
|
||||
|
||||
const int DYNCONV_NEXT_STAGE = -4;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Aid functions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const string SPELLS_MEMORIZED_CACHE = "SMCCCache";
|
||||
|
||||
void DeleteSpellsMemorizedCache(object oPC)
|
||||
{
|
||||
int i;
|
||||
for (i=1; i <= MAX_CLASSES; i++)
|
||||
{
|
||||
int nClass = GetClassByPosition(i, oPC);
|
||||
if (nClass == CLASS_TYPE_INVALID) break;
|
||||
|
||||
if(GetLocalInt(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass)))
|
||||
{
|
||||
DeleteLocalInt(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass));
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "0");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "1");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "2");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "3");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "4");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "5");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "6");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "7");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "8");
|
||||
DeleteLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + "9");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now build the cache
|
||||
void GenerateSpellsMemorizedCache(int nClass, object oPC)
|
||||
{
|
||||
// get the object on the hide of oPC where the persistant data are stored
|
||||
object oToken = GetHideToken(oPC);
|
||||
string sSpellsMemorized = GetSpellsMemorized_Array(nClass);
|
||||
|
||||
// if the persistant array with the remaining memorized spells does not exist, abort
|
||||
if(!array_exists(oToken, sSpellsMemorized))
|
||||
{
|
||||
if(DEBUG) DoDebug("Error: " +sSpellsMemorized+ " array does not exist");
|
||||
}
|
||||
else
|
||||
{
|
||||
string sFile = GetNSBDefinitionFileName(nClass);
|
||||
string sArrayIDX, sSpellbookID, sMessage, sMess, sClass = IntToString(nClass);
|
||||
|
||||
// remember the class (because this might change during the conversation)
|
||||
SetLocalInt(oPC, SPELLS_MEMORIZED_CACHE + sClass, TRUE);
|
||||
|
||||
int nSpellLevel, nSlot, nSlots, nSpellbookID;
|
||||
for(nSpellLevel = 0; nSpellLevel <= 9; nSpellLevel++)
|
||||
{
|
||||
sArrayIDX = "SpellbookIDX" + IntToString(nSpellLevel) + "_" + sClass;
|
||||
sMessage = "";
|
||||
nSlots = array_get_size(oToken, sArrayIDX);
|
||||
for(nSlot = 0; nSlot < nSlots; nSlot++)
|
||||
{
|
||||
nSpellbookID = array_get_int(oToken, sArrayIDX, nSlot);
|
||||
int nCount = nSpellbookID ? array_get_int(oToken, sSpellsMemorized, nSpellbookID) : 0;
|
||||
if(nCount)
|
||||
{
|
||||
// determine spell name from spellID by reference
|
||||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||||
sMess = PRC_TEXT_WHITE + GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||||
// add the metamagic [ext emp]
|
||||
int nMetaMagicFeat = StringToInt(Get2DACache(sFile, "ReqFeat", nSpellbookID));
|
||||
if(nMetaMagicFeat)
|
||||
{
|
||||
int nMetaMagic = GetMetaMagicFromFeat(nMetaMagicFeat);
|
||||
sMess += " - " +GetMetaMagicString(nMetaMagic);
|
||||
}
|
||||
// add the nr of spells in memory
|
||||
sMess += PRC_TEXT_BLUE + " [" +IntToString(nCount)+ "]\n";
|
||||
sMessage += sMess;
|
||||
}
|
||||
}
|
||||
// now store the values for later retrieval
|
||||
if (sMessage != "") SetLocalString(oPC, SPELLS_MEMORIZED_CACHE + sClass + "_" + IntToString(nSpellLevel), sMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// we delete the cached values on exit from the conversation, so no need to do it now
|
||||
// DelayCommand(6.0, DeleteSpellsMemorizedCache(oPC));
|
||||
}
|
||||
|
||||
// creates a string with a list of memorized spells of the given nClass and nSpellSlotLevel
|
||||
// each spell has an extra line, which denotes the spell's name
|
||||
string ListMemorizedSpells(int nClass, int nSpellSlotLevel, object oPC)
|
||||
{
|
||||
// try to get the list from cache; but only if cache is for the correct nClass
|
||||
//if (GetLocalInt(oPC, SPELLS_MEMORIZED_CACHE) == nClass)
|
||||
//{
|
||||
return GetLocalString(oPC, SPELLS_MEMORIZED_CACHE + IntToString(nClass) + "_" + IntToString(nSpellSlotLevel));
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Main function */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = GetPCSpeaker();
|
||||
/* Get the value of the local variable set by the conversation script calling
|
||||
* this script. Values:
|
||||
* DYNCONV_ABORTED Conversation aborted
|
||||
* DYNCONV_EXITED Conversation exited via the exit node
|
||||
* DYNCONV_SETUP_STAGE System's reply turn
|
||||
* 0 Error - something else called the script
|
||||
* Other The user made a choice
|
||||
*/
|
||||
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
|
||||
// The stage is used to determine the active conversation node.
|
||||
// 0 is the entry node.
|
||||
int nStage = GetStage(oPC);
|
||||
|
||||
// Check which of the conversation scripts called the scripts
|
||||
if(nValue == 0) // All of them set the DynConv_Var to non-zero value, so something is wrong -> abort
|
||||
return;
|
||||
|
||||
if(nValue == DYNCONV_SETUP_STAGE)
|
||||
{
|
||||
// Check if this stage is marked as already set up
|
||||
// This stops list duplication when scrolling
|
||||
if(!GetIsStageSetUp(nStage, oPC))
|
||||
{
|
||||
if(nStage == STAGE_SELECT_CLASS)
|
||||
{
|
||||
//select spell class
|
||||
SetHeader("Select a spell book:");
|
||||
int i;
|
||||
for (i=1; i <= MAX_CLASSES; i++)
|
||||
{
|
||||
int nClass = GetClassByPosition(i, oPC);
|
||||
if (nClass == CLASS_TYPE_INVALID) break;
|
||||
|
||||
if(GetIsNSBClass(nClass) && // must be a new spellbook class
|
||||
GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_PREPARED) // must be a prepared caster
|
||||
{
|
||||
// must have levels in the prepared class and at least level 1 spell slots
|
||||
int nAbilityScore = GetAbilityScoreForClass(nClass, oPC);
|
||||
int nClassLevel = GetLevelByPosition(i, oPC);
|
||||
if(nClassLevel
|
||||
&& (GetSlotCount(nClassLevel, 0, nAbilityScore, nClass)
|
||||
|| GetSlotCount(nClassLevel, 1, nAbilityScore, nClass)))
|
||||
{
|
||||
string sClassName = GetStringByStrRef(StringToInt(Get2DACache("classes", "Name", nClass)));
|
||||
GenerateSpellsMemorizedCache(nClass, oPC);
|
||||
AddChoice(sClassName, nClass, oPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SELECT_SPELL_LEVEL)
|
||||
{
|
||||
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
|
||||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||||
|
||||
int nMaxSpellSlotLevel = GetMaxSpellLevelForCasterLevel(nClass, nCasterLevel);
|
||||
int nMinSpellSlotLevel = GetMinSpellLevelForCasterLevel(nClass, nCasterLevel);
|
||||
|
||||
int nChoiceAdded = FALSE;
|
||||
|
||||
if(nMaxSpellSlotLevel >= nMinSpellSlotLevel)
|
||||
{
|
||||
string sChoiceSpellLevel = "Spell slot level ";
|
||||
int nAbilityScore = GetAbilityScoreForClass(nClass, oPC);
|
||||
|
||||
// List all spell slot levels available to the caster for this class
|
||||
int nSpellSlotLevel;
|
||||
for(nSpellSlotLevel = nMinSpellSlotLevel; nSpellSlotLevel <= nMaxSpellSlotLevel; nSpellSlotLevel++)
|
||||
{
|
||||
// for every spell level, determine the slot count, and if it is non-zero add a choice
|
||||
// we do not break out of the loop on an empty slot count, because of bonus slot counts from items there might be gaps
|
||||
if(GetSlotCount(nCasterLevel, nSpellSlotLevel, nAbilityScore, nClass))
|
||||
{
|
||||
AddChoice(sChoiceSpellLevel +IntToString(nSpellSlotLevel), nSpellSlotLevel, oPC);
|
||||
nChoiceAdded = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nChoiceAdded)
|
||||
SetHeader("Select a spell slot level:");
|
||||
else
|
||||
SetHeader("You cannot memorize any spells at the moment - check your ability score");
|
||||
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SELECT_SPELL_SLOT)
|
||||
{
|
||||
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
|
||||
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
|
||||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||||
|
||||
int nAbilityScore = GetAbilityScoreForClass(nClass, oPC);
|
||||
|
||||
// get the object on the hide of oPC where the persistant data are stored
|
||||
//object oToken = GetHideToken(oPC);
|
||||
|
||||
// determine the name of the persistant array that holds the spells to be memorized for the given nClass and nSpellLevel
|
||||
// (the index to the array is the nr of the slot of the given nClass and nSpellLevel)
|
||||
string sSpellsToBeMemorized = GetSpellsToBeMemorized_Array(nClass, nSpellSlotLevel);
|
||||
// unfortunatly, the spellsMemorized list has a different format (all spell levels in one huge sparse array, indexed by nSpellbookID)
|
||||
string sSpellsMemorized = GetSpellsMemorized_Array(nClass);
|
||||
|
||||
// now check if the arrays "spells to be memorized" and "spells memorized" exist at the given spell slot level and create them, if not
|
||||
if (persistant_array_get_size(oPC, sSpellsToBeMemorized) < 0) persistant_array_create(oPC, sSpellsToBeMemorized);
|
||||
if (persistant_array_get_size(oPC, sSpellsMemorized) < 0) persistant_array_create(oPC, sSpellsMemorized);
|
||||
|
||||
string sHeader = "You have remaining:\n";
|
||||
sHeader += ListMemorizedSpells(nClass, nSpellSlotLevel, oPC) + "\n";
|
||||
|
||||
// get the nr of spell slots for the given nClass and nSpellLevel
|
||||
// (should be non-zero, because we only allow the PC to select spell slot levels with non-zero slot count)
|
||||
int nSlots = GetSlotCount(nCasterLevel, nSpellSlotLevel, nAbilityScore, nClass, oPC);
|
||||
if (nSlots > 0)
|
||||
{
|
||||
sHeader += "Select a spell slot:\n"+ PRC_TEXT_WHITE + "spell to be memorized " + PRC_TEXT_BLUE + "[# still in memory]";
|
||||
|
||||
// set the array size of "spells to be memorized" and "spells memorized" to the nr of slots. +1 to skip 0s
|
||||
SQLocals_SetInt(oPC, sSpellsToBeMemorized, nSlots+1);
|
||||
|
||||
string sFile = GetNSBDefinitionFileName(nClass);
|
||||
string sChoice;
|
||||
string sNameToBeMemorized;
|
||||
// add a choice for every slot; show what is currently in the slot (if nothing, show "empty")
|
||||
int nSlotNr;
|
||||
for(nSlotNr = 0; nSlotNr < nSlots; nSlotNr++)
|
||||
{
|
||||
// get the spell associated with the i-th slot
|
||||
int nSpellbookID = persistant_array_get_int(oPC, sSpellsToBeMemorized, nSlotNr);
|
||||
int nMetaMagic = 0;
|
||||
// nothing "to be memorized" for this slot?
|
||||
if (nSpellbookID == 0)
|
||||
{
|
||||
sNameToBeMemorized = "Empty";
|
||||
}
|
||||
else
|
||||
{
|
||||
// get the spell name "to be memorized", including metamagic
|
||||
// int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||
// sNameToBeMemorized = GetStringByStrRef(StringToInt(Get2DACache("iprp_feats", "Name", nIPFeatID)));
|
||||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||||
sNameToBeMemorized = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||||
|
||||
nMetaMagic = GetMetaMagicFromFeat(StringToInt(Get2DACache(sFile, "ReqFeat", nSpellbookID)));
|
||||
if (nMetaMagic) sNameToBeMemorized += " - " + GetMetaMagicString(nMetaMagic);
|
||||
}
|
||||
|
||||
//first we show what spell will "be memorized" at next rest from the given slot (this is in white)
|
||||
sChoice = PRC_TEXT_WHITE + sNameToBeMemorized;
|
||||
|
||||
// now check if there are spells still in memory that are equal to the spell "to be memorized" at the given slot
|
||||
if (nSpellbookID)
|
||||
{
|
||||
int nNrOfSpells_Mem = persistant_array_get_int(oPC, sSpellsMemorized, nSpellbookID);
|
||||
// show in blue and in brackets
|
||||
sChoice += PRC_TEXT_BLUE + " [" +IntToString(nNrOfSpells_Mem)+ "]";
|
||||
}
|
||||
|
||||
// add the slot nr as choice
|
||||
AddChoice(sChoice, nSlotNr, oPC);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sHeader += PRC_TEXT_WHITE + "there aren't any slots available at the chosen level - check your ability score";
|
||||
}
|
||||
SetHeader(sHeader);
|
||||
AddChoice("Back", CHOICE_RETURN_TO_PREVIOUS);
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
}
|
||||
else if (nStage == STAGE_SELECT_METAMAGIC)
|
||||
{
|
||||
// get the metamagic feats oPC possesses
|
||||
int nMetaMagicCaster = GetMetaMagicOfCaster(oPC);
|
||||
int bChoiceAdded;
|
||||
// only need to do this, if the caster has at least one metamagic feat
|
||||
if (nMetaMagicCaster)
|
||||
{
|
||||
// get the currently selected spell slot level
|
||||
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
|
||||
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
|
||||
int nCasterLevel = GetCasterLevelByClass(nClass, oPC);
|
||||
int nMinSpellSlotLevel = GetMinSpellLevelForCasterLevel(nClass, nCasterLevel);
|
||||
|
||||
// metamagics only for slot levels higher than the lowest slot level
|
||||
if (nSpellSlotLevel > nMinSpellSlotLevel)
|
||||
{
|
||||
// calculate the maximum metamagic adjustment that is possible at the given spell slot level
|
||||
// note that the metamagic adjustment will generally result in spells to choose from, that are
|
||||
// lower in level than the spell slot level. But we cannot reduce the level below the minimum spell level of the class
|
||||
int nMaxMetaMagicAdj = nSpellSlotLevel - nMinSpellSlotLevel;
|
||||
|
||||
// go through all possible metamagics by shifting 1 to the left
|
||||
// this will result in checking for some metamagics that are not implemented
|
||||
// but the check against the metamagic feats possessed be oPC will get rid of all non-implemented
|
||||
int nMetaMagic;
|
||||
for (nMetaMagic = 1; nMetaMagic < 0x40; nMetaMagic <<= 1)
|
||||
{
|
||||
if ((nMetaMagicCaster & nMetaMagic) // caster must have the metamagic feat
|
||||
// and the combined levels of the already chosen metamagic with the metamagic to choose must be
|
||||
// less or equal than the max metamagic adjustment allowed for nClass at the given nSpellSlotLevel
|
||||
&& GetMetaMagicSpellLevelAdjustment(nMetaMagic) <= nMaxMetaMagicAdj)
|
||||
{
|
||||
AddChoice(GetMetaMagicString(nMetaMagic), nMetaMagic, oPC);
|
||||
bChoiceAdded = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bChoiceAdded)
|
||||
{
|
||||
SetHeader("Select a metamagic adjustment:");
|
||||
AddChoice("No metamagic", 0, oPC);
|
||||
AddChoice("Back", CHOICE_RETURN_TO_PREVIOUS);
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no metamagics available at the spell slot level?
|
||||
if (!bChoiceAdded)
|
||||
{
|
||||
// then advance to next stage and clear metamagic
|
||||
SetStage(++nStage, oPC);
|
||||
DeleteLocalInt(oPC, CONV_SPELLB_META);
|
||||
}
|
||||
|
||||
MarkStageSetUp(STAGE_SELECT_METAMAGIC, oPC);
|
||||
}
|
||||
|
||||
// if-clause is intentional; DONT change to else-if
|
||||
if(nStage == STAGE_SELECT_SPELL)
|
||||
{
|
||||
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
|
||||
int nMetaMagic = GetLocalInt(oPC, CONV_SPELLB_META);
|
||||
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
|
||||
int nSpellLevel = nSpellSlotLevel - GetMetaMagicSpellLevelAdjustment(nMetaMagic);
|
||||
|
||||
// determine from where to get the spells known (for nClass at the given level)
|
||||
// so far this is the class spellbook, eg. all spells are available (divine casters)
|
||||
string sFile = GetNSBDefinitionFileName(nClass);
|
||||
object oToken;
|
||||
string sSpellBook;
|
||||
if(bKnowsAllClassSpells(nClass))
|
||||
{
|
||||
oToken = GetSpellsOfClass_Token(nClass, nSpellLevel);
|
||||
sSpellBook = GetSpellsOfClass_Array();
|
||||
}
|
||||
else
|
||||
{
|
||||
oToken = GetHideToken(oPC);
|
||||
sSpellBook = GetSpellsKnown_Array(nClass, nSpellLevel);
|
||||
}
|
||||
|
||||
// go through all spells that oPC has in his spellbook at the given nSpellLevel ( for divine casters this might be all)
|
||||
// motu99: This array does NOT include the metamagicked versions of the spells or subradial versions!
|
||||
int nSpellsKnown = array_get_size(oToken, sSpellBook);
|
||||
int bSpellSelected = FALSE;
|
||||
int i;
|
||||
for(i = 0; i < nSpellsKnown; i++)
|
||||
{
|
||||
// this is the cls_spell_* row nr for the UNMETAMAGICKED version of the spell
|
||||
int nSpellbookID = array_get_int(oToken, sSpellBook, i);
|
||||
|
||||
// get the real spellID
|
||||
int nSpellID = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||||
|
||||
// if we choose a metamagic, find the nSpellbookID for the metamagic version of the spell
|
||||
// all metamagic versions of the master spell lie in a consecutive block after the non-metamagic version
|
||||
if (nMetaMagic)
|
||||
{
|
||||
// get the next row in cls_spell_* and test if it belongs to the same real spellID
|
||||
while (StringToInt(Get2DACache(sFile, "RealSpellID", ++nSpellbookID)) == nSpellID)
|
||||
{
|
||||
// do the metamagics match?
|
||||
if (nMetaMagic == GetMetaMagicFromFeat(StringToInt(Get2DACache(sFile, "ReqFeat", nSpellbookID))))
|
||||
{
|
||||
// indicate success by negative nr
|
||||
nSpellbookID = -nSpellbookID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// success? then redo the negation
|
||||
if (nSpellbookID < 0)
|
||||
nSpellbookID = -nSpellbookID;
|
||||
// otherwise indicate failure by setting nSpellbookID to zero
|
||||
else
|
||||
nSpellbookID = 0;
|
||||
}
|
||||
|
||||
// did we find an appropriate spellbook ID for the given spell slot evel and metamagic?
|
||||
// then add it to the list
|
||||
if (nSpellbookID)
|
||||
{
|
||||
// int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||
// string sName = GetStringByStrRef(StringToInt(Get2DACache("iprp_feats", "Name", nIPFeatID)));
|
||||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||||
if (nMetaMagic) sName + " - " +GetMetaMagicString(nMetaMagic);
|
||||
|
||||
AddChoice(sName, nSpellbookID, oPC);
|
||||
bSpellSelected = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bSpellSelected)
|
||||
SetHeader("Select a spell:");
|
||||
else
|
||||
SetHeader("No spells to select at spell level " + IntToString (nSpellLevel));
|
||||
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
}
|
||||
}
|
||||
|
||||
// Do token setup
|
||||
SetupTokens();
|
||||
}
|
||||
else if(nValue == DYNCONV_EXITED ||
|
||||
nValue == DYNCONV_ABORTED )
|
||||
{
|
||||
//end of conversation cleanup
|
||||
DeleteLocalInt(oPC, CONV_SPELLB_CLASS);
|
||||
DeleteLocalInt(oPC, CONV_SPELLB_LEVEL);
|
||||
DeleteLocalInt(oPC, CONV_SPELLB_SLOT);
|
||||
DeleteLocalInt(oPC, CONV_SPELLB_META);
|
||||
|
||||
DeleteSpellsMemorizedCache(oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
int nChoice = GetChoice(oPC);
|
||||
if(nStage == STAGE_SELECT_CLASS)
|
||||
{
|
||||
//store nClass and proceed to slot level selection
|
||||
SetLocalInt(oPC, CONV_SPELLB_CLASS, nChoice);
|
||||
nStage = STAGE_SELECT_SPELL_LEVEL;
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SELECT_SPELL_LEVEL)
|
||||
{
|
||||
//store slot level and proceed to spell slot selection
|
||||
SetLocalInt(oPC, CONV_SPELLB_LEVEL, nChoice);
|
||||
nStage = STAGE_SELECT_SPELL_SLOT;
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SELECT_SPELL_SLOT)
|
||||
{
|
||||
if(nChoice == CHOICE_RETURN_TO_PREVIOUS)
|
||||
nStage = STAGE_SELECT_SPELL_LEVEL;
|
||||
else
|
||||
{
|
||||
// store the spell slot nr and go to metamagic selection phase
|
||||
SetLocalInt(oPC, CONV_SPELLB_SLOT, nChoice);
|
||||
nStage = STAGE_SELECT_METAMAGIC;
|
||||
}
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SELECT_METAMAGIC)
|
||||
{
|
||||
if(nChoice == CHOICE_RETURN_TO_PREVIOUS)
|
||||
nStage = STAGE_SELECT_SPELL_SLOT;
|
||||
else
|
||||
{
|
||||
// store the metamagic and proceed to spell selection phase
|
||||
SetLocalInt(oPC, CONV_SPELLB_META, nChoice);
|
||||
nStage = STAGE_SELECT_SPELL;
|
||||
}
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SELECT_SPELL)
|
||||
{
|
||||
// our choice is the nSpellbookID
|
||||
|
||||
// get the other vital information
|
||||
int nSpellSlot = GetLocalInt(oPC, CONV_SPELLB_SLOT);
|
||||
int nSpellSlotLevel = GetLocalInt(oPC, CONV_SPELLB_LEVEL);
|
||||
int nClass = GetLocalInt(oPC, CONV_SPELLB_CLASS);
|
||||
int nMetaMagic = GetLocalInt(oPC, CONV_SPELLB_META);
|
||||
|
||||
// get the object on the hide of oPC where the persistant data are stored
|
||||
object oToken = GetHideToken(oPC);
|
||||
// determine the name of the persistant array that holds the spells to be memorized for the given nClass and nSpellLevel
|
||||
// (the index to the array is the nr of the slot of the given nClass and nSpellLevel)
|
||||
string sSpellsToBeMemorized = GetSpellsToBeMemorized_Array(nClass, nSpellSlotLevel);
|
||||
|
||||
// store the chosen nSpellbookID (row nr in the newspellbook file cls_spells_*) in the spells to be memorized array
|
||||
array_set_int(oToken, sSpellsToBeMemorized, nSpellSlot, nChoice);
|
||||
|
||||
// let oPC select a new spell (starting with the spell level)
|
||||
nStage = STAGE_SELECT_SPELL_LEVEL;
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
|
||||
// Store the stage value. If it has been changed, this clears out the choices
|
||||
SetStage(nStage, oPC);
|
||||
}
|
||||
}
|
||||
|
||||
598
trunk/users/Stratovarius/NWNEE Updates/inc_lookups.nss
Normal file
598
trunk/users/Stratovarius/NWNEE Updates/inc_lookups.nss
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
|
||||
This file is used for lookup functions for psionics and newspellbooks
|
||||
It is supposed to reduce the need for large loops that may result in
|
||||
TMI errors.
|
||||
It does this by creating arrays in advance and the using those as direct
|
||||
lookups.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
void MakeLookupLoop(int nClass, string sFile, int nMin, int nMax, int nLoopSize = 100, string sTemp = "");
|
||||
void SetupLookupStage(object oMod, int n);
|
||||
|
||||
|
||||
//this returns the real SpellID of "wrapper" spells cast by psionic or the new spellbooks
|
||||
int GetPowerFromSpellID(int nSpellID);
|
||||
|
||||
/**
|
||||
* Maps spells.2da rows of the class-specific entries to corresponding cls_psipw_*.2da rows.
|
||||
*
|
||||
* @param nSpellID Spells.2da row to determine cls_psipw_*.2da row for
|
||||
* @return The mapped value
|
||||
*/
|
||||
int GetPowerfileIndexFromSpellID(int nSpellID);
|
||||
|
||||
/**
|
||||
* Maps spells.2da rows of the real entries to corresponding cls_psipw_*.2da rows.
|
||||
*
|
||||
* @param nSpellID Spells.2da row to determine cls_psipw_*.2da row for
|
||||
* @return The mapped value
|
||||
*/
|
||||
int GetPowerfileIndexFromRealSpellID(int nRealSpellID);
|
||||
|
||||
//this retuns the featID of the class-specific feat for a spellID
|
||||
//useful for psionics GetHasPower function
|
||||
int GetClassFeatFromPower(int nPowerID, int nClass);
|
||||
|
||||
/**
|
||||
* Determines cls_spell_*.2da index from a given new spellbook class-specific
|
||||
* spell spells.2da index.
|
||||
*
|
||||
* @param nSpell The class-specific spell to find cls_spell_*.2da index for
|
||||
* @return The cls_spell_*.2da index in whichever class's file that the
|
||||
* given spell belongs to.
|
||||
* If the spell at nSpell isn't a newspellbook class-specific spell,
|
||||
* returns -1 instead.
|
||||
*/
|
||||
int SpellToSpellbookID(int nSpell);
|
||||
|
||||
/**
|
||||
* Determines cls_spell_*.2da index from a given spells.2da index.
|
||||
*
|
||||
* @param nClass The class in whose spellbook to search in
|
||||
* @param nSpell The spell to search for
|
||||
* @return The cls_spell_*.2da index in whichever class's file that the
|
||||
* given spell belongs to.
|
||||
* If nSpell does not exist within the spellbook,
|
||||
* returns -1 instead.
|
||||
*/
|
||||
int RealSpellToSpellbookID(int nClass, int nSpell);
|
||||
|
||||
/**
|
||||
* Determines number of metamagics from a given spells.2da index.
|
||||
*
|
||||
* @param nClass The class in whose spellbook to search in
|
||||
* @param nSpell The spell to search for
|
||||
* @return The number of metamagics in cls_spell_*.2da
|
||||
* for a particular spell.
|
||||
*/
|
||||
int RealSpellToSpellbookIDCount(int nClass, int nSpell);
|
||||
|
||||
/**
|
||||
* Determines the name of the 2da file that defines the number of alternate magic
|
||||
* system powers/spells/whathaveyou known, maximum level of such known and
|
||||
* number of uses at each level of the given class. And possibly related things
|
||||
* that apply to that specific system.
|
||||
*
|
||||
* @param nClass CLASS_TYPE_* of the class to determine the powers known 2da name of
|
||||
* @return The name of the given class's powers known 2da
|
||||
*/
|
||||
string GetAMSKnownFileName(int nClass);
|
||||
|
||||
/**
|
||||
* Determines the name of the 2da file that lists the powers/spells/whathaveyou
|
||||
* on the given class's list of such.
|
||||
*
|
||||
* @param nClass CLASS_TYPE_* of the class to determine the power list 2da name of
|
||||
* @return The name of the given class's power list 2da
|
||||
*/
|
||||
string GetAMSDefinitionFileName(int nClass);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Includes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
#include "inc_2dacache"
|
||||
#include "inc_array"
|
||||
#include "prc_class_const"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Internal functions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
object _inc_lookups_GetCacheObject(string sTag)
|
||||
{
|
||||
object oWP = GetObjectByTag(sTag);
|
||||
if(!GetIsObjectValid(oWP))
|
||||
{
|
||||
object oChest = GetObjectByTag("Bioware2DACache");
|
||||
if(!GetIsObjectValid(oChest))
|
||||
{
|
||||
//has to be an object, placeables cant go through the DB
|
||||
oChest = CreateObject(OBJECT_TYPE_CREATURE, "prc_2da_cache",
|
||||
GetLocation(GetObjectByTag("HEARTOFCHAOS")), FALSE, "Bioware2DACache");
|
||||
}
|
||||
if(!GetIsObjectValid(oChest))
|
||||
{
|
||||
//has to be an object, placeables cant go through the DB
|
||||
oChest = CreateObject(OBJECT_TYPE_CREATURE, "prc_2da_cache",
|
||||
GetStartingLocation(), FALSE, "Bioware2DACache");
|
||||
}
|
||||
|
||||
int nContainer = 0;
|
||||
string sContainerName = "Bio2DACacheTokenContainer_Lkup_";
|
||||
object oContainer = GetObjectByTag(sContainerName + IntToString(nContainer));
|
||||
|
||||
// Find last existing container
|
||||
if(GetIsObjectValid(oContainer))
|
||||
{
|
||||
nContainer = GetLocalInt(oContainer, "ContainerCount");
|
||||
oContainer = GetObjectByTag(sContainerName + IntToString(nContainer));
|
||||
|
||||
// Make sure it's not full
|
||||
if(GetLocalInt(oContainer, "NumTokensInside") >= 34) // Container has 35 slots. Attempt to not use them all, just in case
|
||||
{
|
||||
oContainer = OBJECT_INVALID;
|
||||
++nContainer; // new container is 1 higher than last one
|
||||
}
|
||||
}
|
||||
|
||||
// We need to create a container
|
||||
if(!GetIsObjectValid(oContainer))
|
||||
{
|
||||
oContainer = CreateObject(OBJECT_TYPE_ITEM, "nw_it_contain001", GetLocation(oChest), FALSE, sContainerName + IntToString(nContainer));
|
||||
DestroyObject(oContainer);
|
||||
oContainer = CopyObject(oContainer, GetLocation(oChest), oChest, sContainerName + IntToString(nContainer));
|
||||
// store the new number of containers in this series
|
||||
if(nContainer)
|
||||
SetLocalInt(GetObjectByTag(sContainerName + "0"), "ContainerCount", nContainer);
|
||||
// else this is the first container - do nothing as this is the same as storing 0 on it.
|
||||
// Also here we still have 2 objects with the same tag so above code may get
|
||||
// the object destroyed at the end of the function if this is the first container.
|
||||
}
|
||||
|
||||
// Create the new token
|
||||
oWP = CreateItemOnObject("hidetoken", oContainer, 1, sTag);
|
||||
|
||||
// Increment token count tracking variable
|
||||
SetLocalInt(oContainer, "NumTokensInside", GetLocalInt(oContainer, "NumTokensInside") + 1);
|
||||
}
|
||||
|
||||
if(!GetIsObjectValid(oWP))
|
||||
{
|
||||
DoDebug("ERROR: Failed to create lookup storage token for " + sTag);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
return oWP;
|
||||
}
|
||||
|
||||
void SetLkupStage(int nStage, object oModule, int nClass, string sFile)
|
||||
{
|
||||
SetLocalInt(oModule, "PRCLookup_Stage", nStage + 1);
|
||||
SetLocalInt(oModule, "PRCLookup_Class", nClass);
|
||||
SetLocalString(oModule, "PRCLookup_File", sFile);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void RunLookupLoop()
|
||||
{
|
||||
// check if we run lookup before
|
||||
if(GetXP(GetObjectByTag("Bioware2DACache")) & 0x01)
|
||||
{
|
||||
if (DEBUG) DoDebug("RunLookupLoop() - marker found - exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
object oModule = GetModule();
|
||||
SetupLookupStage(oModule, 1);
|
||||
int nClass = GetLocalInt(oModule, "PRCLookup_Class");
|
||||
string sFile = GetLocalString(oModule, "PRCLookup_File");
|
||||
if (DEBUG) DoDebug("RunLookupLoop(): Looking in "+sFile+" for nClass "+IntToString(nClass));
|
||||
MakeLookupLoop(nClass, sFile, 1, PRCGetDynamicFileEnd(sFile));
|
||||
}
|
||||
|
||||
void RunNextLoop()
|
||||
{
|
||||
object oModule = GetModule();
|
||||
int nStage = GetLocalInt(oModule, "PRCLookup_Stage");
|
||||
SetupLookupStage(oModule, nStage);
|
||||
int nClass = GetLocalInt(oModule, "PRCLookup_Class");
|
||||
if(nClass)
|
||||
{
|
||||
string sFile = GetLocalString(oModule, "PRCLookup_File");
|
||||
if (DEBUG) DoDebug("RunNextLoop(): Looking in "+sFile+" for nClass "+IntToString(nClass));
|
||||
MakeLookupLoop(nClass, sFile, 1, PRCGetDynamicFileEnd(sFile));
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteLocalInt(oModule, "PRCLookup_Stage");
|
||||
DeleteLocalInt(oModule, "PRCLookup_Class");
|
||||
DeleteLocalString(oModule, "PRCLookup_File");
|
||||
|
||||
//mark lookup as done, tell hb to save the DB
|
||||
object oCache = GetObjectByTag("Bioware2DACache");
|
||||
SetXP(oCache, GetXP(oCache) | 0x01);
|
||||
SetLocalInt(oModule, "Bioware2dacacheCount", GetPRCSwitch(PRC_USE_BIOWARE_DATABASE) - 5);
|
||||
}
|
||||
}
|
||||
|
||||
void SetupLookupStage(object oMod, int n)
|
||||
{
|
||||
switch(n)
|
||||
{
|
||||
case 1: SetLkupStage(n, oMod, CLASS_TYPE_PSION, "cls_psipw_psion"); break;
|
||||
case 2: SetLkupStage(n, oMod, CLASS_TYPE_PSYWAR, "cls_psipw_psywar"); break;
|
||||
case 3: SetLkupStage(n, oMod, CLASS_TYPE_WILDER, "cls_psipw_wilder"); break;
|
||||
case 4: SetLkupStage(n, oMod, CLASS_TYPE_FIST_OF_ZUOKEN, "cls_psipw_foz"); break;
|
||||
case 5: SetLkupStage(n, oMod, CLASS_TYPE_WARMIND, "cls_psipw_warmnd"); break;
|
||||
case 6: SetLkupStage(n, oMod, CLASS_TYPE_TRUENAMER, "cls_true_utter"); break;
|
||||
case 7: SetLkupStage(n, oMod, CLASS_TYPE_CRUSADER, "cls_move_crusdr"); break;
|
||||
case 8: SetLkupStage(n, oMod, CLASS_TYPE_SWORDSAGE, "cls_move_swdsge"); break;
|
||||
case 9: SetLkupStage(n, oMod, CLASS_TYPE_WARBLADE, "cls_move_warbld"); break;
|
||||
case 10: SetLkupStage(n, oMod, CLASS_TYPE_DRAGONFIRE_ADEPT, "cls_inv_dfa"); break;
|
||||
case 11: SetLkupStage(n, oMod, CLASS_TYPE_DRAGON_SHAMAN, "cls_inv_drgshm"); break;
|
||||
case 12: SetLkupStage(n, oMod, CLASS_TYPE_WARLOCK, "cls_inv_warlok"); break;
|
||||
case 13: SetLkupStage(n, oMod, CLASS_TYPE_ARCHIVIST, "cls_spell_archv"); break;
|
||||
case 14: SetLkupStage(n, oMod, CLASS_TYPE_ASSASSIN, "cls_spell_asasin"); break;
|
||||
case 15: SetLkupStage(n, oMod, CLASS_TYPE_BARD, "cls_spell_bard"); break;
|
||||
case 16: SetLkupStage(n, oMod, CLASS_TYPE_BEGUILER, "cls_spell_beguil"); break;
|
||||
case 17: SetLkupStage(n, oMod, CLASS_TYPE_BLACKGUARD, "cls_spell_blkgrd"); break;
|
||||
case 18: SetLkupStage(n, oMod, CLASS_TYPE_DREAD_NECROMANCER, "cls_spell_dnecro"); break;
|
||||
case 19: SetLkupStage(n, oMod, CLASS_TYPE_DUSKBLADE, "cls_spell_duskbl"); break;
|
||||
case 20: SetLkupStage(n, oMod, CLASS_TYPE_FAVOURED_SOUL, "cls_spell_favsol"); break;
|
||||
case 21: SetLkupStage(n, oMod, CLASS_TYPE_HARPER, "cls_spell_harper"); break;
|
||||
case 22: SetLkupStage(n, oMod, CLASS_TYPE_HEALER, "cls_spell_healer"); break;
|
||||
case 23: SetLkupStage(n, oMod, CLASS_TYPE_HEXBLADE, "cls_spell_hexbl"); break;
|
||||
case 24: SetLkupStage(n, oMod, CLASS_TYPE_JUSTICEWW, "cls_spell_justww"); break;
|
||||
case 25: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_CHALICE, "cls_spell_kchal"); break;
|
||||
case 26: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_MIDDLECIRCLE, "cls_spell_kotmc"); break;
|
||||
case 27: SetLkupStage(n, oMod, CLASS_TYPE_OCULAR, "cls_spell_ocu"); break;
|
||||
case 28: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWLORD, "cls_spell_tfshad"); break;
|
||||
case 29: SetLkupStage(n, oMod, CLASS_TYPE_SHAMAN, "cls_spell_shaman"); break;
|
||||
case 30: SetLkupStage(n, oMod, CLASS_TYPE_SLAYER_OF_DOMIEL, "cls_spell_sod"); break;
|
||||
case 31: SetLkupStage(n, oMod, CLASS_TYPE_SOHEI, "cls_spell_sohei"); break;
|
||||
case 32: SetLkupStage(n, oMod, CLASS_TYPE_SOLDIER_OF_LIGHT, "cls_spell_sol"); break;
|
||||
case 33: SetLkupStage(n, oMod, CLASS_TYPE_SORCERER, "cls_spell_sorc"); break;
|
||||
case 34: SetLkupStage(n, oMod, CLASS_TYPE_SUBLIME_CHORD, "cls_spell_schord"); break;
|
||||
case 35: SetLkupStage(n, oMod, CLASS_TYPE_SUEL_ARCHANAMACH, "cls_spell_suel"); break;
|
||||
case 36: SetLkupStage(n, oMod, CLASS_TYPE_VASSAL, "cls_spell_vassal"); break;
|
||||
case 37: SetLkupStage(n, oMod, CLASS_TYPE_VIGILANT, "cls_spell_vigil"); break;
|
||||
case 38: SetLkupStage(n, oMod, CLASS_TYPE_WARMAGE, "cls_spell_wrmage"); break;
|
||||
case 39: SetLkupStage(n, oMod, CLASS_TYPE_BLIGHTER, "cls_spell_blight"); break;
|
||||
case 40: SetLkupStage(n, oMod, CLASS_TYPE_NENTYAR_HUNTER, "cls_spell_hunter"); break;
|
||||
case 41: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_WEAVE, "cls_spell_kngtwv"); break;
|
||||
case 42: SetLkupStage(n, oMod, CLASS_TYPE_PSYCHIC_ROGUE, "cls_psipw_psyrog"); break;
|
||||
case 43: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWCASTER, "cls_myst_shdcst"); break;
|
||||
case 44: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWSMITH, "cls_myst_shdsmt"); break;
|
||||
case 45: SetLkupStage(n, oMod, CLASS_TYPE_CELEBRANT_SHARESS, "cls_spell_sharss"); break;
|
||||
case 46: SetLkupStage(n, oMod, CLASS_TYPE_CULTIST_SHATTERED_PEAK, "cls_spell_cultst"); break;
|
||||
|
||||
default: SetLkupStage(n, oMod, 0, ""); break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
void LookupSpells(int nRealSpellID, string sClass, string sLevel);
|
||||
{
|
||||
int nDescriptor = Get2DACache("prc_spells", "Descriptor", nRealSpellID);//should already be in cache, just read the value
|
||||
|
||||
DESCRIPTOR_ACID
|
||||
DESCRIPTOR_AIR
|
||||
DESCRIPTOR_COLD
|
||||
DESCRIPTOR_LIGHT
|
||||
DESCRIPTOR_ELECTRICITY
|
||||
DESCRIPTOR_DARKNESS
|
||||
DESCRIPTOR_FIRE
|
||||
DESCRIPTOR_SONIC
|
||||
|
||||
|
||||
SUBSCHOOL_HEALING
|
||||
SUBSCHOOL_SUMMONING
|
||||
SUBSCHOOL_POLYMORPH
|
||||
|
||||
SPELL_SCHOOL_ENCHANTMENT
|
||||
SPELL_SCHOOL_NECROMANCY
|
||||
SPELL_SCHOOL_ABJURATION
|
||||
|
||||
string sLevel = Get2DACache("spells", "Cleric", nRealSpellID);
|
||||
if(sLevel != "")
|
||||
{
|
||||
oLevelToken = _inc_lookups_GetCacheObject("SpellLvl_2_Level_"+sLevel);
|
||||
// check if array exist, if not create one
|
||||
if(!array_exists(oLevelToken, "Lkup"))
|
||||
array_create(oLevelToken, "Lkup");
|
||||
array_set_int(oLevelToken, "Lkup", array_get_size(oLevelToken, "Lkup"), i);
|
||||
}
|
||||
sLevel = Get2DACache("spells", "Druid", nRealSpellID);
|
||||
if(sLevel != "")
|
||||
{
|
||||
oLevelToken = _inc_lookups_GetCacheObject("SpellLvl_3_Level_"+sLevel);
|
||||
// check if array exist, if not create one
|
||||
if(!array_exists(oLevelToken, "Lkup"))
|
||||
array_create(oLevelToken, "Lkup");
|
||||
array_set_int(oLevelToken, "Lkup", array_get_size(oLevelToken, "Lkup"), i);
|
||||
}
|
||||
sLevel = Get2DACache("spells", "Paladin", nRealSpellID);
|
||||
if(sLevel != "")
|
||||
{
|
||||
oLevelToken = _inc_lookups_GetCacheObject("SpellLvl_6_Level_"+sLevel);
|
||||
// check if array exist, if not create one
|
||||
if(!array_exists(oLevelToken, "Lkup"))
|
||||
array_create(oLevelToken, "Lkup");
|
||||
array_set_int(oLevelToken, "Lkup", array_get_size(oLevelToken, "Lkup"), i);
|
||||
}
|
||||
sLevel = Get2DACache("spells", "Ranger", nRealSpellID);
|
||||
if(sLevel != "")
|
||||
{
|
||||
oLevelToken = _inc_lookups_GetCacheObject("SpellLvl_7_Level_"+sLevel);
|
||||
// check if array exist, if not create one
|
||||
if(!array_exists(oLevelToken, "Lkup"))
|
||||
array_create(oLevelToken, "Lkup");
|
||||
array_set_int(oLevelToken, "Lkup", array_get_size(oLevelToken, "Lkup"), i);
|
||||
}
|
||||
sLevel = Get2DACache("spells", "Wiz_Sorc", nRealSpellID);
|
||||
if(sLevel != "")
|
||||
{
|
||||
oLevelToken = _inc_lookups_GetCacheObject("SpellLvl_10_Level_"+sLevel);
|
||||
// check if array exist, if not create one
|
||||
if(!array_exists(oLevelToken, "Lkup"))
|
||||
array_create(oLevelToken, "Lkup");
|
||||
array_set_int(oLevelToken, "Lkup", array_get_size(oLevelToken, "Lkup"), i);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
|
||||
void MakeLookupLoop(int nClass, string sFile, int nMin, int nMax, int nLoopSize = 100, string sTemp = "")
|
||||
{
|
||||
// Tell the function to skip before reaching nMax
|
||||
int bSkipLoop = FALSE;
|
||||
int i;
|
||||
|
||||
if(DEBUG) DoDebug("MakeLookupLoop("
|
||||
+IntToString(nClass)+", "
|
||||
+sFile+", "
|
||||
+IntToString(nMin)+", "
|
||||
+IntToString(nMax)+", "
|
||||
+IntToString(nLoopSize)+", "
|
||||
+") : sTemp = "+sTemp);
|
||||
|
||||
// psionic, tob, truenameing and ivocation using classes have slightly different handling
|
||||
// new AMS classes should be added here
|
||||
int bAMS = FALSE;
|
||||
|
||||
if(nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_WARMIND
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_TRUENAMER
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_WARLOCK)
|
||||
bAMS = TRUE;
|
||||
|
||||
//object oSpellIDToken = bAMS ? _inc_lookups_GetCacheObject("PRC_SpellIDToClsPsipw"):
|
||||
// _inc_lookups_GetCacheObject("PRC_GetRowFromSpellID");
|
||||
|
||||
// Failed to obtain a valid token - nothing to store on
|
||||
//if(!GetIsObjectValid(oSpellIDToken))
|
||||
// bSkipLoop = TRUE;
|
||||
|
||||
// Starting a new run and the data is present already. Assume the whole thing is present and abort
|
||||
if(nMin == 1
|
||||
&& GetLocalInt(oSpellIDToken, Get2DACache(sFile, "SpellID", 1)))
|
||||
{
|
||||
if(DEBUG) DoDebug("MakeLookupLoop("+sFile+") restored from database");
|
||||
bSkipLoop = TRUE;
|
||||
}
|
||||
|
||||
if(!bSkipLoop)
|
||||
{
|
||||
string sClass = IntToString(nClass);
|
||||
|
||||
//object oLevelToken;
|
||||
//object oPowerToken = _inc_lookups_GetCacheObject("PRC_GetPowerFromSpellID");
|
||||
//object oRealSpellIDToken = bAMS ? _inc_lookups_GetCacheObject("PRC_GetClassFeatFromPower_"+sClass):
|
||||
_inc_lookups_GetCacheObject("PRC_GetRowFromRealSpellID");
|
||||
|
||||
int nRealSpellID, nFeatID, nCount;
|
||||
string sSpellID, sRealSID;
|
||||
for(i = nMin; i < nMin + nLoopSize; i++)
|
||||
{
|
||||
// None of the relevant 2da files have blank Label entries on rows other than 0. We can assume i is greater than 0 at this point
|
||||
if(Get2DAString(sFile, "Label", i) == "") // Using Get2DAString() instead of Get2DACache() to avoid caching useless data
|
||||
{
|
||||
bSkipLoop = TRUE;
|
||||
break;// exit the loop
|
||||
}
|
||||
|
||||
sSpellID = Get2DACache(sFile, "SpellID", i);
|
||||
sRealSID = Get2DACache(sFile, "RealSpellID", i);
|
||||
nRealSpellID = StringToInt(sRealSID);
|
||||
|
||||
//GetPowerfileIndexFromSpellID
|
||||
//SpellToSpellbookID
|
||||
SetLocalInt(oSpellIDToken, sSpellID, i);
|
||||
|
||||
//GetPowerfileIndexFromRealSpellID
|
||||
SetLocalInt(oSpellIDToken, sRealSID, i);
|
||||
|
||||
//GetPowerFromSpellID
|
||||
SetLocalInt(oPowerToken, sSpellID, nRealSpellID);
|
||||
|
||||
//Spell level lookup
|
||||
if(!bAMS || nClass == CLASS_TYPE_WARLOCK)
|
||||
{
|
||||
string sReqFt = bAMS ? "" : Get2DACache(sFile, "ReqFeat", i);// Only new spellbooks have the ReqFeat column. No sense in caching it for other stuff
|
||||
if(sReqFt == "")
|
||||
{
|
||||
string sLevel = Get2DACache(sFile, "Level", i);
|
||||
//oLevelToken = _inc_lookups_GetCacheObject("SpellLvl_"+sClass+"_Level_"+sLevel);
|
||||
// check if array exist, if not create one
|
||||
if(!persistant_array_exists(oLevelToken, "SpellLvl_"+sClass+"_Level_"+sLevel))
|
||||
persistant_array_create(oLevelToken, "SpellLvl_"+sClass+"_Level_"+sLevel);
|
||||
|
||||
persistant_array_get_int(oLevelToken, "SpellLvl_"+sClass+"_Level_"+sLevel, persistant_array_get_size(oLevelToken, "SpellLvl_"+sClass+"_Level_"+sLevel), i);
|
||||
|
||||
//LookupSpellDescriptor(nRealSpellID, sClass, sLevel);
|
||||
}
|
||||
}
|
||||
|
||||
//GetClassFeatFromPower
|
||||
if(bAMS)
|
||||
{
|
||||
nFeatID = StringToInt(Get2DACache(sFile, "FeatID", i));
|
||||
if(nFeatID != 0)
|
||||
{
|
||||
SetLocalInt(oRealSpellIDToken, sRealSID, nFeatID);
|
||||
}
|
||||
}
|
||||
//RealSpellToSpellbookID
|
||||
//RealSpellToSpellbookIDCount
|
||||
else
|
||||
{
|
||||
if(sRealSID == sTemp)
|
||||
{
|
||||
nCount += 1;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetLocalInt(oRealSpellIDToken, sClass+"_"+sTemp+"_Count", nCount);
|
||||
SetLocalInt(oRealSpellIDToken, sClass+"_"+sRealSID+"_Start", i);
|
||||
sTemp = sRealSID;
|
||||
nCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// And delay continuation to avoid TMI
|
||||
if(i < nMax && !bSkipLoop)
|
||||
DelayCommand(0.0, MakeLookupLoop(nClass, sFile, i, nMax, nLoopSize, sTemp));
|
||||
else
|
||||
DelayCommand(0.0, RunNextLoop());
|
||||
}
|
||||
|
||||
int GetPowerFromSpellID(int nSpellID)
|
||||
{
|
||||
object oWP = GetObjectByTag("PRC_GetPowerFromSpellID");
|
||||
int nPower = GetLocalInt(oWP, /*"PRC_GetPowerFromSpellID_" + */IntToString(nSpellID));
|
||||
if(nPower == 0)
|
||||
nPower = -1;
|
||||
return nPower;
|
||||
}
|
||||
|
||||
int GetPowerfileIndexFromSpellID(int nSpellID)
|
||||
{
|
||||
object oWP = GetObjectByTag("PRC_SpellIDToClsPsipw");
|
||||
int nIndex = GetLocalInt(oWP, /*"PRC_SpellIDToClsPsipw_" + */IntToString(nSpellID));
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
int GetPowerfileIndexFromRealSpellID(int nRealSpellID)
|
||||
{
|
||||
object oWP = GetObjectByTag("PRC_SpellIDToClsPsipw");
|
||||
int nIndex = GetLocalInt(oWP, /*"PRC_SpellIDToClsPsipw_" + */IntToString(nRealSpellID));
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
int GetClassFeatFromPower(int nPowerID, int nClass)
|
||||
{
|
||||
string sLabel = "PRC_GetClassFeatFromPower_" + IntToString(nClass);
|
||||
object oWP = GetObjectByTag(sLabel);
|
||||
int nPower = GetLocalInt(oWP, /*sLabel+"_" + */IntToString(nPowerID));
|
||||
if(nPower == 0)
|
||||
nPower = -1;
|
||||
return nPower;
|
||||
}
|
||||
|
||||
int SpellToSpellbookID(int nSpell)
|
||||
{
|
||||
object oWP = GetObjectByTag("PRC_GetRowFromSpellID");
|
||||
int nOutSpellID = GetLocalInt(oWP, /*"PRC_GetRowFromSpellID_" + */IntToString(nSpell));
|
||||
if(nOutSpellID == 0)
|
||||
nOutSpellID = -1;
|
||||
//if(DEBUG) DoDebug("SpellToSpellbookID(" + IntToString(nSpell) + ", " + sFile + ") = " + IntToString(nOutSpellID));
|
||||
return nOutSpellID;
|
||||
}
|
||||
|
||||
int RealSpellToSpellbookID(int nClass, int nSpell)
|
||||
{
|
||||
object oWP = GetObjectByTag("PRC_GetRowFromRealSpellID");
|
||||
int nOutSpellID = GetLocalInt(oWP, IntToString(nClass) + "_" + IntToString(nSpell) + "_Start");
|
||||
if(nOutSpellID == 0)
|
||||
nOutSpellID = -1;
|
||||
return nOutSpellID;
|
||||
}
|
||||
|
||||
int RealSpellToSpellbookIDCount(int nClass, int nSpell)
|
||||
{
|
||||
return GetLocalInt(GetObjectByTag("PRC_GetRowFromRealSpellID"), IntToString(nClass) + "_" + IntToString(nSpell) + "_Count");
|
||||
}
|
||||
|
||||
string GetAMSKnownFileName(int nClass)
|
||||
{
|
||||
// Get the class-specific base
|
||||
string sFile = Get2DACache("classes", "FeatsTable", nClass);
|
||||
|
||||
// Various naming schemes based on system
|
||||
if(nClass == CLASS_TYPE_TRUENAMER)
|
||||
sFile = "cls_true_known";
|
||||
// ToB
|
||||
else if(nClass == CLASS_TYPE_CRUSADER || nClass == CLASS_TYPE_SWORDSAGE || nClass == CLASS_TYPE_WARBLADE)
|
||||
sFile = "cls_mvkn" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
// Shadowcasting
|
||||
else if(nClass == CLASS_TYPE_SHADOWCASTER || nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
sFile = "cls_mykn" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
// Invocations
|
||||
else if(nClass == CLASS_TYPE_DRAGONFIRE_ADEPT || nClass == CLASS_TYPE_WARLOCK || nClass == CLASS_TYPE_DRAGON_SHAMAN)
|
||||
sFile = "cls_invkn" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
// Assume psionics if no other match
|
||||
else
|
||||
sFile = "cls_psbk" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
string GetAMSDefinitionFileName(int nClass)
|
||||
{
|
||||
// Get the class-specific base
|
||||
string sFile = Get2DACache("classes", "FeatsTable", nClass);
|
||||
|
||||
// Various naming schemes based on system
|
||||
if(nClass == CLASS_TYPE_TRUENAMER)
|
||||
sFile = "cls_true_utter";
|
||||
// ToB
|
||||
else if(nClass == CLASS_TYPE_CRUSADER || nClass == CLASS_TYPE_SWORDSAGE || nClass == CLASS_TYPE_WARBLADE)
|
||||
sFile = "cls_move" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
// Shadowcasting
|
||||
else if(nClass == CLASS_TYPE_SHADOWCASTER || nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
sFile = "cls_myst" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
// Invoc
|
||||
else if(nClass == CLASS_TYPE_DRAGONFIRE_ADEPT || nClass == CLASS_TYPE_WARLOCK || nClass == CLASS_TYPE_DRAGON_SHAMAN)
|
||||
sFile = "cls_inv" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
// Assume psionics if no other match
|
||||
else
|
||||
sFile = "cls_psipw" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061210
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
// Test main
|
||||
//void main(){}
|
||||
1255
trunk/users/Stratovarius/NWNEE Updates/inc_newspellbook.nss
Normal file
1255
trunk/users/Stratovarius/NWNEE Updates/inc_newspellbook.nss
Normal file
File diff suppressed because it is too large
Load Diff
376
trunk/users/Stratovarius/NWNEE Updates/inc_pers_array.nss
Normal file
376
trunk/users/Stratovarius/NWNEE Updates/inc_pers_array.nss
Normal file
@@ -0,0 +1,376 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Persistant array simulation include
|
||||
//:: inc_pers_array
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Persistant array simulation include
|
||||
|
||||
This file defines a set of functions for creating
|
||||
and manipulating persistant arrays, which are
|
||||
implemented as persistant local variables on some
|
||||
holder creature.
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
* Arrays are dynamic and may be increased in size by just _set_'ing a new
|
||||
element
|
||||
* There are no restrictions on what is in the array (can have multiple
|
||||
types in the same array)
|
||||
* Arrays start at index 0
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
// Functions
|
||||
/////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a new persistant array on the given storage creature.
|
||||
* If an array with the same name already exists, the function
|
||||
* errors.
|
||||
*
|
||||
* @param store The creature to use as holder for the array
|
||||
* @param name The name of the array
|
||||
* @return SDL_SUCCESS if the array was successfully created,
|
||||
* one of SDL_ERROR_* on error.
|
||||
*/
|
||||
int persistant_array_create(object store, string name);
|
||||
|
||||
/**
|
||||
* Deletes a persistant array, erasing all it's entries.
|
||||
*
|
||||
* @param store The creature which holds the array to delete
|
||||
* @param name The name of the array
|
||||
* @return SDL_SUCCESS if the array was successfully deleted,
|
||||
* one of SDL_ERROR_* on error
|
||||
*/
|
||||
int persistant_array_delete(object store, string name);
|
||||
|
||||
/**
|
||||
* Stores a string in a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to store the string at
|
||||
* @param entry The string to store
|
||||
* @return SDL_SUCCESS if the store was successfull, SDL_ERROR_* on error.
|
||||
*/
|
||||
int persistant_array_set_string(object store, string name, int i, string entry);
|
||||
|
||||
/**
|
||||
* Stores an integer in a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to store the integer at
|
||||
* @param entry The integer to store
|
||||
* @return SDL_SUCCESS if the store was successfull, SDL_ERROR_* on error.
|
||||
*/
|
||||
int persistant_array_set_int(object store, string name, int i, int entry);
|
||||
|
||||
/**
|
||||
* Stores a float in a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to store the float at
|
||||
* @param entry The float to store
|
||||
* @return SDL_SUCCESS if the store was successfull, SDL_ERROR_* on error.
|
||||
*/
|
||||
int persistant_array_set_float(object store, string name, int i, float entry);
|
||||
|
||||
/**
|
||||
* Stores an object in a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to store the object at
|
||||
* @param entry The object to store
|
||||
* @return SDL_SUCCESS if the store was successfull, SDL_ERROR_* on error.
|
||||
*/
|
||||
int persistant_array_set_object(object store, string name, int i, object entry);
|
||||
|
||||
/**
|
||||
* Gets a string from a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to retrieve the string from
|
||||
* @return The value contained at the index on success,
|
||||
* "" on error
|
||||
*/
|
||||
string persistant_array_get_string(object store, string name, int i);
|
||||
|
||||
/**
|
||||
* Gets an integer from a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to retrieve the integer from
|
||||
* @return The value contained at the index on success,
|
||||
* 0 on error
|
||||
*/
|
||||
int persistant_array_get_int(object store, string name, int i);
|
||||
|
||||
/**
|
||||
* Gets a float from a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to retrieve the float from
|
||||
* @return The value contained at the index on success,
|
||||
* 0.0f on error
|
||||
*/
|
||||
float persistant_array_get_float(object store, string name, int i);
|
||||
|
||||
/**
|
||||
* Gets an object from a persistant array.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param i The index to retrieve the object from
|
||||
* @return The value contained at the index on success,
|
||||
* OBJECT_INVALID on error
|
||||
*/
|
||||
object persistant_array_get_object(object store, string name, int i);
|
||||
|
||||
/**
|
||||
* Removes all entries in the array with indexes greater than or equal to
|
||||
* the new size and sets the array size to be equal to the new size.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @param size_new The new number of entries in the array
|
||||
* @return SDL_SUCCESS on successful resize, SDL_ERROR_* on
|
||||
* error
|
||||
*/
|
||||
int persistant_array_shrink(object store, string name, int size_new);
|
||||
|
||||
/**
|
||||
* Gets the current size of the array. This is one greater
|
||||
* than the index of highest indexed element the array
|
||||
* has contained since the last array_shrink or the new size
|
||||
* specified by the last array_shrink, whichever is greater.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @return The size of the array, or -1 if the specified
|
||||
* array does not exist.
|
||||
*/
|
||||
int persistant_array_get_size(object store, string name);
|
||||
|
||||
/**
|
||||
* Checks whether the given persistant array exists.
|
||||
*
|
||||
* @param store The creature holding the array
|
||||
* @param name The name of the array
|
||||
* @return TRUE if the array exists, FALSE otherwise.
|
||||
*/
|
||||
int persistant_array_exists(object store, string name);
|
||||
|
||||
/////////////////////////////////////
|
||||
// Includes
|
||||
/////////////////////////////////////
|
||||
|
||||
#include "inc_persist_loca"
|
||||
#include "inc_array" // yes this is also got via inc_persist_loca if rather indirectly
|
||||
|
||||
/////////////////////////////////////
|
||||
// Implementation
|
||||
/////////////////////////////////////
|
||||
|
||||
int persistant_array_create(object store, string name)
|
||||
{
|
||||
// error checking
|
||||
if(!GetIsObjectValid(store))
|
||||
return SDL_ERROR_NOT_VALID_OBJECT;
|
||||
else if(persistant_array_exists(store,name))
|
||||
return SDL_ERROR_ALREADY_EXISTS;
|
||||
else
|
||||
{
|
||||
// Initialize the size (always one greater than the actual size)
|
||||
SetPersistantLocalInt(store,name,1);
|
||||
return SDL_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
void persistant_array_delete_loop(object store, string name, int nMin, int nMax)
|
||||
{
|
||||
int i = nMin;
|
||||
while(i < nMin + 250 && i < nMax)
|
||||
{
|
||||
DeletePersistantLocalString(store,name+"_"+IntToString(i));
|
||||
|
||||
// just in case, delete possible object names
|
||||
DeletePersistantLocalObject(store,name+"_"+IntToString(i)+"_OBJECT");
|
||||
i++;
|
||||
}
|
||||
// delay continuation to avoid TMI
|
||||
if(i < nMax)
|
||||
DelayCommand(0.0, persistant_array_delete_loop(store, name, i, nMax));
|
||||
}
|
||||
|
||||
int persistant_array_delete(object store, string name)
|
||||
{
|
||||
// error checking
|
||||
int size=GetPersistantLocalInt(store,name);
|
||||
if (size==0)
|
||||
return SDL_ERROR_DOES_NOT_EXIST;
|
||||
|
||||
persistant_array_delete_loop(store, name, 0, size+5);
|
||||
|
||||
DeletePersistantLocalInt(store,name);
|
||||
|
||||
return SDL_SUCCESS;
|
||||
}
|
||||
|
||||
int persistant_array_set_string(object store, string name, int i, string entry)
|
||||
{
|
||||
int size=GetPersistantLocalInt(store,name);
|
||||
if(size == 0)
|
||||
return SDL_ERROR_DOES_NOT_EXIST;
|
||||
if(i < 0)
|
||||
return SDL_ERROR_OUT_OF_BOUNDS;
|
||||
|
||||
SetPersistantLocalString(store,name+"_"+IntToString(i),entry);
|
||||
|
||||
// save size if we've enlarged it
|
||||
if (i+2>size)
|
||||
SetPersistantLocalInt(store,name,i+2);
|
||||
|
||||
return SDL_SUCCESS;
|
||||
}
|
||||
|
||||
int persistant_array_set_int(object store, string name, int i, int entry)
|
||||
{
|
||||
return persistant_array_set_string(store,name,i,IntToString(entry));
|
||||
}
|
||||
|
||||
int persistant_array_set_float(object store, string name, int i, float entry)
|
||||
{
|
||||
return persistant_array_set_string(store,name,i,FloatToString(entry));
|
||||
}
|
||||
|
||||
int persistant_array_set_object(object store, string name, int i, object entry)
|
||||
{
|
||||
// object is a little more complicated.
|
||||
// we want to create an object as a local variable too
|
||||
if (!GetIsObjectValid(entry))
|
||||
return SDL_ERROR_NOT_VALID_OBJECT;
|
||||
|
||||
int results = persistant_array_set_string(store,name,i,"OBJECT");
|
||||
if (results==SDL_SUCCESS)
|
||||
SetPersistantLocalObject(store,name+"_"+IntToString(i)+"_OBJECT",entry);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
string persistant_array_get_string(object store, string name, int i)
|
||||
{
|
||||
// error checking
|
||||
int size=GetPersistantLocalInt(store,name);
|
||||
if (size==0 || i>size || i < 0)
|
||||
return "";
|
||||
|
||||
return GetPersistantLocalString(store,name+"_"+IntToString(i));
|
||||
}
|
||||
|
||||
int persistant_array_get_int(object store, string name, int i)
|
||||
{
|
||||
return StringToInt(persistant_array_get_string(store,name,i));
|
||||
}
|
||||
|
||||
float persistant_array_get_float(object store, string name, int i)
|
||||
{
|
||||
return StringToFloat(persistant_array_get_string(store,name,i));
|
||||
}
|
||||
|
||||
object persistant_array_get_object(object store, string name, int i)
|
||||
{
|
||||
if(persistant_array_get_string(store, name, i) == "OBJECT")
|
||||
return GetPersistantLocalObject(store,name+"_"+IntToString(i)+"_OBJECT");
|
||||
else
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
int persistant_array_shrink(object store, string name, int size_new)
|
||||
{
|
||||
// Get the current size value
|
||||
int size = GetPersistantLocalInt(store, name);
|
||||
// Error check - non-existent array
|
||||
if(size == 0)
|
||||
return SDL_ERROR_DOES_NOT_EXIST;
|
||||
// If the new number of elements is equal to or greater than the current number of elements, autosuccess
|
||||
if((size - 1) <= size_new)
|
||||
return SDL_SUCCESS;
|
||||
|
||||
// Delete entries that are outside the new array bounds
|
||||
int i;
|
||||
for(i = size_new; i < size; i++)
|
||||
{
|
||||
DeletePersistantLocalString(store, name+"_"+IntToString(i));
|
||||
|
||||
// just in case, delete possible object names
|
||||
DeletePersistantLocalObject(store, name+"_"+IntToString(i)+"_OBJECT");
|
||||
}
|
||||
|
||||
// Store the new size, with the +1 existence marker
|
||||
SetPersistantLocalInt(store, name, size_new + 1);
|
||||
|
||||
return SDL_SUCCESS;
|
||||
}
|
||||
|
||||
int persistant_array_get_size(object store, string name)
|
||||
{
|
||||
return GetPersistantLocalInt(store,name)-1;
|
||||
}
|
||||
|
||||
int persistant_array_exists(object store, string name)
|
||||
{
|
||||
if (GetPersistantLocalInt(store,name))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int IsIntSet(object oPC, string sArray, int nValue)
|
||||
{
|
||||
int nReturn = FALSE;
|
||||
// Run a loop to check if the value is set anywhere in this array
|
||||
int i;
|
||||
for(i = 0; i =< persistant_array_get_size(oPC, sArray); i++)
|
||||
{
|
||||
int nCheck = persistant_array_get_int(oPC, sArray, i);
|
||||
if (nCheck == nValue)
|
||||
{
|
||||
nReturn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nReturn;
|
||||
}
|
||||
|
||||
int IsStringSet(object oPC, string sArray, string sValue)
|
||||
{
|
||||
int nReturn = FALSE;
|
||||
// Run a loop to check if the value is set anywhere in this array
|
||||
int i;
|
||||
for(i = 0; i =< persistant_array_get_size(oPC, sArray); i++)
|
||||
{
|
||||
string sCheck = persistant_array_get_string(oPC, sArray, i);
|
||||
if (sCheck == sValue)
|
||||
{
|
||||
nReturn = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nReturn;
|
||||
}
|
||||
|
||||
// Test main
|
||||
//void main(){}
|
||||
361
trunk/users/Stratovarius/NWNEE Updates/inc_sp_gain_mem.nss
Normal file
361
trunk/users/Stratovarius/NWNEE Updates/inc_sp_gain_mem.nss
Normal file
@@ -0,0 +1,361 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name: new spellbook spellgain / spell memorization include
|
||||
//:: File: inc_sp_gain_mem.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/**
|
||||
contains helper functions for the two dynamic conversation scripts
|
||||
- prc_s_spellb.nss
|
||||
- prc_s_spellgain.nss
|
||||
that handle learning / gaining new spells at level up (prc_s_spellgain)
|
||||
or preparing what spells to learn at next rest (prc_s_spellb)
|
||||
|
||||
Author: motu99
|
||||
Created: May 1, 2008
|
||||
*/
|
||||
|
||||
//#include "prc_inc_core" //granted access via parent (inc_newspellbook)
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Constants
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
// max. number of classes a PC (or creature) can take (3 for NWN, 4 for NWN2)
|
||||
const int MAX_CLASSES = 3;
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Aid functions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
string GetNSBDefinitionFileName(int nClass);
|
||||
int GetCasterLevelByClass(int nClass, object oPC);
|
||||
|
||||
int GetSpellsKnown_MaxCount(int nCasterLevel, int nClass, int nSpellLevel, object oPC);
|
||||
int GetSpellsInClassSpellbook_Count(int nClass, int nSpellLevel);
|
||||
string GetClassString(int nClass);
|
||||
int GetMaxSpellLevelForCasterLevel(int nClass, int nCasterLevel);
|
||||
int GetMinSpellLevelForCasterLevel(int nClass, int nCasterLevel);
|
||||
|
||||
void WipeSpellFromHide(int nIPFeatID, object oPC);
|
||||
|
||||
string GetSpellsKnown_Array(int nClass, int nSpellLevel = -1);
|
||||
object GetSpellsOfClass_Token(int nClass, int nSpellLevel);
|
||||
string GetSpellsOfClass_Array();
|
||||
string GetSpellsMemorized_Array(int nClass);
|
||||
string GetSpellsToBeMemorized_Array(int nClass, int nSpellSlotLevel);
|
||||
|
||||
void array_set_size(object oToken, string sArrayName, int nSize);
|
||||
int array_has_string(object oToken, string sArrayName, string sValue, int nFirst = 0, int nSize = 0);
|
||||
int array_has_int(object oToken, string sArrayName, int nValue, int nFirst = 0, int nSize = 0);
|
||||
int persistant_array_has_string(object oToken, string sArrayName, string sValue, int nFirst = 0, int nSize = 0);
|
||||
int persistant_array_has_int(object oToken, string sArrayName, int nValue, int nFirst = 0, int nSize = 0);
|
||||
int array_extract_string(object oToken, string sArrayName, string sValue, int nFirst = 0);
|
||||
int array_extract_int(object oToken, string sArrayName, int nValue, int nFirst = 0);
|
||||
int persistant_array_extract_string(object oPC, string sArrayName, string sValue, int nFirst = 0);
|
||||
int persistant_array_extract_int(object oPC, string sArrayName, int nValue, int nFirst = 0);
|
||||
|
||||
string GetMetaMagicString_Short(int nMetaMagic);
|
||||
string GetMetaMagicString(int nMetaMagic);
|
||||
int GetMetaMagicFromFeat(int nFeat);
|
||||
int GetMetaMagicOfCaster(object oPC = OBJECT_SELF);
|
||||
|
||||
// name of the new spellbook file (cls_spell_*)
|
||||
string GetNSBDefinitionFileName(int nClass)
|
||||
{
|
||||
return GetFileForClass(nClass);
|
||||
}
|
||||
|
||||
// gets the caster level (without special modifications due to feats), by which the max spell slot level is determined
|
||||
int GetCasterLevelByClass(int nClass, object oPC)
|
||||
{
|
||||
return GetSpellslotLevel(nClass, oPC);
|
||||
// return GetPrCAdjustedCasterLevel(nClass, oPC, TRUE);
|
||||
}
|
||||
|
||||
// gets the maximum nr of spells that oPC can know with a given nCasterLevel, nClass and nSpellLevel
|
||||
int GetSpellsKnown_MaxCount(int nCasterLevel, int nClass, int nSpellLevel, object oPC)
|
||||
{
|
||||
return GetSpellKnownMaxCount(nCasterLevel, nSpellLevel, nClass, oPC);
|
||||
}
|
||||
|
||||
|
||||
// gets the total nr of spells available at nSpellLevel for nClass
|
||||
int GetSpellsInClassSpellbook_Count(int nClass, int nSpellLevel)
|
||||
{
|
||||
return array_get_size(GetSpellsOfClass_Token(nClass, nSpellLevel), GetSpellsOfClass_Array());
|
||||
}
|
||||
|
||||
string GetClassString(int nClass)
|
||||
{
|
||||
// get the name of the feats table 2da
|
||||
string sClass = Get2DACache("classes", "FeatsTable", nClass);
|
||||
// truncate the first 8 characters (the "cls_feat" part), leaving the "_<class>" part
|
||||
sClass = GetStringRight(sClass, GetStringLength(sClass) - 8);
|
||||
return sClass;
|
||||
}
|
||||
|
||||
// gets the maximum spell level that nClass can cast at nCasterLevel
|
||||
int GetMaxSpellLevelForCasterLevel(int nClass, int nCasterLevel)
|
||||
{
|
||||
string sFile;
|
||||
// Bioware casters use their classes.2da-specified tables
|
||||
//if(GetIsBioSpellCastClass(nClass))
|
||||
//{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// sFile = "cls_spbk" + GetClassString(nClass);
|
||||
//}
|
||||
|
||||
// row nr in the files is nCasterLevel minus 1
|
||||
nCasterLevel--;
|
||||
int nSpellLevel;
|
||||
|
||||
if (Get2DACache(sFile, "NumSpellLevels", 9) != "")
|
||||
{
|
||||
string sTemp = Get2DACache(sFile, "NumSpellLevels", nCasterLevel);
|
||||
if (sTemp != "")
|
||||
{
|
||||
nSpellLevel = StringToInt(sTemp)-1;
|
||||
if (nSpellLevel <= 0) nSpellLevel = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (nSpellLevel=9; nSpellLevel >= 0; nSpellLevel--)
|
||||
{
|
||||
string sTemp = Get2DACache(sFile, "SpellLevel" + IntToString(nSpellLevel), nCasterLevel);
|
||||
if (sTemp != "")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nSpellLevel;
|
||||
}
|
||||
|
||||
// gets the minimum spell level that nClass can cast at nCasterLevel
|
||||
int GetMinSpellLevelForCasterLevel(int nClass, int nCasterLevel)
|
||||
{
|
||||
string sFile;
|
||||
// Bioware casters use their classes.2da-specified tables
|
||||
//if(GetIsBioSpellCastClass(nClass))
|
||||
//{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// sFile = "cls_spbk" + GetClassString(nClass);
|
||||
//}
|
||||
|
||||
// row nr in the files is nCasterLevel minus 1
|
||||
nCasterLevel--;
|
||||
|
||||
int bFound = 0;
|
||||
|
||||
int nSpellLevel;
|
||||
for (nSpellLevel=0; nSpellLevel <= 9; nSpellLevel++)
|
||||
{
|
||||
string sTemp = Get2DACache(sFile, "SpellLevel" + IntToString(nSpellLevel), nCasterLevel);
|
||||
if (sTemp != "")
|
||||
{
|
||||
bFound = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bFound) nSpellLevel = -1;
|
||||
return nSpellLevel;
|
||||
}
|
||||
|
||||
// wipes the IPbonusfeat from the hide
|
||||
void WipeSpellFromHide(int nIPFeatID, object oPC)
|
||||
{
|
||||
// go through all item properties on the hide
|
||||
object oHide = GetPCSkin(oPC);
|
||||
itemproperty ipTest = GetFirstItemProperty(oHide);
|
||||
while(GetIsItemPropertyValid(ipTest))
|
||||
{
|
||||
// is it a bonus feat?
|
||||
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_BONUS_FEAT)
|
||||
{
|
||||
// get the row nr of the bonus feat in iprp_feat.2da
|
||||
// is it the ipfeat to delete?
|
||||
if (GetItemPropertySubType(ipTest) == nIPFeatID)
|
||||
{
|
||||
RemoveItemProperty(oHide, ipTest);
|
||||
if(DEBUG) DoDebug("WipeSpellFromHide: Removing item property " + DebugIProp2Str(ipTest));
|
||||
}
|
||||
}
|
||||
ipTest = GetNextItemProperty(oHide);
|
||||
}
|
||||
}
|
||||
|
||||
// one array for each class (array holds all spell levels, but only non-metamagicked masterspells)
|
||||
string GetSpellsKnown_Array(int nClass, int nSpellLevel = -1)
|
||||
{
|
||||
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
||||
if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
|
||||
return "Spellbook_Known_" + IntToString(nClass) + "_" + IntToString(nSpellLevel);
|
||||
return "Spellbook" + IntToString(nClass);
|
||||
}
|
||||
|
||||
// class spellbook (one storage token for each spell level and class)
|
||||
object GetSpellsOfClass_Token(int nClass, int nSpellLevel)
|
||||
{
|
||||
return GetObjectByTag("SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nSpellLevel));
|
||||
}
|
||||
|
||||
string GetSpellsOfClass_Array()
|
||||
{
|
||||
return "Lkup";
|
||||
}
|
||||
|
||||
string GetSpellsMemorized_Array(int nClass)
|
||||
{
|
||||
return "NewSpellbookMem_" + IntToString(nClass);
|
||||
}
|
||||
|
||||
string GetSpellsToBeMemorized_Array(int nClass, int nSpellSlotLevel)
|
||||
{
|
||||
return "Spellbook" + IntToString(nSpellSlotLevel) + "_" + IntToString(nClass);
|
||||
}
|
||||
|
||||
|
||||
void array_set_size(object oToken, string sArrayName, int nSize)
|
||||
{
|
||||
SetLocalInt(oToken, sArrayName, nSize+1);
|
||||
}
|
||||
|
||||
int array_has_string(object oToken, string sArrayName, string sValue, int nFirst = 0, int nSize = 0)
|
||||
{
|
||||
// get array size, if size not already supplied
|
||||
if (nSize == 0) nSize = GetLocalInt(oToken, sArrayName) -1;
|
||||
int i;
|
||||
|
||||
for (i = nFirst; i < nSize; i++)
|
||||
{
|
||||
if (sValue == GetLocalString(oToken, sArrayName + "_" + IntToString(i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int array_has_int(object oToken, string sArrayName, int nValue, int nFirst = 0, int nSize = 0)
|
||||
{
|
||||
// array values are stored as strings, so convert nValue to a string
|
||||
return array_has_string(oToken, sArrayName, IntToString(nValue), nFirst, nSize);
|
||||
}
|
||||
|
||||
int persistant_array_has_string(object oPC, string sArrayName, string sValue, int nFirst = 0, int nSize = 0)
|
||||
{
|
||||
return array_has_string(GetHideToken(oPC), sArrayName, sValue, nFirst, nSize);
|
||||
}
|
||||
|
||||
int persistant_array_has_int(object oPC, string sArrayName, int nValue, int nFirst = 0, int nSize = 0)
|
||||
{
|
||||
return array_has_string(GetHideToken(oPC), sArrayName, IntToString(nValue), nFirst, nSize);
|
||||
}
|
||||
|
||||
int array_extract_string(object oToken, string sArrayName, string sValue, int nFirst = 0)
|
||||
{
|
||||
// get array size
|
||||
int nSize = SQLocals_GetInt(oToken, sArrayName)-1;
|
||||
if (nSize <= nFirst) return -1;
|
||||
|
||||
// position of the first found; -1 if not found
|
||||
int nPos = IsStringSet(oToken, sArrayName, sValue);
|
||||
if (nPos < 0) return -1;
|
||||
|
||||
// Is is not the last element?
|
||||
if (nPos < nSize-1)
|
||||
{
|
||||
// then swap nPos (or rather nPos-1) with the last element (nSize-1)
|
||||
string sTemp = SQLocals_GetString(oToken, sArrayName + "_" + IntToString(nSize-1));
|
||||
SQLocals_SetString(oToken, sArrayName + "_" + IntToString(nPos), sTemp);
|
||||
}
|
||||
|
||||
// now decrement the array size (note that we already subtracted one in the beginning)
|
||||
SQLocals_SetInt(oToken, sArrayName, nSize);
|
||||
|
||||
return nPos;
|
||||
}
|
||||
|
||||
// extracts the integer value nValue from a persistant sArray on oPC
|
||||
// extracts the first instance of nValue that it finds
|
||||
// extracts it by swapping the last array element to the position of the extracted element and reducing the array size by one
|
||||
// returns the position where the extracted element was found
|
||||
int array_extract_int(object oToken, string sArrayName, int nValue, int nFirst = 0)
|
||||
{
|
||||
// array values are stored as strings, so convert nValue to a string
|
||||
return array_extract_string(oToken, sArrayName, IntToString(nValue), nFirst);
|
||||
}
|
||||
|
||||
int persistant_array_extract_string(object oPC, string sArrayName, string sValue, int nFirst = 0)
|
||||
{
|
||||
return array_extract_string(GetHideToken(oPC), sArrayName, sValue, nFirst);
|
||||
}
|
||||
|
||||
int persistant_array_extract_int(object oPC, string sArrayName, int nValue, int nFirst = 0)
|
||||
{
|
||||
// array values are stored as strings, so convert nValue to a string
|
||||
return array_extract_string(GetHideToken(oPC), sArrayName, IntToString(nValue), nFirst);
|
||||
}
|
||||
|
||||
string GetMetaMagicString_Short(int nMetaMagic)
|
||||
{
|
||||
string s;
|
||||
if (nMetaMagic == 0) return s;
|
||||
|
||||
if (nMetaMagic & METAMAGIC_EXTEND) s += "ext ";
|
||||
if (nMetaMagic & METAMAGIC_SILENT) s += "sil ";
|
||||
if (nMetaMagic & METAMAGIC_STILL) s += "sti ";
|
||||
if (nMetaMagic & METAMAGIC_EMPOWER) s += "emp ";
|
||||
if (nMetaMagic & METAMAGIC_MAXIMIZE) s += "max ";
|
||||
if (nMetaMagic & METAMAGIC_QUICKEN) s += "qui ";
|
||||
|
||||
return GetStringLeft(s, GetStringLength(s)-1);
|
||||
}
|
||||
|
||||
string GetMetaMagicString(int nMetaMagic)
|
||||
{
|
||||
string s;
|
||||
if (nMetaMagic == 0) return s;
|
||||
|
||||
if (nMetaMagic & METAMAGIC_EXTEND) s += "extend ";
|
||||
if (nMetaMagic & METAMAGIC_SILENT) s += "silent ";
|
||||
if (nMetaMagic & METAMAGIC_STILL) s += "still ";
|
||||
if (nMetaMagic & METAMAGIC_EMPOWER) s += "empower ";
|
||||
if (nMetaMagic & METAMAGIC_MAXIMIZE) s += "maximize ";
|
||||
if (nMetaMagic & METAMAGIC_QUICKEN) s += "quicken ";
|
||||
|
||||
return GetStringLeft(s, GetStringLength(s)-1);
|
||||
}
|
||||
|
||||
int GetMetaMagicFromFeat(int nFeat)
|
||||
{
|
||||
switch(nFeat)
|
||||
{
|
||||
case FEAT_EMPOWER_SPELL: return METAMAGIC_EMPOWER;
|
||||
case FEAT_EXTEND_SPELL: return METAMAGIC_EXTEND;
|
||||
case FEAT_MAXIMIZE_SPELL: return METAMAGIC_MAXIMIZE;
|
||||
case FEAT_QUICKEN_SPELL: return METAMAGIC_QUICKEN;
|
||||
case FEAT_SILENCE_SPELL: return METAMAGIC_SILENT;
|
||||
case FEAT_STILL_SPELL: return METAMAGIC_STILL;
|
||||
}
|
||||
return METAMAGIC_NONE;
|
||||
}
|
||||
|
||||
int GetMetaMagicOfCaster(object oPC = OBJECT_SELF)
|
||||
{
|
||||
int nMetaMagic;
|
||||
|
||||
if (GetHasFeat(FEAT_EMPOWER_SPELL, oPC)) nMetaMagic |= METAMAGIC_EMPOWER;
|
||||
if (GetHasFeat(FEAT_EXTEND_SPELL, oPC)) nMetaMagic |= METAMAGIC_EXTEND;
|
||||
if (GetHasFeat(FEAT_MAXIMIZE_SPELL, oPC)) nMetaMagic |= METAMAGIC_MAXIMIZE;
|
||||
if (GetHasFeat(FEAT_QUICKEN_SPELL, oPC)) nMetaMagic |= METAMAGIC_QUICKEN;
|
||||
if (GetHasFeat(FEAT_SILENCE_SPELL, oPC)) nMetaMagic |= METAMAGIC_SILENT;
|
||||
if (GetHasFeat(FEAT_STILL_SPELL, oPC)) nMetaMagic |= METAMAGIC_STILL;
|
||||
|
||||
return nMetaMagic;
|
||||
}
|
||||
650
trunk/users/Stratovarius/NWNEE Updates/inc_sqllocals.nss
Normal file
650
trunk/users/Stratovarius/NWNEE Updates/inc_sqllocals.nss
Normal file
@@ -0,0 +1,650 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Utility Include: SQLocals
|
||||
//:: inc_layo_sqlite.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
Daz wrote these library functions to act as replacements for the usual local
|
||||
functions:
|
||||
* GetLocalInt / SetLocalInt / DeleteLocalInt
|
||||
* GetLocalFloat / SetLocalFloat / DeleteLocalFloat
|
||||
* GetLocalString / SetLocalString / DeleteLocalString
|
||||
* GetLocalObject / SetLocalObject / DeleteLocalObject (NB: remember these are references NOT serialised objects)
|
||||
* GetLocalLocation / SetLocalLocation / DeleteLocalLocation
|
||||
* Plus a new function for saving just a vector by itself.
|
||||
Since sometimes iterating over many locals is slow, this might be an excellent way to
|
||||
speed up large amounts of access, or for debugging, or using regex or whatever else.
|
||||
These are functions for PC Object persistence.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Based off of the nwscript_utility_scripts project; see for dates/creator info
|
||||
//:: https://github.com/Finaldeath/nwscript_utility_scripts
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
const string SQLOCALS_TABLE_NAME = "prc_sqlocals_table";
|
||||
|
||||
const int SQLOCALS_TYPE_ALL = 0;
|
||||
const int SQLOCALS_TYPE_INT = 1;
|
||||
const int SQLOCALS_TYPE_FLOAT = 2;
|
||||
const int SQLOCALS_TYPE_STRING = 4;
|
||||
const int SQLOCALS_TYPE_OBJECT = 8;
|
||||
const int SQLOCALS_TYPE_VECTOR = 16;
|
||||
const int SQLOCALS_TYPE_LOCATION = 32;
|
||||
|
||||
// Returns an integer stored on oObject, or 0 on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
int SQLocals_GetInt(object oObject, string sVarName);
|
||||
// Sets an integer stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nValue - Value to store
|
||||
void SQLocals_SetInt(object oObject, string sVarName, int nValue);
|
||||
// Deletes an integer stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteInt(object oObject, string sVarName);
|
||||
|
||||
// Returns a float stored on oObject, or 0.0 on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
float SQLocals_GetFloat(object oObject, string sVarName);
|
||||
// Sets a float stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * fValue - Value to store
|
||||
void SQLocals_SetFloat(object oObject, string sVarName, float fValue);
|
||||
// Deletes a float stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteFloat(object oObject, string sVarName);
|
||||
|
||||
// Returns an string stored on oObject, or "" on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
string SQLocals_GetString(object oObject, string sVarName);
|
||||
// Sets a string stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * sValue - Value to store
|
||||
void SQLocals_SetString(object oObject, string sVarName, string sValue);
|
||||
// Deletes a string stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteString(object oObject, string sVarName);
|
||||
|
||||
// Returns an object identifier stored on oObject
|
||||
// If this is used on a player it might return a "once valid" OID, so check
|
||||
// with GetIsObjectValid, do not compare to OBJECT_INVALID.
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
object SQLocals_GetObject(object oObject, string sVarName);
|
||||
// Sets an object identifier stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * oValue - Value to store
|
||||
void SQLocals_SetObject(object oObject, string sVarName, object oValue);
|
||||
// Deletes an object identifier stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteObject(object oObject, string sVarName);
|
||||
|
||||
// Returns a vector stored on oObject, or [0.0, 0.0, 0.0] on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
vector SQLocals_GetVector(object oObject, string sVarName);
|
||||
// Sets a vector stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * vValue - Value to store
|
||||
void SQLocals_SetVector(object oObject, string sVarName, vector vValue);
|
||||
// Deletes a vector stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteVector(object oObject, string sVarName);
|
||||
|
||||
// Returns a location stored on oObject, or the starting location of the module on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
location SQLocals_GetLocation(object oObject, string sVarName);
|
||||
// Sets a location stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * lValue - Value to store
|
||||
void SQLocals_SetLocation(object oObject, string sVarName, location lValue);
|
||||
// Deletes a location stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteLocation(object oObject, string sVarName);
|
||||
|
||||
// Deletes a set of locals stored on oObject matching the given criteria
|
||||
// * oObject - an object to reference against
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
// * sLike - The string to compare with the SQL "like" comparison
|
||||
// * sEscape - The escape character to use with the SQL "escape" keyword
|
||||
void SQLocals_Delete(object oObject, int nType = SQLOCALS_TYPE_ALL, string sLike = "", string sEscape = "");
|
||||
// Counts a set of locals stored on oObject matching the given criteria
|
||||
// * oObject - an object to reference against
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
// * sLike - The string to compare with the SQL "like" comparison
|
||||
// * sEscape - The escape character to use with the SQL "escape" keyword
|
||||
int SQLocals_Count(object oObject, int nType = SQLOCALS_TYPE_ALL, string sLike = "", string sEscape = "");
|
||||
// Checks a locals stored on oObject is set
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
int SQLocals_IsSet(object oObject, string sVarName, int nType);
|
||||
// Returns the last Unix time the given variable was updated
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
int SQLocals_GetLastUpdated_UnixEpoch(object oObject, string sVarName, int nType);
|
||||
// Returns the last UTC time the given variable was updated
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
string SQLocals_GetLastUpdated_UTC(object oObject, string sVarName, int nType);
|
||||
|
||||
|
||||
/* INTERNAL */
|
||||
void SQLocals_CreateTable(object oObject)
|
||||
{
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"CREATE TABLE IF NOT EXISTS " + SQLOCALS_TABLE_NAME + " (" +
|
||||
"type INTEGER, " +
|
||||
"varname TEXT, " +
|
||||
"value TEXT, " +
|
||||
"timestamp INTEGER, " +
|
||||
"PRIMARY KEY(type, varname));");
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
sqlquery SQLocals_PrepareSelect(object oObject, int nType, string sVarName)
|
||||
{
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"SELECT value FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE type = @type AND varname = @varname;");
|
||||
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
SqlBindString(sql, "@varname", sVarName);
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
sqlquery SQLocals_PrepareInsert(object oObject, int nType, string sVarName)
|
||||
{
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"INSERT INTO " + SQLOCALS_TABLE_NAME + " " +
|
||||
"(type, varname, value, timestamp) VALUES (@type, @varname, @value, strftime('%s','now')) " +
|
||||
"ON CONFLICT (type, varname) DO UPDATE SET value = @value, timestamp = strftime('%s','now');");
|
||||
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
SqlBindString(sql, "@varname", sVarName);
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
sqlquery SQLocals_PrepareDelete(object oObject, int nType, string sVarName)
|
||||
{
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"DELETE FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE type = @type AND varname = @varname;");
|
||||
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
SqlBindString(sql, "@varname", sVarName);
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
string SQLocals_LocationToString(location locLocation)
|
||||
{
|
||||
string sAreaId = ObjectToString(GetAreaFromLocation(locLocation));
|
||||
vector vPosition = GetPositionFromLocation(locLocation);
|
||||
float fFacing = GetFacingFromLocation(locLocation);
|
||||
|
||||
return "#A#" + sAreaId +
|
||||
"#X#" + FloatToString(vPosition.x, 0, 5) +
|
||||
"#Y#" + FloatToString(vPosition.y, 0, 5) +
|
||||
"#Z#" + FloatToString(vPosition.z, 0, 5) +
|
||||
"#F#" + FloatToString(fFacing, 0, 5) + "#";
|
||||
}
|
||||
|
||||
location SQLocals_StringToLocation(string sLocation)
|
||||
{
|
||||
location locLocation;
|
||||
|
||||
int nLength = GetStringLength(sLocation);
|
||||
|
||||
if(nLength > 0)
|
||||
{
|
||||
int nPos, nCount;
|
||||
|
||||
nPos = FindSubString(sLocation, "#A#") + 3;
|
||||
nCount = FindSubString(GetSubString(sLocation, nPos, nLength - nPos), "#");
|
||||
object oArea = StringToObject(GetSubString(sLocation, nPos, nCount));
|
||||
|
||||
nPos = FindSubString(sLocation, "#X#") + 3;
|
||||
nCount = FindSubString(GetSubString(sLocation, nPos, nLength - nPos), "#");
|
||||
float fX = StringToFloat(GetSubString(sLocation, nPos, nCount));
|
||||
|
||||
nPos = FindSubString(sLocation, "#Y#") + 3;
|
||||
nCount = FindSubString(GetSubString(sLocation, nPos, nLength - nPos), "#");
|
||||
float fY = StringToFloat(GetSubString(sLocation, nPos, nCount));
|
||||
|
||||
nPos = FindSubString(sLocation, "#Z#") + 3;
|
||||
nCount = FindSubString(GetSubString(sLocation, nPos, nLength - nPos), "#");
|
||||
float fZ = StringToFloat(GetSubString(sLocation, nPos, nCount));
|
||||
|
||||
vector vPosition = Vector(fX, fY, fZ);
|
||||
|
||||
nPos = FindSubString(sLocation, "#F#") + 3;
|
||||
nCount = FindSubString(GetSubString(sLocation, nPos, nLength - nPos), "#");
|
||||
float fOrientation = StringToFloat(GetSubString(sLocation, nPos, nCount));
|
||||
|
||||
if (GetIsObjectValid(oArea))
|
||||
locLocation = Location(oArea, vPosition, fOrientation);
|
||||
else
|
||||
locLocation = GetStartingLocation();
|
||||
}
|
||||
|
||||
return locLocation;
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* INT */
|
||||
|
||||
// Returns an integer stored on oObject, or 0 on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
int SQLocals_GetInt(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return 0;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareSelect(oObject, SQLOCALS_TYPE_INT, sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetInt(sql, 0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sets an integer stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nValue - Value to store
|
||||
void SQLocals_SetInt(object oObject, string sVarName, int nValue)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareInsert(oObject, SQLOCALS_TYPE_INT, sVarName);
|
||||
SqlBindInt(sql, "@value", nValue);
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Deletes an integer stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteInt(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareDelete(oObject, SQLOCALS_TYPE_INT, sVarName);
|
||||
SqlStep(sql);
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* FLOAT */
|
||||
|
||||
// Returns a float stored on oObject, or 0.0 on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
float SQLocals_GetFloat(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return 0.0f;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareSelect(oObject, SQLOCALS_TYPE_FLOAT, sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetFloat(sql, 0);
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Sets a float stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * fValue - Value to store
|
||||
void SQLocals_SetFloat(object oObject, string sVarName, float fValue)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareInsert(oObject, SQLOCALS_TYPE_FLOAT, sVarName);
|
||||
SqlBindFloat(sql, "@value", fValue);
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Deletes a float stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteFloat(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareDelete(oObject, SQLOCALS_TYPE_FLOAT, sVarName);
|
||||
SqlStep(sql);
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* STRING */
|
||||
|
||||
// Returns an string stored on oObject, or "" on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
string SQLocals_GetString(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return "";
|
||||
|
||||
sqlquery sql = SQLocals_PrepareSelect(oObject, SQLOCALS_TYPE_STRING, sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetString(sql, 0);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
// Sets a string stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * sValue - Value to store
|
||||
void SQLocals_SetString(object oObject, string sVarName, string sValue)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareInsert(oObject, SQLOCALS_TYPE_STRING, sVarName);
|
||||
SqlBindString(sql, "@value", sValue);
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Deletes a string stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteString(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareDelete(oObject, SQLOCALS_TYPE_STRING, sVarName);
|
||||
SqlStep(sql);
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* OBJECT */
|
||||
|
||||
|
||||
// Returns an object identifier stored on oObject
|
||||
// If this is used on a player it might return a "once valid" OID, so check
|
||||
// with GetIsObjectValid, do not compare to OBJECT_INVALID.
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
object SQLocals_GetObject(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return OBJECT_INVALID;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareSelect(oObject, SQLOCALS_TYPE_OBJECT, sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return StringToObject(SqlGetString(sql, 0));
|
||||
else
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
// Sets an object identifier stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * oValue - Value to store
|
||||
void SQLocals_SetObject(object oObject, string sVarName, object oValue)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareInsert(oObject, SQLOCALS_TYPE_OBJECT, sVarName);
|
||||
SqlBindString(sql, "@value", ObjectToString(oValue));
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Deletes an object identifier stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteObject(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareDelete(oObject, SQLOCALS_TYPE_OBJECT, sVarName);
|
||||
SqlStep(sql);
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* VECTOR */
|
||||
|
||||
// Returns a vector stored on oObject, or [0.0, 0.0, 0.0] on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
vector SQLocals_GetVector(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return [0.0f, 0.0f, 0.0f];
|
||||
|
||||
sqlquery sql = SQLocals_PrepareSelect(oObject, SQLOCALS_TYPE_VECTOR, sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetVector(sql, 0);
|
||||
else
|
||||
return [0.0f, 0.0f, 0.0f];
|
||||
}
|
||||
|
||||
// Sets a vector stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * vValue - Value to store
|
||||
void SQLocals_SetVector(object oObject, string sVarName, vector vValue)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareInsert(oObject, SQLOCALS_TYPE_VECTOR, sVarName);
|
||||
SqlBindVector(sql, "@value", vValue);
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Deletes a vector stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteVector(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareDelete(oObject, SQLOCALS_TYPE_VECTOR, sVarName);
|
||||
SqlStep(sql);
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* LOCATION */
|
||||
|
||||
// Returns a location stored on oObject, or the starting location of the module on error
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
location SQLocals_GetLocation(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return GetStartingLocation();
|
||||
|
||||
sqlquery sql = SQLocals_PrepareSelect(oObject, SQLOCALS_TYPE_LOCATION, sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SQLocals_StringToLocation(SqlGetString(sql, 0));
|
||||
else
|
||||
return GetStartingLocation();
|
||||
}
|
||||
|
||||
// Sets a location stored on oObject to the given value
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * lValue - Value to store
|
||||
void SQLocals_SetLocation(object oObject, string sVarName, location lValue)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareInsert(oObject, SQLOCALS_TYPE_LOCATION, sVarName);
|
||||
SqlBindString(sql, "@value", SQLocals_LocationToString(lValue));
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Deletes a location stored on oObject
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to delete
|
||||
void SQLocals_DeleteLocation(object oObject, string sVarName)
|
||||
{
|
||||
if (!GetIsPC(oObject) || sVarName == "") return;
|
||||
|
||||
sqlquery sql = SQLocals_PrepareDelete(oObject, SQLOCALS_TYPE_LOCATION, sVarName);
|
||||
SqlStep(sql);
|
||||
}
|
||||
/* **** */
|
||||
|
||||
/* UTILITY */
|
||||
|
||||
// Deletes a set of locals stored on oObject matching the given criteria
|
||||
// * oObject - an object to reference against
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
// * sLike - The string to compare with the SQL "like" comparison
|
||||
// * sEscape - The escape character to use with the SQL "escape" keyword
|
||||
void SQLocals_Delete(object oObject, int nType = SQLOCALS_TYPE_ALL, string sLike = "", string sEscape = "")
|
||||
{
|
||||
if (!GetIsPC(oObject) || nType < 0) return;
|
||||
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"DELETE FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE " +
|
||||
(nType != SQLOCALS_TYPE_ALL ? "AND type & @type " : " ") +
|
||||
(sLike != "" ? "AND varname LIKE @like " + (sEscape != "" ? "ESCAPE @escape" : "") : "") +
|
||||
";");
|
||||
|
||||
if (nType != SQLOCALS_TYPE_ALL)
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
if (sLike != "")
|
||||
{
|
||||
SqlBindString(sql, "@like", sLike);
|
||||
|
||||
if (sEscape != "")
|
||||
SqlBindString(sql, "@escape", sEscape);
|
||||
}
|
||||
|
||||
SqlStep(sql);
|
||||
}
|
||||
|
||||
// Counts a set of locals stored on oObject matching the given criteria
|
||||
// * oObject - an object to reference against
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
// * sLike - The string to compare with the SQL "like" comparison
|
||||
// * sEscape - The escape character to use with the SQL "escape" keyword
|
||||
int SQLocals_Count(object oObject, int nType = SQLOCALS_TYPE_ALL, string sLike = "", string sEscape = "")
|
||||
{
|
||||
if (!GetIsPC(oObject) || nType < 0) return 0;
|
||||
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"SELECT COUNT(*) FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE " +
|
||||
(nType != SQLOCALS_TYPE_ALL ? "AND type & @type " : " ") +
|
||||
(sLike != "" ? "AND varname LIKE @like " + (sEscape != "" ? "ESCAPE @escape" : "") : "") +
|
||||
";");
|
||||
|
||||
if (nType != SQLOCALS_TYPE_ALL)
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
if (sLike != "")
|
||||
{
|
||||
SqlBindString(sql, "@like", sLike);
|
||||
|
||||
if (sEscape != "")
|
||||
SqlBindString(sql, "@escape", sEscape);
|
||||
}
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetInt(sql, 0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Checks a locals stored on oObject is set
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
int SQLocals_IsSet(object oObject, string sVarName, int nType)
|
||||
{
|
||||
if (!GetIsPC(oObject) || nType < 0) return 0;
|
||||
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"SELECT * FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE " +
|
||||
(nType != SQLOCALS_TYPE_ALL ? "AND type & @type " : " ") +
|
||||
"AND varname = @varname;");
|
||||
|
||||
if (nType != SQLOCALS_TYPE_ALL)
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
SqlBindString(sql, "@varname", sVarName);
|
||||
|
||||
return SqlStep(sql);
|
||||
}
|
||||
|
||||
// Returns the last Unix time the given variable was updated
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
int SQLocals_GetLastUpdated_UnixEpoch(object oObject, string sVarName, int nType)
|
||||
{
|
||||
if (!GetIsPC(oObject) || nType <= 0) return 0;
|
||||
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"SELECT timestamp FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE type = @type " +
|
||||
"AND varname = @varname;");
|
||||
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
SqlBindString(sql, "@varname", sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetInt(sql, 0);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the last UTC time the given variable was updated
|
||||
// * oObject - an object to reference against
|
||||
// * sVarName - name of the variable to retrieve
|
||||
// * nType - The SQL_LOCALS_TYPE_* you wish to remove (default: SQL_LOCALS_TYPE_ALL)
|
||||
string SQLocals_GetLastUpdated_UTC(object oObject, string sVarName, int nType)
|
||||
{
|
||||
if (!GetIsPC(oObject) || nType <= 0) return "";
|
||||
|
||||
SQLocals_CreateTable(oObject);
|
||||
|
||||
sqlquery sql = SqlPrepareQueryObject(oObject,
|
||||
"SELECT datetime(timestamp, 'unixepoch') FROM " + SQLOCALS_TABLE_NAME + " " +
|
||||
"WHERE type = @type " +
|
||||
"AND varname = @varname;");
|
||||
|
||||
SqlBindInt(sql, "@type", nType);
|
||||
SqlBindString(sql, "@varname", sVarName);
|
||||
|
||||
if (SqlStep(sql))
|
||||
return SqlGetString(sql, 0);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
556
trunk/users/Stratovarius/NWNEE Updates/prc_amagsys_gain.nss
Normal file
556
trunk/users/Stratovarius/NWNEE Updates/prc_amagsys_gain.nss
Normal file
@@ -0,0 +1,556 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Alternate magic system gain evaluation script
|
||||
//:: prc_amagsys_gain
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
This file determines if the given character
|
||||
has gained new spells / powers / utterances /
|
||||
whathaveyou since the last time it was run.
|
||||
If so, it starts the relevant selection
|
||||
conversations.
|
||||
|
||||
Add new classes to their respective magic
|
||||
user type block, or if such doesn't exist
|
||||
yet for the system the class belongs to,
|
||||
make a new block for them at the end of main().
|
||||
|
||||
|
||||
@author Ornedan
|
||||
@date Created - 2006.12.14
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "inc_dynconv"
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_newspellbook"
|
||||
#include "true_inc_trufunc"
|
||||
#include "tob_inc_tobfunc"
|
||||
#include "shd_inc_shdfunc"
|
||||
#include "inv_inc_invfunc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void CheckSpellbooks(object oPC);
|
||||
void CheckPsionics(object oPC);
|
||||
void CheckInvocations(object oPC);
|
||||
void CheckToB(object oPC);
|
||||
void CheckShadow(object oPC);
|
||||
void CheckTruenaming(object oPC);
|
||||
int CheckMissingPowers(object oPC, int nClass);
|
||||
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel);
|
||||
int CheckMissingUtterances(object oPC, int nClass, int nLexicon);
|
||||
int CheckMissingManeuvers(object oPC, int nClass);
|
||||
int CheckMissingMysteries(object oPC, int nClass);
|
||||
int CheckMissingInvocations(object oPC, int nClass);
|
||||
void AMSCompatibilityCheck(object oPC);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
|
||||
// Sanity checks - Shifted or polymorphed characters may have their hide fucked up, and might be missing access to their hide-feats
|
||||
// @todo Shifting probably doesn't do this anymore, could be ditchable - Ornedan, 20061214
|
||||
if(GetLocalInt(oPC, "nPCShifted"))
|
||||
return;
|
||||
effect eTest = GetFirstEffect(oPC);
|
||||
while(GetIsEffectValid(eTest))
|
||||
{
|
||||
if(GetEffectType(eTest) == EFFECT_TYPE_POLYMORPH)
|
||||
return;
|
||||
eTest = GetNextEffect(oPC);
|
||||
}
|
||||
|
||||
DelayCommand(0.0f, CheckSpellbooks(oPC));
|
||||
}
|
||||
|
||||
// Handle new spellbooks
|
||||
void CheckSpellbooks(object oPC)
|
||||
{
|
||||
if(!GetPRCSwitch(PRC_BARD_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_BARD, 0, 6))
|
||||
return;
|
||||
if(!GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK) && CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_SUEL_ARCHANAMACH, 1, 5))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_FAVOURED_SOUL, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_MYSTIC, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_WARMAGE, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_DREAD_NECROMANCER, 1, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_HEXBLADE, 1, 4))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_DUSKBLADE, 0, 5))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_JUSTICEWW, 1, 4))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_KNIGHT_WEAVE, 1, 6))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_WITCH, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_SUBLIME_CHORD, 4, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_ARCHIVIST, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_BEGUILER, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_HARPER, 1, 3))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_TEMPLAR, 0, 9))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_ASSASSIN, 1, 4))
|
||||
return;
|
||||
if(CheckMissingSpells(oPC, CLASS_TYPE_CELEBRANT_SHARESS, 1, 4))
|
||||
return;
|
||||
|
||||
DelayCommand(0.0f, CheckPsionics(oPC));
|
||||
}
|
||||
|
||||
// Handle psionics
|
||||
void CheckPsionics(object oPC)
|
||||
{
|
||||
if(CheckMissingPowers(oPC, CLASS_TYPE_PSION))
|
||||
return;
|
||||
if(CheckMissingPowers(oPC, CLASS_TYPE_WILDER))
|
||||
return;
|
||||
if(CheckMissingPowers(oPC, CLASS_TYPE_PSYWAR))
|
||||
return;
|
||||
if(CheckMissingPowers(oPC, CLASS_TYPE_PSYCHIC_ROGUE))
|
||||
return;
|
||||
if(CheckMissingPowers(oPC, CLASS_TYPE_FIST_OF_ZUOKEN))
|
||||
return;
|
||||
if(CheckMissingPowers(oPC, CLASS_TYPE_WARMIND))
|
||||
return;
|
||||
//expanded knowledge
|
||||
if(CheckMissingPowers(oPC, -1))
|
||||
return;
|
||||
//epic expanded knowledge
|
||||
if(CheckMissingPowers(oPC, -2))
|
||||
return;
|
||||
|
||||
DelayCommand(0.0f, CheckInvocations(oPC));
|
||||
}
|
||||
|
||||
// Handle Invocations
|
||||
void CheckInvocations(object oPC)
|
||||
{
|
||||
if(CheckMissingInvocations(oPC, CLASS_TYPE_DRAGONFIRE_ADEPT))
|
||||
return;
|
||||
if(CheckMissingInvocations(oPC, CLASS_TYPE_WARLOCK))
|
||||
return;
|
||||
if(CheckMissingInvocations(oPC, CLASS_TYPE_DRAGON_SHAMAN))
|
||||
return;
|
||||
//extra invocations
|
||||
if(CheckMissingInvocations(oPC, CLASS_TYPE_INVALID))
|
||||
return;
|
||||
//epic extra invocations
|
||||
if(CheckMissingInvocations(oPC, -2))
|
||||
return;
|
||||
|
||||
DelayCommand(0.0f, CheckToB(oPC));
|
||||
}
|
||||
|
||||
// Handle Tome of Battle
|
||||
void CheckToB(object oPC)
|
||||
{
|
||||
if(CheckMissingManeuvers(oPC, CLASS_TYPE_CRUSADER))
|
||||
return;
|
||||
if(CheckMissingManeuvers(oPC, CLASS_TYPE_SWORDSAGE))
|
||||
return;
|
||||
if(CheckMissingManeuvers(oPC, CLASS_TYPE_WARBLADE))
|
||||
return;
|
||||
|
||||
DelayCommand(0.0f, CheckShadow(oPC));
|
||||
}
|
||||
|
||||
// Handle Shadowcasting
|
||||
void CheckShadow(object oPC)
|
||||
{
|
||||
if(CheckMissingMysteries(oPC, CLASS_TYPE_SHADOWCASTER))
|
||||
return;
|
||||
if(CheckMissingMysteries(oPC, CLASS_TYPE_SHADOWSMITH))
|
||||
return;
|
||||
|
||||
DelayCommand(0.0f, CheckTruenaming(oPC));
|
||||
}
|
||||
|
||||
// Handle Truenaming - Three different Lexicons to check
|
||||
void CheckTruenaming(object oPC)
|
||||
{
|
||||
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_EVOLVING_MIND))
|
||||
return;
|
||||
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_CRAFTED_TOOL))
|
||||
return;
|
||||
if(CheckMissingUtterances(oPC, CLASS_TYPE_TRUENAMER, LEXICON_PERFECTED_MAP))
|
||||
return;
|
||||
|
||||
if(!GetIsDM(oPC))
|
||||
DelayCommand(0.0f, AMSCompatibilityCheck(oPC));
|
||||
}
|
||||
|
||||
int CheckMissingPowers(object oPC, int nClass)
|
||||
{
|
||||
int nLevel = GetLevelByClass(nClass, oPC);
|
||||
if(!nLevel && nClass != -1 && nClass != -2)
|
||||
return FALSE;
|
||||
else if(nClass == -1 && !GetHasFeat(FEAT_EXPANDED_KNOWLEDGE_1))
|
||||
return FALSE;
|
||||
else if(nClass == -2 && !GetHasFeat(FEAT_EPIC_EXPANDED_KNOWLEDGE_1))
|
||||
return FALSE;
|
||||
|
||||
int nCurrentPowers = GetPowerCount(oPC, nClass);
|
||||
int nMaxPowers = GetMaxPowerCount(oPC, nClass);
|
||||
|
||||
if(nCurrentPowers < nMaxPowers)
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("psi_powconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CheckMissingInvocations(object oPC, int nClass)
|
||||
{
|
||||
int nLevel = GetLevelByClass(nClass, oPC);
|
||||
if(!nLevel && (nClass == CLASS_TYPE_DRAGONFIRE_ADEPT || nClass == CLASS_TYPE_WARLOCK || nClass == CLASS_TYPE_DRAGON_SHAMAN))
|
||||
return FALSE;
|
||||
else if(nClass == CLASS_TYPE_INVALID && !GetHasFeat(FEAT_EXTRA_INVOCATION_I))
|
||||
return FALSE;
|
||||
else if(nClass == -2 && !GetHasFeat(FEAT_EPIC_EXTRA_INVOCATION_I))
|
||||
return FALSE;
|
||||
|
||||
int nCurrentInvocations = GetInvocationCount(oPC, nClass);
|
||||
if(DEBUG) DoDebug("Current Invocations: " + IntToString(nCurrentInvocations));
|
||||
int nMaxInvocations = GetMaxInvocationCount(oPC, nClass);
|
||||
if(DEBUG) DoDebug("Max Invocations: " + IntToString(nMaxInvocations));
|
||||
|
||||
if(nCurrentInvocations < nMaxInvocations)
|
||||
{
|
||||
// Mark the class for which the PC is to gain invocations and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("inv_invokeconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void AddSpellsForLevel(int nClass, int nLevel)
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
object oSkin = GetPCSkin(oPC);
|
||||
//object oPC = GetHideToken(oPC);
|
||||
string sFile = GetFileForClass(nClass);
|
||||
string sSpellbook;
|
||||
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
||||
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||
sSpellbook = "Spellbook"+IntToString(nClass);
|
||||
else
|
||||
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(nLevel);
|
||||
|
||||
// Create spells known persistant array if it is missing
|
||||
int nSize = persistant_array_get_size(oPC, sSpellbook);
|
||||
if (nSize < 0)
|
||||
{
|
||||
persistant_array_create(oPC, sSpellbook);
|
||||
nSize = 0;
|
||||
}
|
||||
|
||||
//check for learnable spells
|
||||
//object oPC_Class = GetObjectByTag("SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nLevel));
|
||||
int nSpells_Total = persistant_array_get_size(oPC, "Lkup");
|
||||
int i;
|
||||
for(i = 0; i < nSpells_Total; i++)
|
||||
{
|
||||
int nSpellbookID = persistant_array_get_int(oPC, "Lkup", i);
|
||||
if(Get2DAString(sFile, "AL", nSpellbookID) != "1")
|
||||
{
|
||||
array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
|
||||
nSize++;
|
||||
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||
{
|
||||
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||||
AddSpellUse(oPC, nSpellbookID, nClass, sFile, "NewSpellbookMem_" + IntToString(nClass), nSpellbookType, oSkin, nFeatID, nIPFeatID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CheckMissingSpells(object oPC, int nClass, int nMinLevel, int nMaxLevel)
|
||||
{
|
||||
int nLevel;
|
||||
//Raks cast as sorcs
|
||||
if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|
||||
nLevel = GetLevelByClass(CLASS_TYPE_OUTSIDER, oPC);
|
||||
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI) //Bozaks cast as sorcs
|
||||
nLevel = GetLevelByClass(CLASS_TYPE_MONSTROUS, oPC);
|
||||
else if(nClass == CLASS_TYPE_SORCERER && GetRacialType(oPC) == RACIAL_TYPE_DRIDER) //Driders cast as sorcs
|
||||
nLevel = GetLevelByClass(CLASS_TYPE_ABERRATION, oPC);
|
||||
else
|
||||
nLevel = nClass == CLASS_TYPE_SUBLIME_CHORD ? GetLevelByClass(nClass, oPC) : GetSpellslotLevel(nClass, oPC);
|
||||
|
||||
if (DEBUG) DoDebug("CheckMissingSpells 1 Class: " + IntToString(nClass));
|
||||
if (DEBUG) DoDebug("CheckMissingSpells 1 Level: " + IntToString(nLevel));
|
||||
|
||||
if(!nLevel)
|
||||
return FALSE;
|
||||
if(nClass == CLASS_TYPE_BARD || nClass == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
if((GetLevelByClass(nClass, oPC) == nLevel) //no PrC
|
||||
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oPC) || GetHasFeat(FEAT_DRACONIC_BREATH, oPC))) //no Draconic feats that apply
|
||||
return FALSE;
|
||||
}
|
||||
else if(nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
int nLastGainLevel = GetPersistantLocalInt(oPC, "LastSpellGainLevel");
|
||||
nLevel = GetLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
|
||||
|
||||
if(nLastGainLevel < nLevel)
|
||||
{
|
||||
if(nLevel == 1)
|
||||
{
|
||||
//count the number of available at 1st level spells
|
||||
int nSpellsAvailable = 3 + GetAbilityModifier(ABILITY_INTELLIGENCE, oPC);
|
||||
SetLocalInt(oPC, "LrnLvlUp", nSpellsAvailable);
|
||||
}
|
||||
else if(nLevel > 1)
|
||||
//add additional 2 spells form cleric list
|
||||
SetLocalInt(oPC, "LrnLvlUp", 2);
|
||||
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_ARCHIVIST);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, TRUE, FALSE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
//add cleric spells known for level 0
|
||||
else if(persistant_array_get_size(oPC, "Spellbook_Known_"+IntToString(CLASS_TYPE_ARCHIVIST)+"_0") < 5) // TODO: replace with GetSpellKnownCurrentCount
|
||||
{
|
||||
ActionDoCommand(AddSpellsForLevel(CLASS_TYPE_ARCHIVIST, 0));
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("CheckMissingSpells 2 Class: " + IntToString(nClass));
|
||||
if (DEBUG) DoDebug("CheckMissingSpells 2 Level: " + IntToString(nLevel));
|
||||
|
||||
int i;
|
||||
for(i = nMinLevel; i <= nMaxLevel; i++)
|
||||
{
|
||||
int nMaxSpells = GetSpellKnownMaxCount(nLevel, i, nClass, oPC);
|
||||
if(nMaxSpells > 0)
|
||||
{
|
||||
int nCurrentSpells = GetSpellKnownCurrentCount(oPC, i, nClass);
|
||||
int nSpellsAvailable = GetSpellUnknownCurrentCount(oPC, i, nClass);
|
||||
|
||||
if(nCurrentSpells < nMaxSpells && nSpellsAvailable > 0)
|
||||
{
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS && bKnowsAllClassSpells(nClass))
|
||||
{
|
||||
ActionDoCommand(AddSpellsForLevel(nClass, i));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", nClass);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "SpellbookMaxSpelllevel", nMaxLevel);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Advanced Learning check
|
||||
nLevel = GetLevelByClass(nClass, oPC);
|
||||
int nALSpells = GetPersistantLocalInt(oPC, "AdvancedLearning_"+IntToString(nClass));
|
||||
if(nClass == CLASS_TYPE_BEGUILER && nALSpells < (nLevel+1)/4)//one every 4 levels starting at 3.
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_BEGUILER);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
else if(nClass == CLASS_TYPE_DREAD_NECROMANCER && nALSpells < nLevel/4)//one every 4 levels
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_DREAD_NECROMANCER);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
else if(nClass == CLASS_TYPE_WARMAGE)
|
||||
{
|
||||
if((nLevel >= 40 && nALSpells < 9) ||// :/
|
||||
(nLevel >= 36 && nLevel < 40 && nALSpells < 8) ||
|
||||
(nLevel >= 32 && nLevel < 36 && nALSpells < 7) ||
|
||||
(nLevel >= 28 && nLevel < 32 && nALSpells < 6) ||
|
||||
(nLevel >= 24 && nLevel < 28 && nALSpells < 5) ||
|
||||
(nLevel >= 16 && nLevel < 24 && nALSpells < 4) ||
|
||||
(nLevel >= 11 && nLevel < 16 && nALSpells < 3) ||
|
||||
(nLevel >= 6 && nLevel < 11 && nALSpells < 2) ||
|
||||
(nLevel >= 3 && nLevel < 6 && nALSpells < 1))
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_WARMAGE);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if(nClass == CLASS_TYPE_NIGHTSTALKER && nALSpells < (nLevel+1)/6)//one every 6 levels starting at 5th
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "SpellGainClass", CLASS_TYPE_NIGHTSTALKER);
|
||||
SetLocalInt(oPC, "SpellbookMinSpelllevel", nMinLevel);
|
||||
SetLocalInt(oPC, "AdvancedLearning", 1);
|
||||
StartDynamicConversation("prc_s_spellgain", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CheckMissingUtterances(object oPC, int nClass, int nLexicon)
|
||||
{
|
||||
int nLevel = GetLevelByClass(nClass, oPC);
|
||||
if(!nLevel)
|
||||
return FALSE;
|
||||
|
||||
int nCurrentUtterances = GetUtteranceCount(oPC, nClass, nLexicon);
|
||||
int nMaxUtterances = GetMaxUtteranceCount(oPC, nClass, nLexicon);
|
||||
if(DEBUG) DoDebug("CheckMissingUtterances(" + IntToString(nClass) + ", " + IntToString(nLexicon) + ", " + GetName(oPC) + ") = " + IntToString(nCurrentUtterances) + ", " + IntToString(nMaxUtterances));
|
||||
|
||||
if(nCurrentUtterances < nMaxUtterances)
|
||||
{
|
||||
// Mark the class for which the PC is to gain Utterances and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("true_utterconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CheckMissingManeuvers(object oPC, int nClass)
|
||||
{
|
||||
int nLevel = GetLevelByClass(nClass, oPC);
|
||||
if(!nLevel)
|
||||
return FALSE;
|
||||
|
||||
int nCurrentManeuvers = GetManeuverCount(oPC, nClass, MANEUVER_TYPE_MANEUVER);
|
||||
int nMaxManeuvers = GetMaxManeuverCount(oPC, nClass, MANEUVER_TYPE_MANEUVER);
|
||||
int nCurrentStances = GetManeuverCount(oPC, nClass, MANEUVER_TYPE_STANCE);
|
||||
int nMaxStances = GetMaxManeuverCount(oPC, nClass, MANEUVER_TYPE_STANCE);
|
||||
|
||||
if(nCurrentManeuvers < nMaxManeuvers || nCurrentStances < nMaxStances)
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("tob_moveconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CheckMissingMysteries(object oPC, int nClass)
|
||||
{
|
||||
int nLevel = GetLevelByClass(nClass, oPC);
|
||||
if(!nLevel)
|
||||
return FALSE;
|
||||
|
||||
int nCurrentMysteries = GetMysteryCount(oPC, nClass);
|
||||
int nMaxMysteries = GetMaxMysteryCount(oPC, nClass);
|
||||
|
||||
if(nCurrentMysteries < nMaxMysteries)
|
||||
{
|
||||
// Mark the class for which the PC is to gain powers and start the conversation
|
||||
SetLocalInt(oPC, "nClass", nClass);
|
||||
StartDynamicConversation("shd_mystconv", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//AMS Compatibility functions - xwarren:
|
||||
void CopyAMSArray(object oHideToken, object oAMSToken, int nClass, string sArray, int nMin, int nMax, int nLoopSize = 100)
|
||||
{
|
||||
string sFile = GetFileForClass(nClass);
|
||||
int i = nMin;
|
||||
while(i < nMin + nLoopSize && i < nMax)
|
||||
{
|
||||
int nSpellbookID = array_get_int(oHideToken, sArray, i);
|
||||
int nSpell = StringToInt(Get2DACache(sFile, "RealSpellID", nSpellbookID));
|
||||
if(DEBUG) DoDebug("Copying spell "+IntToString(nSpell));
|
||||
array_set_int(oAMSToken, sArray, i, nSpell);
|
||||
i++;
|
||||
}
|
||||
if(i < nMax)
|
||||
DelayCommand(0.0, CopyAMSArray(oHideToken, oAMSToken, nClass, sArray, i, nMax));
|
||||
}
|
||||
|
||||
void DoBuckUpAMS(object oPC, int nClass, string sSpellbook, object oHideToken, object oAMSToken)
|
||||
{
|
||||
if(DEBUG) DoDebug("Creating buck-up copy of "+sSpellbook);
|
||||
if(array_exists(oAMSToken, sSpellbook))
|
||||
array_delete(oAMSToken, sSpellbook);
|
||||
array_create(oAMSToken, sSpellbook);
|
||||
int nSize = array_get_size(oHideToken, sSpellbook);
|
||||
DelayCommand(0.0, CopyAMSArray(oHideToken, oAMSToken, nClass, sSpellbook, 0, nSize));
|
||||
}
|
||||
|
||||
void AMSCompatibilityCheck(object oPC)
|
||||
{
|
||||
//Get an extra hide token with amagsys info
|
||||
object oAMSToken = GetHideToken(oPC, TRUE);
|
||||
object oHideToken = GetHideToken(oPC);
|
||||
|
||||
int i;
|
||||
for(i = 1; i <= 3; i++)
|
||||
{
|
||||
int nClass = GetClassByPosition(i, oPC);
|
||||
string sSpellbook;
|
||||
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
||||
if(nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
|
||||
{
|
||||
sSpellbook = "Spellbook"+IntToString(nClass);
|
||||
int nSize1 = array_get_size(oHideToken, sSpellbook);
|
||||
int nSize2 = array_get_size(oAMSToken, sSpellbook);
|
||||
if(nSize1 > nSize2)
|
||||
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
|
||||
}
|
||||
else if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
|
||||
{
|
||||
int j;
|
||||
for(j = 0; j <= 9; j++)
|
||||
{
|
||||
sSpellbook = "Spellbook_Known_"+IntToString(nClass)+"_"+IntToString(j);
|
||||
int nSize1 = array_get_size(oHideToken, sSpellbook);
|
||||
int nSize2 = array_get_size(oAMSToken, sSpellbook);
|
||||
if(nSize1 > nSize2)
|
||||
DelayCommand(0.1f, DoBuckUpAMS(oPC, nClass, sSpellbook, oHideToken, oAMSToken));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
trunk/users/Stratovarius/NWNEE Updates/prc_archv_lspell.nss
Normal file
114
trunk/users/Stratovarius/NWNEE Updates/prc_archv_lspell.nss
Normal file
@@ -0,0 +1,114 @@
|
||||
//Learn spell from scroll function for archivist class.
|
||||
|
||||
#include "inc_newspellbook"
|
||||
|
||||
void SortSpellbook()
|
||||
{
|
||||
object oToken = GetHideToken(OBJECT_SELF);
|
||||
int i;
|
||||
for(i = 0; i < 10; i++)
|
||||
{
|
||||
float fDelay = i*0.1f;
|
||||
string sSpellBook = GetSpellsKnown_Array(CLASS_TYPE_ARCHIVIST, i);
|
||||
if(persistant_array_exists(oToken, sSpellBook))
|
||||
{
|
||||
DelayCommand(fDelay, CountingSortInt(oToken, sSpellBook));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
object oScroll = GetSpellTargetObject();
|
||||
|
||||
if(GetItemPossessor(oScroll) != oPC)
|
||||
return;
|
||||
|
||||
int nItemType = GetBaseItemType(oScroll);
|
||||
if(GetIdentified(oScroll) && nItemType != BASE_ITEM_SCROLL && nItemType != BASE_ITEM_SPELLSCROLL && nItemType != BASE_ITEM_ENCHANTED_SCROLL)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(oPC, GetStringByStrRef(53309));//"You cannnot learn anything from that item."
|
||||
return;
|
||||
}
|
||||
|
||||
int nSpellID = -1;
|
||||
itemproperty ipTest = GetFirstItemProperty(oScroll);
|
||||
while(GetIsItemPropertyValid(ipTest))
|
||||
{
|
||||
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_CAST_SPELL)
|
||||
{
|
||||
nSpellID = StringToInt(Get2DACache("iprp_spells", "SpellIndex", GetItemPropertySubType(ipTest)));
|
||||
break;
|
||||
}
|
||||
ipTest = GetNextItemProperty(oScroll);
|
||||
}
|
||||
|
||||
if(nSpellID > -1)
|
||||
{
|
||||
//look for the spellID in spell book
|
||||
int nSpellbookID = RealSpellToSpellbookID(CLASS_TYPE_ARCHIVIST, nSpellID);
|
||||
|
||||
//it's not in the spell book
|
||||
if(nSpellbookID == -1)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(oPC, GetStringByStrRef(16789885));//"You can only learn Divine spells."
|
||||
return;
|
||||
}
|
||||
|
||||
//check spell level
|
||||
string sFile = "cls_spell_archv";
|
||||
int nSpellLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookID));
|
||||
int nCasterLevel = GetCasterLevelByClass(CLASS_TYPE_ARCHIVIST, oPC);
|
||||
int nSpellLevelMax = GetMaxSpellLevelForCasterLevel(CLASS_TYPE_ARCHIVIST, nCasterLevel);
|
||||
|
||||
if(nSpellLevel > nSpellLevelMax)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(oPC, GetStringByStrRef(68612));//"You have not achieved the required level to learn that spell."
|
||||
return;
|
||||
}
|
||||
if(nSpellLevel > (GetAbilityScore(oPC, ABILITY_INTELLIGENCE) - 10))
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(oPC, GetStringByStrRef(68613));//"You do not have the minimum attribute required to learn this spell."
|
||||
return;
|
||||
}
|
||||
|
||||
//check if oPC doesn't have the spell and can learn it
|
||||
//object oToken = GetHideToken(oPC);
|
||||
string sSpellBook = GetSpellsKnown_Array(CLASS_TYPE_ARCHIVIST, nSpellLevel);
|
||||
|
||||
// Create spells known persistant array if it is missing
|
||||
int nSize = persistant_array_get_size(oPC, sSpellBook);
|
||||
if (nSize < 0)
|
||||
{
|
||||
persistant_array_create(oPC, sSpellBook);
|
||||
nSize = 0;
|
||||
}
|
||||
|
||||
if(IsIntSet(oPC, sSpellBook, nSpellbookID) != -1)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(oPC, GetStringByStrRef(53308));//"You already have that spell in your spellbook."
|
||||
return;
|
||||
}
|
||||
|
||||
//destroy the scroll
|
||||
int nStack = GetNumStackedItems(oScroll);
|
||||
if (nStack > 1)
|
||||
SetItemStackSize(oScroll, --nStack);
|
||||
else
|
||||
DestroyObject(oScroll);
|
||||
|
||||
//add the spell
|
||||
persistant_array_set_int(oPC, sSpellBook, nSize, nSpellbookID);
|
||||
PlaySound("gui_learnspell");
|
||||
|
||||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||||
SendMessageToPC(oPC, ReplaceChars(GetStringByStrRef(53307), "<CUSTOM0>", sName));//"<CUSTOM0> has been added to your spellbook."
|
||||
}
|
||||
//SortSpellbook(); Causing TMIs - disabled at the moment
|
||||
}
|
||||
1172
trunk/users/Stratovarius/NWNEE Updates/prc_s_spellgain.nss
Normal file
1172
trunk/users/Stratovarius/NWNEE Updates/prc_s_spellgain.nss
Normal file
File diff suppressed because it is too large
Load Diff
124
trunk/users/Stratovarius/NWNEE Updates/prc_witch_lspell.nss
Normal file
124
trunk/users/Stratovarius/NWNEE Updates/prc_witch_lspell.nss
Normal file
@@ -0,0 +1,124 @@
|
||||
//Learn spell from scroll function for witch class.
|
||||
// Deprecated as Witch is no longer in the PRC
|
||||
|
||||
#include "inc_newspellbook"
|
||||
|
||||
void main()
|
||||
{
|
||||
/* if(GetPRCSwitch(PRC_WITCH_DISABLE_SPELL_LEARN))
|
||||
{
|
||||
SendMessageToPC(OBJECT_SELF, "Spell-learning for Witch class has been disabled in this module");
|
||||
return;
|
||||
}
|
||||
|
||||
object oScroll = GetSpellTargetObject();
|
||||
if(GetItemPossessor(oScroll) != OBJECT_SELF)
|
||||
return;
|
||||
|
||||
int nItemType = GetBaseItemType(oScroll);
|
||||
if(GetIdentified(oScroll) && nItemType != BASE_ITEM_SCROLL && nItemType != BASE_ITEM_SPELLSCROLL && nItemType != BASE_ITEM_ENCHANTED_SCROLL)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, GetStringByStrRef(53309));//"You cannnot learn anything from that item."
|
||||
return;
|
||||
}
|
||||
|
||||
int nSpellID = -1;
|
||||
itemproperty ipTest = GetFirstItemProperty(oScroll);
|
||||
while(GetIsItemPropertyValid(ipTest))
|
||||
{
|
||||
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_CAST_SPELL)
|
||||
{
|
||||
nSpellID = StringToInt(Get2DACache("iprp_spells", "SpellIndex", GetItemPropertySubType(ipTest)));
|
||||
break;
|
||||
}
|
||||
ipTest = GetNextItemProperty(oScroll);
|
||||
}
|
||||
|
||||
if(nSpellID > -1)
|
||||
{
|
||||
//look for the spellID in spell book
|
||||
int nSpellbookID = RealSpellToSpellbookID(CLASS_TYPE_WITCH, nSpellID);
|
||||
|
||||
//it's not in the spell book
|
||||
if(nSpellbookID == -1)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, GetStringByStrRef(16789885));//"You can only learn Witch spells."
|
||||
return;
|
||||
}
|
||||
|
||||
//check spell level
|
||||
string sFile = "cls_spell_witch";
|
||||
int nSpellLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookID));
|
||||
int nCasterLevel = GetCasterLevelByClass(CLASS_TYPE_WITCH, OBJECT_SELF);
|
||||
int nSpellLevelMax = GetMaxSpellLevelForCasterLevel(CLASS_TYPE_WITCH, nCasterLevel);
|
||||
|
||||
if(nSpellLevel > nSpellLevelMax)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, GetStringByStrRef(68612));//"You have not achieved the required level to learn that spell."
|
||||
return;
|
||||
}
|
||||
if(nSpellLevel > (GetAbilityScore(OBJECT_SELF, ABILITY_WISDOM) - 10))
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, GetStringByStrRef(68613));//"You do not have the minimum attribute required to learn this spell."
|
||||
return;
|
||||
}
|
||||
int nXPCost = 75*nSpellLevel;
|
||||
if(!nXPCost) nXPCost = 25;
|
||||
|
||||
if(!GetHasXPToSpend(OBJECT_SELF, nXPCost))
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, "Not enough XP to learn this spell.");
|
||||
return;
|
||||
}
|
||||
|
||||
//check if OBJECT_SELF doesn't have the spell and can learn it
|
||||
object oToken = GetHideToken(OBJECT_SELF);
|
||||
string sSpellBook = "Spellbook" + IntToString(CLASS_TYPE_WITCH);//GetSpellsKnown_Array(CLASS_TYPE_WITCH);
|
||||
|
||||
// Create spells known persistant array if it is missing
|
||||
int nSize = array_get_size(oToken, sSpellBook);
|
||||
if (nSize < 0)
|
||||
{
|
||||
array_create(oToken, sSpellBook);
|
||||
nSize = 0;
|
||||
}
|
||||
|
||||
if(array_has_int(oToken, sSpellBook, nSpellbookID) != -1)
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, GetStringByStrRef(53308));//"You already have that spell in your spellbook."
|
||||
return;
|
||||
}
|
||||
|
||||
//destroy the scroll
|
||||
int nStack = GetNumStackedItems(oScroll);
|
||||
if (nStack > 1)
|
||||
SetItemStackSize(oScroll, --nStack);
|
||||
else
|
||||
DestroyObject(oScroll);
|
||||
|
||||
//make a spellcraft check
|
||||
if(!GetIsSkillSuccessful(OBJECT_SELF, SKILL_SPELLCRAFT, 10 + nSpellLevel))
|
||||
{
|
||||
PlaySound("gui_failspell");
|
||||
SendMessageToPC(OBJECT_SELF, "You failed to learn this spell.");
|
||||
return;
|
||||
}
|
||||
|
||||
//add the spell
|
||||
PlaySound("gui_learnspell");
|
||||
int nIPFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
|
||||
int nFeatID = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
|
||||
array_set_int(oToken, sSpellBook, nSize, nSpellbookID);
|
||||
AddSpellUse(OBJECT_SELF, nSpellbookID, CLASS_TYPE_WITCH, sFile, "NewSpellbookMem_" + IntToString(CLASS_TYPE_WITCH), SPELLBOOK_TYPE_SPONTANEOUS, GetPCSkin(OBJECT_SELF), nFeatID, nIPFeatID);
|
||||
SpendXP(OBJECT_SELF, nXPCost);
|
||||
|
||||
string sName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||||
SendMessageToPC(OBJECT_SELF, ReplaceChars(GetStringByStrRef(53307), "<CUSTOM0>", sName));//"<CUSTOM0> has been added to your spellbook."
|
||||
}*/
|
||||
}
|
||||
91
trunk/users/Stratovarius/To do.txt
Normal file
91
trunk/users/Stratovarius/To do.txt
Normal file
@@ -0,0 +1,91 @@
|
||||
-----------------------------------------------------
|
||||
3.1
|
||||
-----------------------------------------------------
|
||||
|
||||
-----------------------------------------------------
|
||||
Primary
|
||||
-----------------------------------------------------
|
||||
|
||||
Truenaming:
|
||||
|
||||
Truenamer
|
||||
62/63 Utterances
|
||||
4 Prestige Classes
|
||||
|
||||
Truenamer Class: See the Named to go.
|
||||
|
||||
Truename PrCs:
|
||||
Acolyte of the Ego - Unstarted
|
||||
Fiendbinder - Unstarted
|
||||
|
||||
Utterances: Incarnation of Angels skipped, needs Primo to work on templates.
|
||||
|
||||
-----------------------------------------------------
|
||||
Secondary
|
||||
-----------------------------------------------------
|
||||
|
||||
Base Classes:
|
||||
Dread Necromancer - All to do, Spells
|
||||
Beguiler - All to do, Spells
|
||||
|
||||
Psionic PrCs:
|
||||
Metamind - All to do
|
||||
Psion Uncarnate - All to do
|
||||
Pyrokineticist - All to do
|
||||
Cryokineticist - All to do
|
||||
|
||||
Normal PrCs:
|
||||
Stormsinger - All to do
|
||||
Blood Magus - Check what is done and what needs doing.
|
||||
|
||||
Pale master -> 3.1:
|
||||
Fighter vassal -> Use TNecro
|
||||
Incorp vassal
|
||||
Cleric vassal
|
||||
Summon Undead
|
||||
Summon Greater Undead
|
||||
Poke attacks
|
||||
Death Touch -> create undead on failed save
|
||||
|
||||
Domains (PGtF):
|
||||
Balance
|
||||
Cold
|
||||
Mentalism
|
||||
Repose
|
||||
Suffering
|
||||
Trade
|
||||
|
||||
-----------------------------------------------------
|
||||
Feats to do in spare time
|
||||
-----------------------------------------------------
|
||||
|
||||
Complete Divine:
|
||||
|
||||
Cheetah's Speed
|
||||
Elephant's Hide
|
||||
Extra Wildshape
|
||||
Grizzly Claws
|
||||
Oaken Resilience
|
||||
Quicken Turning
|
||||
Sacred Healing
|
||||
True Believer
|
||||
Wolverine's Rage
|
||||
|
||||
Complete Warrior:
|
||||
Axiomatic Strike
|
||||
Dash
|
||||
Extend Rage
|
||||
Extra Rage
|
||||
Extra Smiting
|
||||
Freezing the Lifeblood
|
||||
Improved Rapid Shot
|
||||
Intimidating Rage
|
||||
Karmic Strike
|
||||
Weakening Touch
|
||||
Divine Cleansing
|
||||
Divine Resistance
|
||||
Divine Vigor
|
||||
Sacred Vengeance
|
||||
|
||||
Champions of Ruin:
|
||||
Doomspeak
|
||||
BIN
trunk/users/Stratovarius/blood magus.tka
Normal file
BIN
trunk/users/Stratovarius/blood magus.tka
Normal file
Binary file not shown.
402
trunk/users/Stratovarius/prc_add_spell_dc.nss
Normal file
402
trunk/users/Stratovarius/prc_add_spell_dc.nss
Normal file
@@ -0,0 +1,402 @@
|
||||
|
||||
// Use this function to get the adjustments to a spell or SLAs saving throw
|
||||
// from the various class effects
|
||||
// Update this function if any new classes change saving throws
|
||||
int PRCGetSaveDC(object oTarget, object oCaster, int nSpellID = -1);
|
||||
|
||||
//called just from above and from inc_epicspells
|
||||
int GetChangesToSaveDC(object oTarget, object oCaster = OBJECT_SELF, int nSpellID = -1);
|
||||
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_class_const"
|
||||
#include "prc_feat_const"
|
||||
#include "lookup_2da_spell"
|
||||
#include "prcsp_archmaginc"
|
||||
#include "prc_alterations"
|
||||
#include "prc_add_spl_pen"
|
||||
|
||||
|
||||
|
||||
// Check for CLASS_TYPE_HIEROPHANT > 0 in caller
|
||||
int GetWasLastSpellHieroSLA(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int iAbility = PRCGetLastSpellCastClass() == CLASS_TYPE_INVALID;
|
||||
int iSpell = spell_id == SPELL_HOLY_AURA ||
|
||||
spell_id == SPELL_UNHOLY_AURA ||
|
||||
spell_id == SPELL_BANISHMENT ||
|
||||
spell_id == SPELL_BATTLETIDE ||
|
||||
spell_id == SPELL_BLADE_BARRIER ||
|
||||
spell_id == SPELL_CIRCLE_OF_DOOM ||
|
||||
spell_id == SPELL_CONTROL_UNDEAD ||
|
||||
spell_id == SPELL_CREATE_GREATER_UNDEAD ||
|
||||
spell_id == SPELL_CREATE_UNDEAD ||
|
||||
spell_id == SPELL_CURE_CRITICAL_WOUNDS ||
|
||||
spell_id == SPELL_DEATH_WARD ||
|
||||
spell_id == SPELL_DESTRUCTION ||
|
||||
spell_id == SPELL_DISMISSAL ||
|
||||
spell_id == SPELL_DIVINE_POWER ||
|
||||
spell_id == SPELL_EARTHQUAKE ||
|
||||
spell_id == SPELL_ENERGY_DRAIN ||
|
||||
spell_id == SPELL_ETHEREALNESS ||
|
||||
spell_id == SPELL_FIRE_STORM ||
|
||||
spell_id == SPELL_FLAME_STRIKE ||
|
||||
spell_id == SPELL_FREEDOM_OF_MOVEMENT ||
|
||||
spell_id == SPELL_GATE ||
|
||||
spell_id == SPELL_GREATER_DISPELLING ||
|
||||
spell_id == SPELL_GREATER_MAGIC_WEAPON ||
|
||||
spell_id == SPELL_GREATER_RESTORATION ||
|
||||
spell_id == SPELL_HAMMER_OF_THE_GODS ||
|
||||
spell_id == SPELL_HARM ||
|
||||
spell_id == SPELL_HEAL ||
|
||||
spell_id == SPELL_HEALING_CIRCLE ||
|
||||
spell_id == SPELL_IMPLOSION ||
|
||||
spell_id == SPELL_INFLICT_CRITICAL_WOUNDS ||
|
||||
spell_id == SPELL_MASS_HEAL ||
|
||||
spell_id == SPELL_MONSTROUS_REGENERATION ||
|
||||
spell_id == SPELL_NEUTRALIZE_POISON ||
|
||||
spell_id == SPELL_PLANAR_ALLY ||
|
||||
spell_id == SPELL_POISON ||
|
||||
spell_id == SPELL_RAISE_DEAD ||
|
||||
spell_id == SPELL_REGENERATE ||
|
||||
spell_id == SPELL_RESTORATION ||
|
||||
spell_id == SPELL_RESURRECTION ||
|
||||
spell_id == SPELL_SLAY_LIVING ||
|
||||
spell_id == SPELL_SPELL_RESISTANCE ||
|
||||
spell_id == SPELL_STORM_OF_VENGEANCE ||
|
||||
spell_id == SPELL_SUMMON_CREATURE_IV ||
|
||||
spell_id == SPELL_SUMMON_CREATURE_IX ||
|
||||
spell_id == SPELL_SUMMON_CREATURE_V ||
|
||||
spell_id == SPELL_SUMMON_CREATURE_VI ||
|
||||
spell_id == SPELL_SUMMON_CREATURE_VII ||
|
||||
spell_id == SPELL_SUMMON_CREATURE_VIII ||
|
||||
spell_id == SPELL_SUNBEAM ||
|
||||
spell_id == SPELL_TRUE_SEEING ||
|
||||
spell_id == SPELL_UNDEATH_TO_DEATH ||
|
||||
spell_id == SPELL_UNDEATHS_ETERNAL_FOE ||
|
||||
spell_id == SPELL_WORD_OF_FAITH;
|
||||
|
||||
return iAbility && iSpell;
|
||||
}
|
||||
|
||||
int GetHierophantSLAAdjustment(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (GetLevelByClass(CLASS_TYPE_HIEROPHANT, oCaster) > 0 && GetWasLastSpellHieroSLA(spell_id, oCaster) )
|
||||
{
|
||||
retval = StringToInt( lookup_spell_cleric_level(spell_id) );
|
||||
retval -= GetLevelByClass(CLASS_TYPE_HIEROPHANT, oCaster);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int GetHeartWarderDC(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
// Check the curent school
|
||||
if (GetLocalInt(oCaster, "X2_L_LAST_SPELLSCHOOL_VAR") != SPELL_SCHOOL_ENCHANTMENT)
|
||||
return 0;
|
||||
|
||||
if (!GetHasFeat(FEAT_VOICE_SIREN, oCaster)) return 0;
|
||||
|
||||
// Bonus Requires Verbal Spells
|
||||
string VS = lookup_spell_vs(PRCGetSpellId());
|
||||
if (VS != "v" && VS != "vs")
|
||||
return 0;
|
||||
|
||||
// These feats provide greater bonuses or remove the Verbal requirement
|
||||
if (PRCGetMetaMagicFeat() & METAMAGIC_SILENT
|
||||
|| GetHasFeat(FEAT_GREATER_SPELL_FOCUS_ENCHANTMENT, oCaster)
|
||||
|| GetHasFeat(FEAT_EPIC_SPELL_FOCUS_ENCHANTMENT, oCaster))
|
||||
return 0;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
//Elemental Savant DC boost based on elemental spell type.
|
||||
int ElementalSavantDC(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int nDC = 0;
|
||||
int nES;
|
||||
|
||||
// All Elemental Savants will have this feat
|
||||
// when they first gain a DC bonus.
|
||||
if (GetHasFeat(FEAT_ES_FOCUS_1, oCaster)) {
|
||||
// get spell elemental type
|
||||
string element = ChangedElementalType(spell_id, oCaster);
|
||||
|
||||
// Any value that does not match one of the enumerated feats
|
||||
int feat = 0;
|
||||
|
||||
// Specify the elemental type rather than lookup by class?
|
||||
if (element == "Fire")
|
||||
{
|
||||
feat = FEAT_ES_FIRE;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_FIRE,oCaster);
|
||||
}
|
||||
else if (element == "Cold")
|
||||
{
|
||||
feat = FEAT_ES_COLD;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_COLD,oCaster);
|
||||
}
|
||||
else if (element == "Electricity")
|
||||
{
|
||||
feat = FEAT_ES_ELEC;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_ELEC,oCaster);
|
||||
}
|
||||
else if (element == "Acid")
|
||||
{
|
||||
feat = FEAT_ES_ACID;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_ACID,oCaster);
|
||||
}
|
||||
|
||||
// Now determine the bonus
|
||||
if (feat && GetHasFeat(feat, oCaster))
|
||||
{
|
||||
|
||||
if (nES > 28) nDC = 10;
|
||||
else if (nES > 25) nDC = 9;
|
||||
else if (nES > 22) nDC = 8;
|
||||
else if (nES > 19) nDC = 7;
|
||||
else if (nES > 16) nDC = 6;
|
||||
else if (nES > 13) nDC = 5;
|
||||
else if (nES > 10) nDC = 4;
|
||||
else if (nES > 7) nDC = 3;
|
||||
else if (nES > 4) nDC = 2;
|
||||
else if (nES > 1) nDC = 1;
|
||||
|
||||
}
|
||||
}
|
||||
// SendMessageToPC(GetFirstPC(), "Your Elemental Focus modifier is " + IntToString(nDC));
|
||||
return nDC;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Red Wizard DC boost based on spell school specialization
|
||||
int RedWizardDC(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int iRedWizard = GetLevelByClass(CLASS_TYPE_RED_WIZARD, oCaster);
|
||||
int nDC;
|
||||
|
||||
if (iRedWizard > 0)
|
||||
{
|
||||
int nSpell = PRCGetSpellId();
|
||||
string sSpellSchool = lookup_spell_school(nSpell);
|
||||
int iSpellSchool;
|
||||
int iRWSpec;
|
||||
|
||||
if (sSpellSchool == "A") iSpellSchool = SPELL_SCHOOL_ABJURATION;
|
||||
else if (sSpellSchool == "C") iSpellSchool = SPELL_SCHOOL_CONJURATION;
|
||||
else if (sSpellSchool == "D") iSpellSchool = SPELL_SCHOOL_DIVINATION;
|
||||
else if (sSpellSchool == "E") iSpellSchool = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sSpellSchool == "V") iSpellSchool = SPELL_SCHOOL_EVOCATION;
|
||||
else if (sSpellSchool == "I") iSpellSchool = SPELL_SCHOOL_ILLUSION;
|
||||
else if (sSpellSchool == "N") iSpellSchool = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sSpellSchool == "T") iSpellSchool = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (GetHasFeat(FEAT_RW_TF_ABJ, oCaster)) iRWSpec = SPELL_SCHOOL_ABJURATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_CON, oCaster)) iRWSpec = SPELL_SCHOOL_CONJURATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_DIV, oCaster)) iRWSpec = SPELL_SCHOOL_DIVINATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_ENC, oCaster)) iRWSpec = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (GetHasFeat(FEAT_RW_TF_EVO, oCaster)) iRWSpec = SPELL_SCHOOL_EVOCATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_ILL, oCaster)) iRWSpec = SPELL_SCHOOL_ILLUSION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_NEC, oCaster)) iRWSpec = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (GetHasFeat(FEAT_RW_TF_TRS, oCaster)) iRWSpec = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (iSpellSchool == iRWSpec)
|
||||
{
|
||||
|
||||
nDC = 1;
|
||||
|
||||
if (iRedWizard > 29) nDC = 16;
|
||||
else if (iRedWizard > 27) nDC = 15;
|
||||
else if (iRedWizard > 25) nDC = 14;
|
||||
else if (iRedWizard > 23) nDC = 13;
|
||||
else if (iRedWizard > 21) nDC = 12;
|
||||
else if (iRedWizard > 19) nDC = 11;
|
||||
else if (iRedWizard > 17) nDC = 10;
|
||||
else if (iRedWizard > 15) nDC = 9;
|
||||
else if (iRedWizard > 13) nDC = 8;
|
||||
else if (iRedWizard > 11) nDC = 7;
|
||||
else if (iRedWizard > 9) nDC = 6;
|
||||
else if (iRedWizard > 7) nDC = 5;
|
||||
else if (iRedWizard > 5) nDC = 4;
|
||||
else if (iRedWizard > 3) nDC = 3;
|
||||
else if (iRedWizard > 1) nDC = 2;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// SendMessageToPC(GetFirstPC(), "Your Spell Power modifier is " + IntToString(nDC));
|
||||
return nDC;
|
||||
}
|
||||
|
||||
|
||||
//Tattoo Focus DC boost based on spell school specialization
|
||||
int TattooFocus(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
|
||||
int nDC;
|
||||
int nSpell = PRCGetSpellId();
|
||||
string sSpellSchool = lookup_spell_school(nSpell);
|
||||
int iSpellSchool;
|
||||
int iRWSpec;
|
||||
|
||||
if (sSpellSchool == "A") iSpellSchool = SPELL_SCHOOL_ABJURATION;
|
||||
else if (sSpellSchool == "C") iSpellSchool = SPELL_SCHOOL_CONJURATION;
|
||||
else if (sSpellSchool == "D") iSpellSchool = SPELL_SCHOOL_DIVINATION;
|
||||
else if (sSpellSchool == "E") iSpellSchool = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sSpellSchool == "V") iSpellSchool = SPELL_SCHOOL_EVOCATION;
|
||||
else if (sSpellSchool == "I") iSpellSchool = SPELL_SCHOOL_ILLUSION;
|
||||
else if (sSpellSchool == "N") iSpellSchool = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sSpellSchool == "T") iSpellSchool = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (GetHasFeat(FEAT_RW_TF_ABJ, oCaster)) iRWSpec = SPELL_SCHOOL_ABJURATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_CON, oCaster)) iRWSpec = SPELL_SCHOOL_CONJURATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_DIV, oCaster)) iRWSpec = SPELL_SCHOOL_DIVINATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_ENC, oCaster)) iRWSpec = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (GetHasFeat(FEAT_RW_TF_EVO, oCaster)) iRWSpec = SPELL_SCHOOL_EVOCATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_ILL, oCaster)) iRWSpec = SPELL_SCHOOL_ILLUSION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_NEC, oCaster)) iRWSpec = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (GetHasFeat(FEAT_RW_TF_TRS, oCaster)) iRWSpec = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (iSpellSchool == iRWSpec)
|
||||
{
|
||||
nDC = 1;
|
||||
}
|
||||
return nDC;
|
||||
}
|
||||
|
||||
// Shadow Weave Feat
|
||||
// DC +1 (school Ench,Illu,Necro)
|
||||
int ShadowWeaveDC(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int iShadow = GetLevelByClass(CLASS_TYPE_SHADOW_ADEPT, oCaster);
|
||||
int nDC;
|
||||
|
||||
if (iShadow > 0)
|
||||
{
|
||||
int nSpell = PRCGetSpellId();
|
||||
string sSpellSchool = lookup_spell_school(nSpell);
|
||||
int iSpellSchool;
|
||||
|
||||
if (sSpellSchool == "A") iSpellSchool = SPELL_SCHOOL_ABJURATION;
|
||||
else if (sSpellSchool == "C") iSpellSchool = SPELL_SCHOOL_CONJURATION;
|
||||
else if (sSpellSchool == "D") iSpellSchool = SPELL_SCHOOL_DIVINATION;
|
||||
else if (sSpellSchool == "E") iSpellSchool = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sSpellSchool == "V") iSpellSchool = SPELL_SCHOOL_EVOCATION;
|
||||
else if (sSpellSchool == "I") iSpellSchool = SPELL_SCHOOL_ILLUSION;
|
||||
else if (sSpellSchool == "N") iSpellSchool = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sSpellSchool == "T") iSpellSchool = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (iSpellSchool == SPELL_SCHOOL_ENCHANTMENT || iSpellSchool == SPELL_SCHOOL_NECROMANCY || iSpellSchool == SPELL_SCHOOL_ILLUSION)
|
||||
{
|
||||
|
||||
if (iShadow > 29) nDC = 10;
|
||||
else if (iShadow > 26) nDC = 9;
|
||||
else if (iShadow > 23) nDC = 8;
|
||||
else if (iShadow > 20) nDC = 7;
|
||||
else if (iShadow > 17) nDC = 6;
|
||||
else if (iShadow > 14) nDC = 5;
|
||||
else if (iShadow > 11) nDC = 4;
|
||||
else if (iShadow > 8) nDC = 3;
|
||||
else if (iShadow > 5) nDC = 2;
|
||||
else if (iShadow > 2) nDC = 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//SendMessageToPC(GetFirstPC(), "Your Spell DC modifier is " + IntToString(nDC));
|
||||
return nDC;
|
||||
}
|
||||
|
||||
int KOTCSpellFocusVsDemons(object oTarget, object oCaster)
|
||||
{
|
||||
int nDC = 0;
|
||||
int iKOTC = GetLevelByClass(CLASS_TYPE_KNIGHT_CHALICE, oCaster);
|
||||
|
||||
if (iKOTC >= 1)
|
||||
{
|
||||
if (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_OUTSIDER)
|
||||
{
|
||||
if (GetAlignmentGoodEvil(oTarget) == ALIGNMENT_EVIL)
|
||||
{
|
||||
nDC = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nDC;
|
||||
}
|
||||
|
||||
int BloodMagusBloodComponent(object oCaster)
|
||||
{
|
||||
int nDC = 0;
|
||||
if (GetLevelByClass(CLASS_TYPE_BLOOD_MAGUS, oCaster) > 0 && GetLocalInt(oCaster, "BloodComponent") == TRUE)
|
||||
{
|
||||
nDC = 1;
|
||||
effect eSelfDamage = EffectDamage(1, DAMAGE_TYPE_MAGICAL);
|
||||
// To make sure it doesn't cause a conc check
|
||||
DelayCommand(1.0, ApplyEffectToObject(DURATION_TYPE_INSTANT, eSelfDamage, oCaster));
|
||||
}
|
||||
return nDC;
|
||||
}
|
||||
|
||||
int RunecasterRunePowerDC(object oCaster)
|
||||
{
|
||||
int nDC = 0;
|
||||
int nClass = GetLevelByClass(CLASS_TYPE_RUNECASTER, oCaster);
|
||||
if (nClass >= 2)
|
||||
{
|
||||
if (nClass >= 30) nDC = 10;
|
||||
else if (nClass >= 27) nDC = 9;
|
||||
else if (nClass >= 24) nDC = 8;
|
||||
else if (nClass >= 21) nDC = 7;
|
||||
else if (nClass >= 18) nDC = 6;
|
||||
else if (nClass >= 15) nDC = 5;
|
||||
else if (nClass >= 12) nDC = 4;
|
||||
else if (nClass >= 9) nDC = 3;
|
||||
else if (nClass >= 5) nDC = 2;
|
||||
else if (nClass >= 2) nDC = 1;
|
||||
}
|
||||
return nDC;
|
||||
}
|
||||
|
||||
int PRCGetSaveDC(object oTarget, object oCaster, int nSpellID = -1)
|
||||
{
|
||||
if(nSpellID == -1)
|
||||
nSpellID = PRCGetSpellId();
|
||||
//10+spelllevel+stat(cha default)
|
||||
int nDC = GetSpellSaveDC();
|
||||
// For when you want to assign the caster DC
|
||||
//this does take feat/race/class into account, it only overrides the baseDC
|
||||
if (GetLocalInt(oCaster, PRC_DC_BASE_OVERRIDE) != 0)
|
||||
{
|
||||
nDC = GetLocalInt(oCaster, PRC_DC_BASE_OVERRIDE);
|
||||
SendMessageToPC(oCaster, "Forced Base-DC casting at DC " + IntToString(nDC));
|
||||
}
|
||||
nDC += GetChangesToSaveDC(oTarget, oCaster, nSpellID);
|
||||
return nDC;
|
||||
|
||||
}
|
||||
|
||||
//called just from above and from inc_epicspells
|
||||
int GetChangesToSaveDC(object oTarget, object oCaster = OBJECT_SELF, int nSpellID = -1)
|
||||
{
|
||||
if(nSpellID == -1)
|
||||
nSpellID = PRCGetSpellId();
|
||||
int nDC;
|
||||
nDC += ElementalSavantDC(nSpellID, oCaster);
|
||||
nDC += GetHierophantSLAAdjustment(nSpellID, oCaster);
|
||||
nDC += GetHeartWarderDC(nSpellID, oCaster);
|
||||
nDC += GetSpellPowerBonus(oCaster);
|
||||
nDC += ShadowWeaveDC(nSpellID, oCaster);
|
||||
nDC += RedWizardDC(nSpellID, oCaster);
|
||||
nDC += TattooFocus(nSpellID, oCaster);
|
||||
nDC += KOTCSpellFocusVsDemons(oTarget, oCaster);
|
||||
nDC += BloodMagusBloodComponent(oCaster);
|
||||
nDC += RunecasterRunePowerDC(oCaster);
|
||||
nDC += GetLocalInt(oCaster, PRC_DC_ADJUSTMENT);//this is for builder use
|
||||
return nDC;
|
||||
|
||||
}
|
||||
280
trunk/users/Stratovarius/prc_add_spl_pen.nss
Normal file
280
trunk/users/Stratovarius/prc_add_spl_pen.nss
Normal file
@@ -0,0 +1,280 @@
|
||||
|
||||
|
||||
// Use this function to get the adjustments to a spell or SLAs spell penetration
|
||||
// from the various class effects
|
||||
// Update this function if any new classes change spell pentration
|
||||
int add_spl_pen(object oCaster = OBJECT_SELF);
|
||||
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_alterations"
|
||||
#include "prcsp_archmaginc"
|
||||
|
||||
int GetHeartWarderPene(int spell_id, object oCaster = OBJECT_SELF) {
|
||||
// Guard Expensive Calculations
|
||||
if (!GetHasFeat(FEAT_VOICE_SIREN, oCaster)) return 0;
|
||||
|
||||
int nSchool = GetLocalInt(OBJECT_SELF,"X2_L_LAST_SPELLSCHOOL_VAR");
|
||||
|
||||
if ( nSchool != SPELL_SCHOOL_ENCHANTMENT) return 0;
|
||||
|
||||
// Bonus Requires Verbal Spells
|
||||
string VS = lookup_spell_vs(spell_id);
|
||||
if (VS != "v" && VS != "vs")
|
||||
return 0;
|
||||
|
||||
// These feats provide greater bonuses or remove the Verbal requirement
|
||||
if (PRCGetMetaMagicFeat() & METAMAGIC_SILENT
|
||||
|| GetHasFeat(FEAT_SPELL_PENETRATION, oCaster)
|
||||
|| GetHasFeat(FEAT_GREATER_SPELL_PENETRATION, oCaster)
|
||||
|| GetHasFeat(FEAT_EPIC_SPELL_PENETRATION, oCaster))
|
||||
return 0;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate Elemental Savant Contributions
|
||||
//
|
||||
int ElementalSavantSP(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int nSP = 0;
|
||||
int nES;
|
||||
|
||||
// All Elemental Savants will have this feat
|
||||
// when they first gain a penetration bonus.
|
||||
// Otherwise this would require checking ~4 items (class or specific feats)
|
||||
if (GetHasFeat(FEAT_ES_PEN_1, oCaster)) {
|
||||
// get spell elemental type
|
||||
string element = ChangedElementalType(spell_id, oCaster);
|
||||
|
||||
// Any value that does not match one of the enumerated feats
|
||||
int feat = 0;
|
||||
|
||||
// Specify the elemental type rather than lookup by class?
|
||||
if (element == "Fire")
|
||||
{
|
||||
feat = FEAT_ES_FIRE;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_FIRE,oCaster);
|
||||
}
|
||||
else if (element == "Cold")
|
||||
{
|
||||
feat = FEAT_ES_COLD;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_COLD,oCaster);
|
||||
}
|
||||
else if (element == "Electricity")
|
||||
{
|
||||
feat = FEAT_ES_ELEC;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_ELEC,oCaster);
|
||||
}
|
||||
else if (element == "Acid")
|
||||
{
|
||||
feat = FEAT_ES_ACID;
|
||||
nES = GetLevelByClass(CLASS_TYPE_ES_ACID,oCaster);
|
||||
}
|
||||
|
||||
// Now determine the bonus
|
||||
if (feat && GetHasFeat(feat, oCaster))
|
||||
{
|
||||
|
||||
if (nES > 28) nSP = 10;
|
||||
else if (nES > 25) nSP = 9;
|
||||
else if (nES > 22) nSP = 8;
|
||||
else if (nES > 19) nSP = 7;
|
||||
else if (nES > 16) nSP = 6;
|
||||
else if (nES > 13) nSP = 5;
|
||||
else if (nES > 10) nSP = 4;
|
||||
else if (nES > 7) nSP = 3;
|
||||
else if (nES > 4) nSP = 2;
|
||||
else if (nES > 1) nSP = 1;
|
||||
|
||||
}
|
||||
}
|
||||
// SendMessageToPC(GetFirstPC(), "Your Elemental Penetration modifier is " + IntToString(nSP));
|
||||
return nSP;
|
||||
}
|
||||
|
||||
//Red Wizard SP boost based on spell school specialization
|
||||
int RedWizardSP(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int iRedWizard = GetLevelByClass(CLASS_TYPE_RED_WIZARD, oCaster);
|
||||
int nSP;
|
||||
|
||||
if (iRedWizard > 0)
|
||||
{
|
||||
int nSpell = PRCGetSpellId();
|
||||
string sSpellSchool = lookup_spell_school(nSpell);
|
||||
int iSpellSchool;
|
||||
int iRWSpec;
|
||||
|
||||
if (sSpellSchool == "A") iSpellSchool = SPELL_SCHOOL_ABJURATION;
|
||||
else if (sSpellSchool == "C") iSpellSchool = SPELL_SCHOOL_CONJURATION;
|
||||
else if (sSpellSchool == "D") iSpellSchool = SPELL_SCHOOL_DIVINATION;
|
||||
else if (sSpellSchool == "E") iSpellSchool = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sSpellSchool == "V") iSpellSchool = SPELL_SCHOOL_EVOCATION;
|
||||
else if (sSpellSchool == "I") iSpellSchool = SPELL_SCHOOL_ILLUSION;
|
||||
else if (sSpellSchool == "N") iSpellSchool = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sSpellSchool == "T") iSpellSchool = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (GetHasFeat(FEAT_RW_TF_ABJ, oCaster)) iRWSpec = SPELL_SCHOOL_ABJURATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_CON, oCaster)) iRWSpec = SPELL_SCHOOL_CONJURATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_DIV, oCaster)) iRWSpec = SPELL_SCHOOL_DIVINATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_ENC, oCaster)) iRWSpec = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (GetHasFeat(FEAT_RW_TF_EVO, oCaster)) iRWSpec = SPELL_SCHOOL_EVOCATION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_ILL, oCaster)) iRWSpec = SPELL_SCHOOL_ILLUSION;
|
||||
else if (GetHasFeat(FEAT_RW_TF_NEC, oCaster)) iRWSpec = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (GetHasFeat(FEAT_RW_TF_TRS, oCaster)) iRWSpec = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (iSpellSchool == iRWSpec)
|
||||
{
|
||||
|
||||
nSP = 1;
|
||||
|
||||
if (iRedWizard > 29) nSP = 16;
|
||||
else if (iRedWizard > 27) nSP = 15;
|
||||
else if (iRedWizard > 25) nSP = 14;
|
||||
else if (iRedWizard > 23) nSP = 13;
|
||||
else if (iRedWizard > 21) nSP = 12;
|
||||
else if (iRedWizard > 19) nSP = 11;
|
||||
else if (iRedWizard > 17) nSP = 10;
|
||||
else if (iRedWizard > 15) nSP = 9;
|
||||
else if (iRedWizard > 13) nSP = 8;
|
||||
else if (iRedWizard > 11) nSP = 7;
|
||||
else if (iRedWizard > 9) nSP = 6;
|
||||
else if (iRedWizard > 7) nSP = 5;
|
||||
else if (iRedWizard > 5) nSP = 4;
|
||||
else if (iRedWizard > 3) nSP = 3;
|
||||
else if (iRedWizard > 1) nSP = 2;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// SendMessageToPC(GetFirstPC(), "Your Spell Power modifier is " + IntToString(nSP));
|
||||
return nSP;
|
||||
}
|
||||
|
||||
int GetSpellPenetreFocusSchool(object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int nSchool = GetLocalInt(OBJECT_SELF,"X2_L_LAST_SPELLSCHOOL_VAR");
|
||||
|
||||
if (nSchool >0){
|
||||
if (GetHasFeat(FEAT_FOCUSED_SPELL_PENETRATION_ABJURATION+nSchool-1, oCaster))
|
||||
return 4;}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetSpellPowerBonus(object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int nBonus = 0;
|
||||
|
||||
if(GetHasFeat(FEAT_SPELLPOWER_10, oCaster))
|
||||
nBonus = 10;
|
||||
else if(GetHasFeat(FEAT_SPELLPOWER_8, oCaster))
|
||||
nBonus = 8;
|
||||
else if(GetHasFeat(FEAT_SPELLPOWER_6, oCaster))
|
||||
nBonus = 6;
|
||||
else if(GetHasFeat(FEAT_SPELLPOWER_4, oCaster))
|
||||
nBonus = 4;
|
||||
else if(GetHasFeat(FEAT_SPELLPOWER_2, oCaster))
|
||||
nBonus = 2;
|
||||
|
||||
return nBonus;
|
||||
}
|
||||
|
||||
// Shadow Weave Feat
|
||||
// +1 caster level vs SR (school Ench,Illu,Necro)
|
||||
int ShadowWeavePen(int spell_id, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int iShadow = GetLevelByClass(CLASS_TYPE_SHADOW_ADEPT, oCaster);
|
||||
int nSP;
|
||||
|
||||
if (iShadow > 0)
|
||||
{
|
||||
int nSpell = PRCGetSpellId();
|
||||
string sSpellSchool = lookup_spell_school(nSpell);
|
||||
int iSpellSchool;
|
||||
|
||||
if (sSpellSchool == "A") iSpellSchool = SPELL_SCHOOL_ABJURATION;
|
||||
else if (sSpellSchool == "C") iSpellSchool = SPELL_SCHOOL_CONJURATION;
|
||||
else if (sSpellSchool == "D") iSpellSchool = SPELL_SCHOOL_DIVINATION;
|
||||
else if (sSpellSchool == "E") iSpellSchool = SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sSpellSchool == "V") iSpellSchool = SPELL_SCHOOL_EVOCATION;
|
||||
else if (sSpellSchool == "I") iSpellSchool = SPELL_SCHOOL_ILLUSION;
|
||||
else if (sSpellSchool == "N") iSpellSchool = SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sSpellSchool == "T") iSpellSchool = SPELL_SCHOOL_TRANSMUTATION;
|
||||
|
||||
if (iSpellSchool == SPELL_SCHOOL_ENCHANTMENT || iSpellSchool == SPELL_SCHOOL_NECROMANCY || iSpellSchool == SPELL_SCHOOL_ILLUSION)
|
||||
{
|
||||
|
||||
if (iShadow > 29) nSP = 10;
|
||||
else if (iShadow > 26) nSP = 9;
|
||||
else if (iShadow > 23) nSP = 8;
|
||||
else if (iShadow > 20) nSP = 7;
|
||||
else if (iShadow > 17) nSP = 6;
|
||||
else if (iShadow > 14) nSP = 5;
|
||||
else if (iShadow > 11) nSP = 4;
|
||||
else if (iShadow > 8) nSP = 3;
|
||||
else if (iShadow > 5) nSP = 2;
|
||||
else if (iShadow > 2) nSP = 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//SendMessageToPC(GetFirstPC(), "Your Spell Pen modifier is " + IntToString(nSP));
|
||||
return nSP;
|
||||
}
|
||||
|
||||
int KOTCSpellPenVsDemons(object oCaster)
|
||||
{
|
||||
int nSP = 0;
|
||||
int iKOTC = GetLevelByClass(CLASS_TYPE_KNIGHT_CHALICE, oCaster);
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
|
||||
if (iKOTC >= 1)
|
||||
{
|
||||
if (MyPRCGetRacialType(oTarget) == RACIAL_TYPE_OUTSIDER)
|
||||
{
|
||||
if (GetAlignmentGoodEvil(oTarget) == ALIGNMENT_EVIL)
|
||||
{
|
||||
nSP = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nSP;
|
||||
}
|
||||
|
||||
int RunecasterRunePowerSP(object oCaster)
|
||||
{
|
||||
int nSP = 0;
|
||||
int nClass = GetLevelByClass(CLASS_TYPE_RUNECASTER, oCaster);
|
||||
if (nClass >= 2)
|
||||
{
|
||||
if (nClass >= 30) nSP = 10;
|
||||
else if (nClass >= 27) nSP = 9;
|
||||
else if (nClass >= 24) nSP = 8;
|
||||
else if (nClass >= 21) nSP = 7;
|
||||
else if (nClass >= 18) nSP = 6;
|
||||
else if (nClass >= 15) nSP = 5;
|
||||
else if (nClass >= 12) nSP = 4;
|
||||
else if (nClass >= 9) nSP = 3;
|
||||
else if (nClass >= 5) nSP = 2;
|
||||
else if (nClass >= 2) nSP = 1;
|
||||
}
|
||||
return nSP;
|
||||
}
|
||||
|
||||
int add_spl_pen(object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int spell_id = PRCGetSpellId();
|
||||
int nSP = ElementalSavantSP(spell_id, oCaster);
|
||||
nSP += GetHeartWarderPene(spell_id, oCaster);
|
||||
nSP += RedWizardSP(spell_id, oCaster);
|
||||
nSP += GetSpellPowerBonus(oCaster);
|
||||
nSP += GetSpellPenetreFocusSchool(oCaster);
|
||||
nSP += ShadowWeavePen(spell_id,oCaster);
|
||||
nSP += KOTCSpellPenVsDemons(oCaster);
|
||||
nSP += RunecasterRunePowerSP(oCaster);
|
||||
|
||||
return nSP;
|
||||
}
|
||||
23
trunk/users/Stratovarius/prc_blm_blcomp.nss
Normal file
23
trunk/users/Stratovarius/prc_blm_blcomp.nss
Normal file
@@ -0,0 +1,23 @@
|
||||
// Written by Stratovarius
|
||||
// Turns Blood Component on and off.
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
object oPC = OBJECT_SELF;
|
||||
string nMes = "";
|
||||
|
||||
if(!GetLocalInt(oPC, "BloodComponent"))
|
||||
{
|
||||
SetLocalInt(oPC, "BloodComponent", TRUE);
|
||||
nMes = "*Blood Component Activated*";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Removes effects
|
||||
DeleteLocalInt(oPC, "BloodComponent");
|
||||
nMes = "*Blood Component Deactivated*";
|
||||
}
|
||||
|
||||
FloatingTextStringOnCreature(nMes, oPC, FALSE);
|
||||
}
|
||||
23
trunk/users/Stratovarius/prc_blm_bldseek.nss
Normal file
23
trunk/users/Stratovarius/prc_blm_bldseek.nss
Normal file
@@ -0,0 +1,23 @@
|
||||
// Written by Stratovarius
|
||||
// Turns Bloodseeking Spell on and off.
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
object oPC = OBJECT_SELF;
|
||||
string nMes = "";
|
||||
|
||||
if(!GetLocalInt(oPC, "BloodSeeking"))
|
||||
{
|
||||
SetLocalInt(oPC, "BloodSeeking", TRUE);
|
||||
nMes = "*Blood Seeking Activated*";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Removes effects
|
||||
DeleteLocalInt(oPC, "BloodSeeking");
|
||||
nMes = "*Blood Seeking Deactivated*";
|
||||
}
|
||||
|
||||
FloatingTextStringOnCreature(nMes, oPC, FALSE);
|
||||
}
|
||||
89
trunk/users/Stratovarius/prc_blm_dthknell.nss
Normal file
89
trunk/users/Stratovarius/prc_blm_dthknell.nss
Normal file
@@ -0,0 +1,89 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Death Knell
|
||||
//:: prc_blm_dthknell.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
If target creature with less than 10 HP fails save
|
||||
caster gains 1d8 temp HP, +2 Str, and +1 Caster level
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Stratovarius
|
||||
//:: Created On: Sept 3, 2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_alterations"
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_alterations"
|
||||
|
||||
#include "prc_alterations"
|
||||
|
||||
void DeathKnellCheck(object oPC)
|
||||
{
|
||||
if (!GetHasSpellEffect(2086, oPC)) // Death Knell
|
||||
{
|
||||
DeleteLocalInt(oPC, "DeathKnell");
|
||||
}
|
||||
else
|
||||
{
|
||||
DelayCommand(6.0, DeathKnellCheck(oPC));
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||
SetLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_NECROMANCY);
|
||||
|
||||
//Declare major variables
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
int iHP = GetCurrentHitPoints(oTarget);
|
||||
int nCaster = PRCGetCasterLevel(OBJECT_SELF);
|
||||
int nDuration = nCaster;
|
||||
int nBonus = d8(1);
|
||||
int nPenetr = nCaster + SPGetPenetr();
|
||||
|
||||
effect eDur = EffectVisualEffect(VFX_DUR_CESSATE_NEGATIVE);
|
||||
effect eStr = EffectAbilityIncrease(ABILITY_STRENGTH, 2);
|
||||
effect eHP = EffectTemporaryHitpoints(nBonus);
|
||||
|
||||
effect eVis2 = EffectVisualEffect(VFX_IMP_DEATH_L);
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_HOLY_AID);
|
||||
|
||||
|
||||
effect eLink = EffectLinkEffects(eStr, eDur);
|
||||
|
||||
|
||||
//Fire cast spell at event for the specified target
|
||||
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
||||
//Resist magic check
|
||||
|
||||
if (iHP < 10)
|
||||
{
|
||||
if(!PRCDoResistSpell(OBJECT_SELF, oTarget,nPenetr))
|
||||
{
|
||||
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, PRCGetSaveDC(oTarget, OBJECT_SELF)))
|
||||
{
|
||||
//Apply the VFX impact and effects
|
||||
DeathlessFrenzyCheck(oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis2, oTarget);
|
||||
|
||||
|
||||
//Apply the bonuses to the PC
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, OBJECT_SELF);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, OBJECT_SELF, TurnsToSeconds(nDuration),TRUE,-1,nCaster);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eHP, OBJECT_SELF, TurnsToSeconds(nDuration),TRUE,-1,nCaster);
|
||||
SetLocalInt(OBJECT_SELF, "DeathKnell", TRUE);
|
||||
DelayCommand(9.0, DeathKnellCheck(OBJECT_SELF));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingTextStringOnCreature("*Death Knell failure: The target isn't weak enough*", OBJECT_SELF, FALSE);
|
||||
}
|
||||
|
||||
DeleteLocalInt(OBJECT_SELF, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||
// Getting rid of the local integer storing the spellschool name
|
||||
}
|
||||
26
trunk/users/Stratovarius/prc_blm_wakebld.nss
Normal file
26
trunk/users/Stratovarius/prc_blm_wakebld.nss
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "prc_alterations"
|
||||
|
||||
void main()
|
||||
{
|
||||
//Declare major variables
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
int nDamage = d10(10);
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_DEATH_L);
|
||||
effect eDam = EffectDamage(nDamage, DAMAGE_TYPE_MAGICAL);
|
||||
|
||||
|
||||
int nTouchAttack = PRCDoMeleeTouchAttack(oTarget);;
|
||||
if (nTouchAttack > 0)
|
||||
{
|
||||
// This ability does not work on critical immunes.
|
||||
if(!GetIsReactionTypeFriendly(oTarget) && !GetIsImmune(oTarget, IMMUNITY_TYPE_CRITICAL_HIT))
|
||||
{
|
||||
//Fire cast spell at event for the specified target
|
||||
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, GetSpellId()));
|
||||
//Apply the VFX impact and effects
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
51
trunk/users/Stratovarius/prc_bloodmagus.nss
Normal file
51
trunk/users/Stratovarius/prc_bloodmagus.nss
Normal file
@@ -0,0 +1,51 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Blood Magus
|
||||
//:: prc_bloodmagus.nss
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Check to see which Blood Magus feats a creature
|
||||
//:: has and apply the appropriate bonuses.
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Stratovarius
|
||||
//:: Created On: Sept 3, 2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_alterations"
|
||||
|
||||
/// Class level to Conc /////////
|
||||
void DurableCasting(object oPC, object oSkin, int nBlood)
|
||||
{
|
||||
|
||||
if(GetLocalInt(oSkin, "DurableCasting") == nBlood) return;
|
||||
|
||||
SetCompositeBonus(oSkin, "DurableCasting", nBlood, ITEM_PROPERTY_SKILL_BONUS, SKILL_CONCENTRATION);
|
||||
}
|
||||
|
||||
void Infusion(object oPC, object oSkin, int iLevel)
|
||||
{
|
||||
string sFlag = "BloodMagusInfusion";
|
||||
|
||||
if(GetLocalInt(oSkin, sFlag) == iLevel) return;
|
||||
|
||||
SetCompositeBonus(oSkin, sFlag, iLevel, ITEM_PROPERTY_ABILITY_BONUS, IP_CONST_ABILITY_CON);
|
||||
SetLocalInt(oSkin, sFlag, iLevel);
|
||||
}
|
||||
|
||||
void ThickerThanWater(object oPC, object oSkin)
|
||||
{
|
||||
if(GetLocalInt(oSkin, "ThickerThanWater") == TRUE) return;
|
||||
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_PIERCING, IP_CONST_DAMAGERESIST_1), oSkin);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ItemPropertyDamageResistance(IP_CONST_DAMAGETYPE_SLASHING, IP_CONST_DAMAGERESIST_1), oSkin);
|
||||
SetLocalInt(oSkin, "ThickerThanWater", TRUE);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
object oSkin = GetPCSkin(oPC);
|
||||
int nBlood = GetLevelByClass(CLASS_TYPE_BLOOD_MAGUS, oPC);
|
||||
|
||||
if(nBlood >= 1) DurableCasting(oPC, oSkin, nBlood);
|
||||
if(nBlood >= 7) ThickerThanWater(oPC, oSkin);
|
||||
if(nBlood >= 9) Infusion(oPC, oSkin, 2);
|
||||
}
|
||||
4
trunk/users/Tenjac/config.make.txt
Normal file
4
trunk/users/Tenjac/config.make.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
NWN_DIR = F:\Program Files (x86)\GOG Galaxy\Games\Neverwinter Nights Enhanced Edition\
|
||||
PRC_VERSION = 4.0.2
|
||||
PRC_INSTALLVERSION = 4.0.2
|
||||
NWN_DOC_DIR = C:\Users\wesle\OneDrive\Documents\Neverwinter Nights
|
||||
2657
trunk/users/Tenjac/nss.syn
Normal file
2657
trunk/users/Tenjac/nss.syn
Normal file
File diff suppressed because it is too large
Load Diff
4
trunk/users/Tenjac/prc_crft_alchemy.nss
Normal file
4
trunk/users/Tenjac/prc_crft_alchemy.nss
Normal file
@@ -0,0 +1,4 @@
|
||||
//////////////////////////////////////////////////////////
|
||||
//
|
||||
//
|
||||
//////////////////////////////////////////////////////////
|
||||
295
trunk/users/Tenjac/prc_crft_poison.nss
Normal file
295
trunk/users/Tenjac/prc_crft_poison.nss
Normal file
@@ -0,0 +1,295 @@
|
||||
///////////////////////////////////////////////////
|
||||
// Craft Poison Convo
|
||||
// prc_crft_poison
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
#include "prc_inc_spells"
|
||||
#include "inc_dynconv"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Constant defintions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const int STAGE_ENTRY =0;
|
||||
const int STAGE_POISON =1;
|
||||
const int STAGE_CONFIRM =2;
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Aid functions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void AddToTempList(object oPC, string sChoice, int nChoice)
|
||||
{
|
||||
if(DEBUG_LIST) DoDebug("\nAdding to temp list: '" + sChoice + "' - " + IntToString(nChoice));
|
||||
if(DEBUG_LIST) PrintList(oPC);
|
||||
// If there is nothing yet
|
||||
if(!GetLocalInt(oPC, "PRC_CRAFT_CONVO_ListInited"))
|
||||
{
|
||||
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head", sChoice);
|
||||
SetLocalInt(oPC, "PRC_CRAFT_CONVO_List_" + sChoice, nChoice);
|
||||
|
||||
SetLocalInt(oPC, "PRC_CRAFT_CONVO_ListInited", TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find the location to instert into
|
||||
string sPrev = "", sNext = GetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head");
|
||||
while(sNext != "" && StringCompare(sChoice, sNext) >= 0)
|
||||
{
|
||||
if(DEBUG_LIST) DoDebug("Comparison between '" + sChoice + "' and '" + sNext + "' = " + IntToString(StringCompare(sChoice, sNext)));
|
||||
sPrev = sNext;
|
||||
sNext = GetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sNext);
|
||||
}
|
||||
|
||||
// Insert the new entry
|
||||
// Does it replace the head?
|
||||
if(sPrev == "")
|
||||
{
|
||||
if(DEBUG_LIST) DoDebug("New head");
|
||||
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Head", sChoice);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG_LIST) DoDebug("Inserting into position between '" + sPrev + "' and '" + sNext + "'");
|
||||
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sPrev, sChoice);
|
||||
}
|
||||
|
||||
SetLocalString(oPC, "PRC_CRAFT_CONVO_List_Next_" + sChoice, sNext);
|
||||
SetLocalInt(oPC, "PRC_CRAFT_CONVO_List_" + sChoice, nChoice);
|
||||
}
|
||||
}
|
||||
|
||||
//Adds names to a list based on sTable (2da), delayed recursion
|
||||
|
||||
// to avoid TMI
|
||||
|
||||
void PopulateList(object oPC, int MaxValue, int bSort, string sTable, object oItem = OBJECT_INVALID, int i = 0)
|
||||
{
|
||||
|
||||
if(GetLocalInt(oPC, "DynConv_Waiting") == FALSE)
|
||||
|
||||
return;
|
||||
|
||||
if(i <= MaxValue)
|
||||
|
||||
{
|
||||
int bValid = TRUE;
|
||||
string sTemp = "";
|
||||
bValid = array_get_int(oPC, PRC_CRAFT_ITEMPROP_ARRAY, i);
|
||||
|
||||
sTemp = Get2DACache(sTable, "Name", i);
|
||||
|
||||
if((sTemp != "") && bValid)//this is going to kill
|
||||
{
|
||||
if(sTable == "iprp_spells")
|
||||
{
|
||||
string sIndex = Get2DACache(sTable, "SpellIndex", i);
|
||||
if(sIndex != GetLocalString(oPC, "LastSpell"))
|
||||
|
||||
{ //don't add if it's a repeat
|
||||
|
||||
if(bSort) AddToTempList(oPC, ActionString(GetStringByStrRef(StringToInt(sTemp))), i);
|
||||
else AddChoice(ActionString(GetStringByStrRef(StringToInt(sTemp))), i, oPC);
|
||||
|
||||
SetLocalString(oPC, "LastSpell", sIndex);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if(bSort) AddToTempList(oPC, ActionString(GetStringByStrRef(StringToInt(sTemp))), i);
|
||||
else AddChoice(ActionString(GetStringByStrRef(StringToInt(sTemp))), i, oPC);
|
||||
}
|
||||
}
|
||||
|
||||
if(!(i % 100) && i) //i != 0, i % 100 == 0
|
||||
FloatingTextStringOnCreature("*Tick*", oPC, FALSE);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if(bSort) TransferTempList(oPC);
|
||||
DeleteLocalInt(oPC, "DynConv_Waiting");
|
||||
FloatingTextStringOnCreature("*Done*", oPC, FALSE);
|
||||
return;
|
||||
}
|
||||
DelayCommand(0.01, PopulateList(oPC, MaxValue, bSort, sTable, oItem, i + 1));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Main function */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = GetPCSpeaker();
|
||||
/* Get the value of the local variable set by the conversation script calling
|
||||
* this script. Values:
|
||||
* DYNCONV_ABORTED Conversation aborted
|
||||
* DYNCONV_EXITED Conversation exited via the exit node
|
||||
* DYNCONV_SETUP_STAGE System's reply turn
|
||||
* 0 Error - something else called the script
|
||||
* Other The user made a choice
|
||||
*/
|
||||
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
|
||||
// The stage is used to determine the active conversation node.
|
||||
// 0 is the entry node.
|
||||
int nStage = GetStage(oPC);
|
||||
|
||||
int nPoison = GetSkillRank(SKILL_CRAFT_POISON, oPC);
|
||||
int nAlchem = GetSkillRank(SKILL_CRAFT_ALCHEMY, oPC);
|
||||
|
||||
// Check which of the conversation scripts called the scripts
|
||||
if(nValue == 0) // All of them set the DynConv_Var to non-zero value, so something is wrong -> abort
|
||||
return;
|
||||
|
||||
if(nValue == DYNCONV_SETUP_STAGE)
|
||||
{
|
||||
// Check if this stage is marked as already set up
|
||||
// This stops list duplication when scrolling
|
||||
if(!GetIsStageSetUp(nStage, oPC))
|
||||
{
|
||||
// variable named nStage determines the current conversation node
|
||||
// Function SetHeader to set the text displayed to the PC
|
||||
// Function AddChoice to add a response option for the PC. The responses are show in order added
|
||||
if(nStage == STAGE_ENTRY)
|
||||
{
|
||||
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
|
||||
SetHeader("Would you like to craft a poison?");
|
||||
AddChoice("Yes.", 1);
|
||||
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
}
|
||||
|
||||
if(nStage == STAGE_POISON)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_crft_poison: Building poison selection");
|
||||
SetHeader("Which poison would you like to create?");
|
||||
|
||||
//Read 2da and setup choices
|
||||
PopulateList(oPC, PRCGetFileEnd("prc_craft_poison"), TRUE, "prc_craft_poison");
|
||||
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
SetDefaultTokens();
|
||||
}
|
||||
|
||||
else if (nStage == STAGE_CONFIRM)
|
||||
{
|
||||
SetHeader("Are you sure you want to create this item?");
|
||||
|
||||
AddChoice("Back", CHOICE_BACK, oPC);
|
||||
|
||||
if(GetGold(oPC) >= nCost) AddChoice("Confirm", CHOICE_CONFIRM_CRAFT, oPC);
|
||||
MarkStageSetUp(nStage);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("Invalid Stage: " + IntToString(nStage));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Do token setup
|
||||
SetupTokens();
|
||||
|
||||
// End of conversation cleanup
|
||||
else if(nValue == DYNCONV_EXITED)
|
||||
{
|
||||
// Add any locals set through this conversation
|
||||
DeleteLocalInt(oPC, "PRC_CRAFT_COST");
|
||||
DeleteLocalInt(oPC, "PRC_CRAFT_DC");
|
||||
DeleteLocalString(oPC, "PRC_CRAFT_RESREF");
|
||||
DeleteLocalInt(oPC, "PRC_CRAFT_SKILLUSED");
|
||||
}
|
||||
// Abort conversation cleanup.
|
||||
// NOTE: This section is only run when the conversation is aborted
|
||||
// while aborting is allowed. When it isn't, the dynconvo infrastructure
|
||||
// handles restoring the conversation in a transparent manner
|
||||
else if(nValue == DYNCONV_ABORTED)
|
||||
{
|
||||
DeleteLocalInt(oPC, "PRC_CRAFT_COST");
|
||||
DeleteLocalInt(oPC, "PRC_CRAFT_DC");
|
||||
DeleteLocalString(oPC, "PRC_CRAFT_RESREF");
|
||||
DeleteLocalInt(oPC, "PRC_CRAFT_SKILLUSED");
|
||||
// Add any locals set through this conversation
|
||||
if(DEBUG) DoDebug("prc_craft: ERROR: Conversation abort section run");
|
||||
}
|
||||
// Handle PC responses
|
||||
else
|
||||
{
|
||||
// variable named nChoice is the value of the player's choice as stored when building the choice list
|
||||
// variable named nStage determines the current conversation node
|
||||
int nChoice = GetChoice(oPC);
|
||||
if(nStage == STAGE_ENTRY)
|
||||
{
|
||||
if(nChoice == 1) nStage = STAGE_POISON;
|
||||
// Move to another stage based on response, for example
|
||||
//nStage = STAGE_QUUX;
|
||||
}
|
||||
|
||||
else if(nStage == STAGE_POISON)
|
||||
{
|
||||
//Create choice list
|
||||
|
||||
}
|
||||
|
||||
else if(nStage == STAGE_CONFIRM)
|
||||
{
|
||||
if(nChoice == CHOICE_ABORT_CRAFT)
|
||||
{
|
||||
nStage = STAGE_ENTRY;
|
||||
}
|
||||
|
||||
else if(nChoice == CHOICE_CONFIRM_CRAFT)
|
||||
{
|
||||
int n2daLine = nChoice--;
|
||||
if(n2daLine < 0) SendMessageToPC(oPC, "Invalid prc_crft_poison.2da line");
|
||||
int nDC = StringToInt(Get2daCache("prc_crft_poison", "CraftDC", n2daLine));
|
||||
int nCost = StringToInt(Get2daCache("prc_crft_poison", "GoldCost", n2daLine));
|
||||
string sPoison = Get2daCache("prc_crft_poison", "Poison2daLine", n2daLine);
|
||||
int nName = StringToInt(Get2daCache("prc_crft_poison", "Name", n2daLine));
|
||||
int nDesc = StringToInt(Get2daCache("prc_crft_poison", "Description", n2daLine));
|
||||
int nType = StringToInt(Get2daCache("prc_crft_poison", "PoisonType", n2daLine));
|
||||
nSkill = SKILL_CRAFT_POISON;
|
||||
|
||||
//Use alchemy skill if it is 5 or more higher than craft(poisonmaking). DC is increased by 4.
|
||||
if((nAlchem - nPoison) >4)
|
||||
{
|
||||
nSkill = SKILL_CRAFT_ALCHEMY;
|
||||
nDC += 4;
|
||||
SendMessageToPC(oPC, "Using craft(alchemy) instead of craft(poison). New DC is "+ IntToString(nDC) + ".");
|
||||
}
|
||||
|
||||
TakeGoldFromCreature(nCost, oPC, TRUE);
|
||||
if(GetIsSkillSuccessful(oPC, nSkill), nDC))
|
||||
{
|
||||
SendMessageToPc(oPC, "Item successfully created.");
|
||||
object oTarget; CreateItemOnObject("prc_it_poison", oPC, 1, "prc_it_pois" + sPoison);
|
||||
|
||||
if(nType == 0) CreateItemOnObject("prc_it_poist0", oPC, 1, "prc_it_pois" + sPoison);
|
||||
|
||||
else if(nType == 1) CreateItemOnObject("prc_it_poist1", oPC, 1, "prc_it_pois" + sPoison);
|
||||
|
||||
else if(nType == 2) CreateItemOnObject("prc_it_poist2", oPC, 1, "prc_it_pois" + sPoison);
|
||||
|
||||
else if(nType == 3) CreateItemOnObject("prc_it_poist3", oPC, 1, "prc_it_pois" + sPoison);
|
||||
|
||||
else
|
||||
{
|
||||
SendMessageToPC(oPC, "Invalid poison type. Aborting."
|
||||
GiveGoldToCreature(oPC, nCost);
|
||||
return;
|
||||
}
|
||||
|
||||
//Set name and descrip
|
||||
SetName(oTarget, GetStringByStrRef(nName));
|
||||
SetDescription(oTarget, GetStringByStrRef(nDesc));
|
||||
}
|
||||
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
|
||||
}
|
||||
}
|
||||
// Store the stage value. If it has been changed, this clears out the choices
|
||||
SetStage(nStage, oPC);
|
||||
}
|
||||
}
|
||||
BIN
trunk/users/Tenjac/spells worksheet.ods
Normal file
BIN
trunk/users/Tenjac/spells worksheet.ods
Normal file
Binary file not shown.
27
trunk/users/Tenjac/spells/Template.nss
Normal file
27
trunk/users/Tenjac/spells/Template.nss
Normal file
@@ -0,0 +1,27 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name
|
||||
//:: FileName sp_.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
100
trunk/users/Tenjac/spells/prc_axiowater.nss
Normal file
100
trunk/users/Tenjac/spells/prc_axiowater.nss
Normal file
@@ -0,0 +1,100 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Axiomatic Water Impact Script
|
||||
//:: FileName prc_axiowater.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Lawful]
|
||||
Level: Cleric 1, Paladin 1,
|
||||
Components: V, S, M,
|
||||
Casting Time: 1 minute
|
||||
Range: Touch
|
||||
Target: Flask of water touched
|
||||
Duration: Instantaneous
|
||||
Saving Throw: Will negates (object)
|
||||
Spell Resistance: Yes (object)
|
||||
|
||||
You speak the ancient, slippery words as you pour the iron and silver into the flask. Despite the fact that there
|
||||
is more powder than will fit in the container, all of it dissolves, leaving a flask of water dotted with motes of gunmetal gray.
|
||||
|
||||
This transmutation imbues a flask (1 pint) of water with the order of law, turning it into axiomatic water. Axiomati
|
||||
water damages chaotic outsiders the way holy water damages undead and evil outsiders. A flask of axiomatic water can
|
||||
be thrown as a splash weapon. Treat this attack as a ranged touch attack with a range increment of 10 feet. A flask
|
||||
breaks if thrown against the body of a corporeal creature, but to use it against an incorporeal creature, the bearer
|
||||
must open the flask and pout the axiomatic water out onto the target. Thus, a character can douse an incorporeal
|
||||
creature with axiomatic water only if he is adjacent to it. Doing so is a ranged touch attack that does not provoke
|
||||
attacks of opportunity.
|
||||
|
||||
A direct hit by a flask of axiomatic water deals 2d4 points of damage to a chaotic outsider. Each such creature
|
||||
within 5 feet of the point where the flask hits takes 1 point of damage from the splash.
|
||||
|
||||
Material Component: 5 pounds of powdered iron and silver (worth 25 gp).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/10/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
#include "prc_inc_sp_tch"
|
||||
|
||||
void main()
|
||||
{
|
||||
location lTarget = GetSpellTargetLocation();
|
||||
float fRadius = FeetToMeters(5);
|
||||
int nTouch;
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_HEAD_HOLY);
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
|
||||
//Targeted a creature
|
||||
if (GetIsObjectValid(oTarget) == TRUE)
|
||||
{
|
||||
nTouch = PRCDoRangedTouchAttack(oTarget);
|
||||
}
|
||||
|
||||
//Hit
|
||||
if(nTouch >= 1)
|
||||
{
|
||||
int nDirectDam = d4(2);
|
||||
}
|
||||
|
||||
//Critical
|
||||
if(nTouch == 2)
|
||||
{
|
||||
nDam += nDam;
|
||||
}
|
||||
|
||||
effect eDam = EffectDamage(nDam, DAMAGE_TYPE_DIVINE);
|
||||
object oDoNotDam = oTarget;
|
||||
|
||||
//Outsider
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_OUTSIDER)
|
||||
{
|
||||
//Chaotic
|
||||
if(GetAlignmentLawChaos(oTarget) == ALIGNMENT_CHAOTIC)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eDam, oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
||||
}
|
||||
}
|
||||
|
||||
oTarget = MyGetFirstObjectInShape(SHAPE_SPHERE, fRadius, lTarget);
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(oTarget != oDoNotDam)
|
||||
{
|
||||
//Outsider
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_OUTSIDER)
|
||||
{
|
||||
//Chaotic
|
||||
if(GetAlignmentLawChaos(oTarget) == ALIGNMENT_CHAOTIC)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(1, DAMAGE_TYPE_DIVINE), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
MyGetNextObjectInShape(SHAPE_SPHERE, fRadius, lTarget);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
115
trunk/users/Tenjac/spells/prc_c_bladebane.nss
Normal file
115
trunk/users/Tenjac/spells/prc_c_bladebane.nss
Normal file
@@ -0,0 +1,115 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Short description Bladebane Conversation
|
||||
//:: filename prc_c_bladebane.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
|
||||
|
||||
@author Tenjac
|
||||
@date Created - 7/29/22
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "inc_dynconv"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Constant defintions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const int STAGE_ENTRY = 0;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Aid functions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Main function */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = GetPCSpeaker();
|
||||
/* Get the value of the local variable set by the conversation script calling
|
||||
* this script. Values:
|
||||
* DYNCONV_ABORTED Conversation aborted
|
||||
* DYNCONV_EXITED Conversation exited via the exit node
|
||||
* DYNCONV_SETUP_STAGE System's reply turn
|
||||
* 0 Error - something else called the script
|
||||
* Other The user made a choice
|
||||
*/
|
||||
int nValue = GetLocalInt(oPC, DYNCONV_VARIABLE);
|
||||
// The stage is used to determine the active conversation node.
|
||||
// 0 is the entry node.
|
||||
int nStage = GetStage(oPC);
|
||||
|
||||
// Check which of the conversation scripts called the scripts
|
||||
if(nValue == 0) // All of them set the DynConv_Var to non-zero value, so something is wrong -> abort
|
||||
return;
|
||||
|
||||
if(nValue == DYNCONV_SETUP_STAGE)
|
||||
{
|
||||
// Check if this stage is marked as already set up
|
||||
// This stops list duplication when scrolling
|
||||
if(!GetIsStageSetUp(nStage, oPC))
|
||||
{
|
||||
// variable named nStage determines the current conversation node
|
||||
// Function SetHeader to set the text displayed to the PC
|
||||
// Function AddChoice to add a response option for the PC. The responses are show in order added
|
||||
if(nStage == STAGE_ENTRY)
|
||||
{
|
||||
// Set the header
|
||||
SetHeader("Choose racial type.");
|
||||
int i;
|
||||
for (i=0; i <=254; i++)
|
||||
{
|
||||
string sName = Get2daCache("racialtypes", "Constant", i);
|
||||
// Add responses for the PC
|
||||
if(sName != "")
|
||||
{
|
||||
AddChoice(sName, i, oPC);
|
||||
}
|
||||
}
|
||||
|
||||
MarkStageSetUp(nStage, oPC); // This prevents the setup being run for this stage again until MarkStageNotSetUp is called for it
|
||||
SetDefaultTokens(); // Set the next, previous, exit and wait tokens to default values
|
||||
}
|
||||
//add more stages for more nodes with Else If clauses
|
||||
}
|
||||
|
||||
// Do token setup
|
||||
SetupTokens();
|
||||
}
|
||||
// End of conversation cleanup
|
||||
else if(nValue == DYNCONV_EXITED)
|
||||
{
|
||||
// Add any locals set through this conversation
|
||||
}
|
||||
// Abort conversation cleanup.
|
||||
// NOTE: This section is only run when the conversation is aborted
|
||||
// while aborting is allowed. When it isn't, the dynconvo infrastructure
|
||||
// handles restoring the conversation in a transparent manner
|
||||
else if(nValue == DYNCONV_ABORTED)
|
||||
{
|
||||
// Add any locals set through this conversation
|
||||
}
|
||||
// Handle PC responses
|
||||
else
|
||||
{
|
||||
// variable named nChoice is the value of the player's choice as stored when building the choice list
|
||||
// variable named nStage determines the current conversation node
|
||||
int nChoice = GetChoice(oPC);
|
||||
if(nStage == STAGE_ENTRY)
|
||||
{
|
||||
int n2daLine = nChoice--;
|
||||
SetLocalInt(oPC, "BladebaneRace", n2daLine);
|
||||
// Move to another stage based on response, for example
|
||||
//nStage = STAGE_QUUX;
|
||||
}
|
||||
|
||||
// Store the stage value. If it has been changed, this clears out the choices
|
||||
SetStage(nStage, oPC);
|
||||
}
|
||||
}
|
||||
70
trunk/users/Tenjac/spells/prc_evnt_ssf.nss
Normal file
70
trunk/users/Tenjac/spells/prc_evnt_ssf.nss
Normal file
@@ -0,0 +1,70 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Smite of Sacred Fire
|
||||
//:: FileName sp_smitesacfire.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Good]
|
||||
Level: Paladin 2,
|
||||
Components: V, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round/level; see text
|
||||
|
||||
You must cast this spell in the same round when you
|
||||
attempt a smite attack. If the attack hits, you deal
|
||||
an extra 2d6 points of damage to the target of the
|
||||
smite. Whether or not you succeed on the smite attempt,
|
||||
during each subsequent round of the spell?s duration,
|
||||
you deal an extra 2d6 points of damage on any successful
|
||||
melee attack against the target you attempted to smite.
|
||||
The spell ends prematurely after any round when you do not
|
||||
attempt a melee attack against the target you previously
|
||||
attempted to smite, or if you fail to hit with any of
|
||||
your attacks in a round.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/25/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oSpellOrigin = OBJECT_SELF;
|
||||
// find the weapon
|
||||
object oWeapon = PRCGetSpellCastItem(oSpellOrigin);
|
||||
// find the target of the spell
|
||||
object oTarget = PRCGetSpellTargetObject(oSpellOrigin);
|
||||
|
||||
//Hit in the last round
|
||||
if(GetHasSpellEffect(SPELL_SMITE_SACRED_FIRE_HIT))
|
||||
{
|
||||
//Target of the original smite
|
||||
if(GetLocalInt(oTarget, "PRCSSFTarget"));
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(DAMAGE_TYPE_DIVINE, d6(2)), oTarget);
|
||||
ActionCastSpellOnSelf(SPELL_SMITE_SACRED_FIRE_HIT);
|
||||
}
|
||||
}
|
||||
|
||||
else //We've missed; effect ends, make sure this doesn't trigger the first time
|
||||
{
|
||||
effect eToDispel = GetFirstEffect(oSpellOrigin);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_SMITE_OF_SACRED_FIRE)
|
||||
{
|
||||
RemoveEffect(oSpellOrigin, eToDispel);
|
||||
}
|
||||
eToDispel = GetNextEffect(oSpellOrigin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
42
trunk/users/Tenjac/spells/prc_rightaura.nss
Normal file
42
trunk/users/Tenjac/spells/prc_rightaura.nss
Normal file
@@ -0,0 +1,42 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Righteous Aura On Death
|
||||
//:: FileName prc_rightaura.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/20/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
int nDice = min(20, PRCGetCasterLevel(oPC) * 2);
|
||||
location lLoc = GetLocation(oPC);
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_STRIKE_HOLY), lLoc);
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(20), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(GetAlignmentGoodEvil(oTarget) == ALIGNMENT_GOOD)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectHeal(d6(nDice)), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HOLY_AID), oTarget);
|
||||
}
|
||||
|
||||
if(GetAlignmentGoodEvil(oTarget) == ALIGNMENT_EVIL)
|
||||
{
|
||||
int nDam = d6(nDice);
|
||||
//Double damage for undead
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD) nDam+=nDam;
|
||||
effect eLink = EffectLinkEffects(EffectVisualEffect(VFX_IMP_HOLY_AID), EffectDamage(DAMAGE_TYPE_DIVINE, nDam));
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oTarget);
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(20), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
}
|
||||
115
trunk/users/Tenjac/spells/sp_algnaurdisc.nss
Normal file
115
trunk/users/Tenjac/spells/sp_algnaurdisc.nss
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aligned Aura Discarge
|
||||
//:: FileName sp_algnaurdisc.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/25/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
location lLoc = GetLocation(oPC);
|
||||
int nDC;
|
||||
int nAlign;
|
||||
int nAlignTarget;
|
||||
|
||||
if (GetHasSpellEffect(SPELL_ALIGNED_AURA_LAW,oPC)) nAlign == ALIGNMENT_LAWFUL;
|
||||
else if(GetHasSpellEffect(SPELL_ALIGNED_AURA_CHAOS,oPC)) nAlign = ALIGNMENT_CHAOTIC;
|
||||
else if (GetHasSpellEffect(SPELL_ALIGNED_AURA_GOOD,oPC)) nAlign = ALIGNMENT_GOOD;
|
||||
else if (GetHasSpellEffect(SPELL_ALIGNED_AURA_EVIL,oPC)) nAlign = ALIGNMENT_EVIL;
|
||||
else SendMessageToPC(oPC, "Invalid alignment passed in script sp_algnaurdisc.nss");
|
||||
|
||||
//Get duration left
|
||||
int nEffectDuration, nEffectDurationRemaining;
|
||||
effect eEffect = GetFirstEffect(OBJECT_SELF);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
{
|
||||
if(GetEffectSpellId(eEffect) == SPELL_ALIGNED_AURA_LAW)
|
||||
{
|
||||
nEffectDuration = GetEffectDuration(eEffect);
|
||||
nEffectDurationRemaining = GetEffectDurationRemaining(eEffect);
|
||||
nAlign = ALIGNMENT_LAWFUL;
|
||||
}
|
||||
else if(GetSpellId(eEffect) == SPELL_ALIGNED_AURA_CHAOS)
|
||||
{
|
||||
nEffectDuration = GetEffectDuration(eEffect);
|
||||
nEffectDurationRemaining = GetEffectDurationRemaining(eEffect);
|
||||
nAlign = ALIGNMENT_CHAOTIC;
|
||||
}
|
||||
else if(GetSpellId(eEffect) == SPELL_ALIGNED_AURA_GOOD)
|
||||
{
|
||||
nEffectDuration = GetEffectDuration(eEffect);
|
||||
nEffectDurationRemaining = GetEffectDurationRemaining(eEffect);
|
||||
nAlign = ALIGNMENT_GOOD;
|
||||
}
|
||||
else if(GetSpellId(eEffect) == SPELL_ALIGNED_AURA_EVIL)
|
||||
{
|
||||
nEffectDuration = GetEffectDuration(eEffect);
|
||||
nEffectDurationRemaining = GetEffectDurationRemaining(eEffect);
|
||||
nAlign = ALIGNMENT_EVIL;
|
||||
}
|
||||
eEffect = GetNextEffect(OBJECT_SELF);
|
||||
}
|
||||
//GetEffectDurationRemaining returns seconds, need rounds
|
||||
int nDice = nEffectDurationRemaining / 6;
|
||||
int nDam = d4(min(15, nDice));
|
||||
|
||||
//Do the AoE
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE,FeetToMeters(60.0), lLoc);
|
||||
{
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(oTarget != oPC)
|
||||
{
|
||||
//lawful or chaotic
|
||||
if(nAlign == ALIGNMENT_LAWFUL || nAlign == ALIGNMENT_CHAOTIC) nAlignTarget = GetAlignmentLawChaos(oTarget);
|
||||
else if (nAlign == ALIGNMENT_GOOD || nAlign == ALIGNMENT_EVIL) nAlignTarget = GetAlignmentGoodEvil(oTarget);
|
||||
|
||||
//Same alignment, heal
|
||||
if(nAlign == nAlignTarget)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectHeal(nDam, oTarget), oTarget);
|
||||
}
|
||||
//Opposing alignment, damage
|
||||
if(nAlign != nAlignTarget)
|
||||
{
|
||||
nDC = PRCGetSaveDC(oTarget, oPC);
|
||||
//SR
|
||||
if(!PRCDoResistSpell(oPC, oTarget, nCasterLvl + SPGetPenetr()))
|
||||
{
|
||||
//Fort Save half
|
||||
if(PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_DIVINE)
|
||||
{
|
||||
nDam = nDam/2;
|
||||
}
|
||||
effect eDam = PRCEffectDamage(oTarget, nDam, DAMAGE_TYPE_MAGICAL);
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_DIVINE_STRIKE_HOLY);
|
||||
effect eLink = EffectLinkEffects(eDam, eVis);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(60.0), lLoc);
|
||||
}
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
68
trunk/users/Tenjac/spells/sp_alignedaura.nss
Normal file
68
trunk/users/Tenjac/spells/sp_alignedaura.nss
Normal file
@@ -0,0 +1,68 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aligned Aura
|
||||
//:: FileName sp_alignedaura.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
|
||||
Abjuration
|
||||
Level: Blackguard 4, Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft. or 60 ft.
|
||||
Area: 20-ft.-radius emanation or 60-ft.-radius burst, centered on you
|
||||
Duration: 1 round/level or until discharged
|
||||
Saving Throw: Fortitude partial
|
||||
Spell Resistance: Yes
|
||||
|
||||
A rush of divine energy flows through your holy symbol, infusing your body
|
||||
with the essence of the divine ethos. When you cast this spell, choose one
|
||||
non-neutral aspect of your own alignment<6E>chaos, evil, good, or law.
|
||||
(If you are neutral, you can select whichever alignment you wish each time
|
||||
you cast this spell). You are immediately surrounded in a 20-foot aura of
|
||||
invisible energy associated with the chosen alignment component. Anyone in
|
||||
that area who shares that alignment component gains a bonus, and anyone with
|
||||
the opposed alignment component must make a Fortitude save or take a penalty.
|
||||
The values of these modifiers and the features to which they apply are given
|
||||
on the following table. These modifiers end when the affected creature leaves
|
||||
the spell's area.
|
||||
|
||||
Alignment Bonus Penalty
|
||||
Chaos +1 on attack rolls -1 on saving throws
|
||||
Evil +1 on damage rolls -1 to Armor Class
|
||||
Good +1 on saving throws -1 on attack rolls
|
||||
Law +1 to Armor Class -1 on damage rolls
|
||||
At any point before the duration expires, you can choose to unleash the spell's
|
||||
remaining power in a 60-foot burst that deals 1d4 points of damage per round of
|
||||
duration remaining (maximum 15d4) to each creature of the opposed alignment in
|
||||
the area. Each affected creature can attempt a Fortitude save for half damage.
|
||||
The burst also heals 1 point of damage per round of duration remaining
|
||||
(maximum 15 points) for each creature of the same alignment in the area. Once
|
||||
this option is invoked, the spell ends immediately.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/24/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
int nGood = GetAlignmentGoodEvil(oPC);
|
||||
int nLaw = GetLawChaosValue(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nSpellID = PRCGetSpellId();
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(AOE_MOB_ALIGNED_AURA), oPC, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_YELLOW_WHITE), oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
119
trunk/users/Tenjac/spells/sp_alignedauraA.nss
Normal file
119
trunk/users/Tenjac/spells/sp_alignedauraA.nss
Normal file
@@ -0,0 +1,119 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aligned Aura
|
||||
//:: FileName sp_alignedaura.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
|
||||
Abjuration
|
||||
Level: Blackguard 4, Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft. or 60 ft.
|
||||
Area: 20-ft.-radius emanation or 60-ft.-radius burst, centered on you
|
||||
Duration: 1 round/level or until discharged
|
||||
Saving Throw: Fortitude partial
|
||||
Spell Resistance: Yes
|
||||
|
||||
A rush of divine energy flows through your holy symbol, infusing your body
|
||||
with the essence of the divine ethos. When you cast this spell, choose one
|
||||
non-neutral aspect of your own alignment<6E>chaos, evil, good, or law.
|
||||
(If you are neutral, you can select whichever alignment you wish each time
|
||||
you cast this spell). You are immediately surrounded in a 20-foot aura of
|
||||
invisible energy associated with the chosen alignment component. Anyone in
|
||||
that area who shares that alignment component gains a bonus, and anyone with
|
||||
the opposed alignment component must make a Fortitude save or take a penalty.
|
||||
The values of these modifiers and the features to which they apply are given
|
||||
on the following table. These modifiers end when the affected creature leaves
|
||||
the spell's area.
|
||||
|
||||
Alignment Bonus Penalty
|
||||
Chaos +1 on attack rolls -1 on saving throws
|
||||
Evil +1 on damage rolls -1 to Armor Class
|
||||
Good +1 on saving throws -1 on attack rolls
|
||||
Law +1 to Armor Class -1 on damage rolls
|
||||
At any point before the duration expires, you can choose to unleash the spell's
|
||||
remaining power in a 60-foot burst that deals 1d4 points of damage per round of
|
||||
duration remaining (maximum 15d4) to each creature of the opposed alignment in
|
||||
the area. Each affected creature can attempt a Fortitude save for half damage.
|
||||
The burst also heals 1 point of damage per round of duration remaining
|
||||
(maximum 15 points) for each creature of the same alignment in the area. Once
|
||||
this option is invoked, the spell ends immediately.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/24/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oCreator = GetAreaOfEffectCreator();
|
||||
int nGood = GetAlignmentGoodEvil(oCreator);
|
||||
int nLaw = GetLawChaosValue(oCreator);
|
||||
int nCasterLvl = PRCGetCasterLevel(oCreator);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nSpellID = PRCGetSpellId();
|
||||
int nSaveType;
|
||||
object oTarget = GetEnteringObject();
|
||||
effect eBuff;
|
||||
effect eDebuff;
|
||||
effect eVisHelp;
|
||||
effect eVisHarm;
|
||||
effect eLink;
|
||||
|
||||
if(nSpellID == SPELL_ALIGNED_AURA_CHAOS)
|
||||
{
|
||||
eBuff = EffectAttackIncrease(1);
|
||||
eDebuff = EffectSavingThrowDecrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_ALL);
|
||||
eVisHelp = EffectVisualEffect(VFX_IMP_DESTRUCTION);
|
||||
eVisHarm = EffectVisualEffect(VFX_IMP_HEAD_ODD);
|
||||
nSaveType = SAVING_THROW_TYPE_CHAOS;
|
||||
}
|
||||
if(nSpellID == SPELL_ALIGNED_AURA_EVIL)
|
||||
{
|
||||
eBuff = EffectDamageIncrease(DAMAGE_BONUS_1);
|
||||
eDebuff = EffectACDecrease(1);
|
||||
eVisHelp = EffectVisualEffect(VFX_IMP_EVIL_HELP);
|
||||
eVisHarm = EffectVisualEffect(VFX_IMP_HEAD_EVIL);
|
||||
nSaveType = SAVING_THROW_TYPE_EVIL;
|
||||
}
|
||||
if(nSpellID == SPELL_ALIGNED_AURA_GOOD)
|
||||
{
|
||||
eBuff = EffectSavingThrowIncrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_ALL;
|
||||
eDebuff = EffectAttackDecrease(1);
|
||||
eVisHelp = EffectVisualEffect(VFX_IMP_GOOD_HELP);
|
||||
eVisHarm = EffectVisualEffect(VFX_IMP_HEAD_HOLY);
|
||||
nSaveType = SAVING_THROW_TYPE_GOOD;
|
||||
}
|
||||
if(nSpellID == SPELL_ALIGNED_AURA_LAW)
|
||||
{
|
||||
eBuff = EffectACIncrease(1);
|
||||
eDebuff = EffectDamageDecrease(DAMAGE_BONUS_1, DAMAGE_TYPE_BLUDGEONING|DAMAGE_TYPE_PIERCING|DAMAGE_TYPE_SLASHING);
|
||||
eVisHelp = EffectVisualEffect(VFX_IMP_AC_BONUS);
|
||||
eVisHarm = EffectVisualEffect(VFX_IMP_HEAD_COLD);
|
||||
nSaveType = SAVING_THROW_TYPE_LAW;
|
||||
}
|
||||
if(GetIsReactionTypeFriendly(oTarget) || GetFactionEqual(oTarget))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eBuff, oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVisHelp, oTarget);
|
||||
}
|
||||
|
||||
else
|
||||
{ //Spell Resist
|
||||
if(!PRCDoResistSpell(oCaster, oTarget,nCasterLvl + SPGetPenetr()))
|
||||
{
|
||||
//Save
|
||||
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, (PRCGetSaveDC(oTarget,oCreator)), nSaveType))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDebuff, oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVisHarm, oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
68
trunk/users/Tenjac/spells/sp_alignedauraB.nss
Normal file
68
trunk/users/Tenjac/spells/sp_alignedauraB.nss
Normal file
@@ -0,0 +1,68 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aligned Aura
|
||||
//:: FileName sp_alignedaura.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
|
||||
Abjuration
|
||||
Level: Blackguard 4, Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft. or 60 ft.
|
||||
Area: 20-ft.-radius emanation or 60-ft.-radius burst, centered on you
|
||||
Duration: 1 round/level or until discharged
|
||||
Saving Throw: Fortitude partial
|
||||
Spell Resistance: Yes
|
||||
|
||||
A rush of divine energy flows through your holy symbol, infusing your body
|
||||
with the essence of the divine ethos. When you cast this spell, choose one
|
||||
non-neutral aspect of your own alignment<6E>chaos, evil, good, or law.
|
||||
(If you are neutral, you can select whichever alignment you wish each time
|
||||
you cast this spell). You are immediately surrounded in a 20-foot aura of
|
||||
invisible energy associated with the chosen alignment component. Anyone in
|
||||
that area who shares that alignment component gains a bonus, and anyone with
|
||||
the opposed alignment component must make a Fortitude save or take a penalty.
|
||||
The values of these modifiers and the features to which they apply are given
|
||||
on the following table. These modifiers end when the affected creature leaves
|
||||
the spell's area.
|
||||
|
||||
Alignment Bonus Penalty
|
||||
Chaos +1 on attack rolls -1 on saving throws
|
||||
Evil +1 on damage rolls -1 to Armor Class
|
||||
Good +1 on saving throws -1 on attack rolls
|
||||
Law +1 to Armor Class -1 on damage rolls
|
||||
At any point before the duration expires, you can choose to unleash the spell's
|
||||
remaining power in a 60-foot burst that deals 1d4 points of damage per round of
|
||||
duration remaining (maximum 15d4) to each creature of the opposed alignment in
|
||||
the area. Each affected creature can attempt a Fortitude save for half damage.
|
||||
The burst also heals 1 point of damage per round of duration remaining
|
||||
(maximum 15 points) for each creature of the same alignment in the area. Once
|
||||
this option is invoked, the spell ends immediately.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/24/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oCaster = GetAreaOfEffectCreator();
|
||||
object oTarget = GetExitingObject();
|
||||
int nSpellId
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
nSpellId = GetEffectSpellId(eToDispel);
|
||||
if(nSpellId == SPELL_ALIGNED_AURA_CHAOS || nSpellId == SPELL_ALIGNED_AURA_LAW || nSpellId == SPELL_ALIGNED_AURA_GOOD || nSpellId == SPELL_ALIGNED_AURA_EVIL)
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
60
trunk/users/Tenjac/spells/sp_angelskin.nss
Normal file
60
trunk/users/Tenjac/spells/sp_angelskin.nss
Normal file
@@ -0,0 +1,60 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Angelskin
|
||||
//:: FileName sp_angelskin.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Abjuration [Good]
|
||||
Level: Paladin 2
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Lawful good creature touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
You touch your ally with the holy symbol and invoke the blessed words. An opalescent
|
||||
glow spreads across her skin, imbuing it with a pearl-like sheen.
|
||||
|
||||
The subject gains damage reduction 5/evil.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/22/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
|
||||
if(nMetaMagic & METAMAGIC_EXTEND)
|
||||
{
|
||||
fDur += fDur;
|
||||
}
|
||||
//Alignment check
|
||||
if(GetAlignmentGoodEvil(oTarget) == ALIGNMENT_GOOD) && (GetAlignmentLawChaos(oTarget) == ALIGNMENT_LAWFUL)
|
||||
{
|
||||
effect eDR = EffectDamageReduction(5,DAMAGE_POWER_PLUS_THREE,0);
|
||||
effect eVFX = EffectVisualEffect(VFX_DUR_AURA_WHITE);
|
||||
effect eSpell = EffectLinkEffects(eDR, eVFX);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSpell, oTarget, fDur);
|
||||
}
|
||||
//Invalid target alignment
|
||||
else
|
||||
{
|
||||
SendMessageToPC(oPC, "This spell must target a lawful good creature.");
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
|
||||
67
trunk/users/Tenjac/spells/sp_auracold.nss
Normal file
67
trunk/users/Tenjac/spells/sp_auracold.nss
Normal file
@@ -0,0 +1,67 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aura of Cold
|
||||
//:: FileName sp_auracold.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Cold]
|
||||
Level: Cleric 3, Druid 3, Disciple of Thrym 3, Paladin 4, Ranger 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 5 ft.
|
||||
Area: 5-ft.-radius spherical emanation, centered on you
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: Yes
|
||||
|
||||
You are covered in a thin layer of white frost and frigid cold emanates from your
|
||||
body, dealing 1d6 points of cold damage at the start of your round to each creature
|
||||
within 5 feet.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/8/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void DoCold(object oPC, int nRounds)
|
||||
{
|
||||
if(nRounds > 0)
|
||||
{
|
||||
location lLoc=GetLocation(oPC);
|
||||
//Do the AoE
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE,FeetToMeters(5.0), lLoc);
|
||||
{
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(oTarget != oPC)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(1), DAMAGE_TYPE_COLD), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FROST_S), oTarget);
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(5.0), lLoc);
|
||||
}
|
||||
}
|
||||
nRounds--;
|
||||
DelayCommand(6.0f, DoCold(oPC, nRounds));
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nRounds = nCasterLvl;
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) nRounds += nRounds;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_BLUE_WHITE), oPC, fDur);
|
||||
|
||||
DoCold(oPC, nRounds);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
48
trunk/users/Tenjac/spells/sp_aurasun.nss
Normal file
48
trunk/users/Tenjac/spells/sp_aurasun.nss
Normal file
@@ -0,0 +1,48 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aura of the Sun
|
||||
//:: FileName sp_aurasun.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Aura of the Sun
|
||||
Abjuration [Light]
|
||||
Level: Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius emanation centered on you
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: No
|
||||
Spell Resistance: None
|
||||
|
||||
By casting aura of the sun, you fill the area around you with warm, glowing light that eliminates natural
|
||||
shadows and hampers magical darkness.Any creature attempting to cast a spell from the shadow subschool or
|
||||
a spell with the darkness descriptor within an aura of the sun must succeed on a caster level check (DC 11 +
|
||||
your caster level), or the spell fails. Areas of magical darkness originating from 3rd-level or lower spells
|
||||
and effects are temporarily suppressed when overlapping with an aura of the sun. Creatures that take penalties
|
||||
in bright light also take them while within an aura of the sun, and an undead creature takes 1d6 points of positive
|
||||
energy damage at the end of its turn every round that it spends within the spell's area.Furthermore, any creature
|
||||
attempting to hide within the aura takes a -4 penalty on Hide checks.
|
||||
This effect is centered on you and moves with you.
|
||||
Anyone who enters the aura immediately becomes subject to its effect, but creatures that leave are no longer affected.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(AOE_MOB_AURASUN), fDur, oPC);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
42
trunk/users/Tenjac/spells/sp_aurasunA.nss
Normal file
42
trunk/users/Tenjac/spells/sp_aurasunA.nss
Normal file
@@ -0,0 +1,42 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aura of the Sun On Enter
|
||||
//:: FileName sp_aurasunA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Aura of the Sun
|
||||
Abjuration [Light]
|
||||
Level: Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius emanation centered on you
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: No
|
||||
Spell Resistance: None
|
||||
|
||||
By casting aura of the sun, you fill the area around you with warm, glowing light that eliminates natural
|
||||
shadows and hampers magical darkness.Any creature attempting to cast a spell from the shadow subschool or
|
||||
a spell with the darkness descriptor within an aura of the sun must succeed on a caster level check (DC 11 +
|
||||
your caster level), or the spell fails. Areas of magical darkness originating from 3rd-level or lower spells
|
||||
and effects are temporarily suppressed when overlapping with an aura of the sun. Creatures that take penalties
|
||||
in bright light also take them while within an aura of the sun, and an undead creature takes 1d6 points of positive
|
||||
energy damage at the end of its turn every round that it spends within the spell's area.Furthermore, any creature
|
||||
attempting to hide within the aura takes a -4 penalty on Hide checks.
|
||||
This effect is centered on you and moves with you.
|
||||
Anyone who enters the aura immediately becomes subject to its effect, but creatures that leave are no longer affected.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/10/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main
|
||||
{
|
||||
object oCreator = GetAreaOfEffectCreator();
|
||||
int nCasterLvl = PRCGetCasterLvl(oCreator);
|
||||
object oTarget = GetEnteringObject();
|
||||
SPApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectSkillDecrease(SKILL_HIDE), oTarget);
|
||||
SetLocalInt(oTarget, "PRCAuraSunDC", 11 + nCasterLvl);
|
||||
}
|
||||
54
trunk/users/Tenjac/spells/sp_aurasunB.nss
Normal file
54
trunk/users/Tenjac/spells/sp_aurasunB.nss
Normal file
@@ -0,0 +1,54 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aura of the Sun On Exit
|
||||
//:: FileName sp_aurasunB.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Aura of the Sun
|
||||
Abjuration [Light]
|
||||
Level: Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius emanation centered on you
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: No
|
||||
Spell Resistance: None
|
||||
|
||||
By casting aura of the sun, you fill the area around you with warm, glowing light that eliminates natural
|
||||
shadows and hampers magical darkness.Any creature attempting to cast a spell from the shadow subschool or
|
||||
a spell with the darkness descriptor within an aura of the sun must succeed on a caster level check (DC 11 +
|
||||
your caster level), or the spell fails. Areas of magical darkness originating from 3rd-level or lower spells
|
||||
and effects are temporarily suppressed when overlapping with an aura of the sun. Creatures that take penalties
|
||||
in bright light also take them while within an aura of the sun, and an undead creature takes 1d6 points of positive
|
||||
energy damage at the end of its turn every round that it spends within the spell's area.Furthermore, any creature
|
||||
attempting to hide within the aura takes a -4 penalty on Hide checks.
|
||||
This effect is centered on you and moves with you.
|
||||
Anyone who enters the aura immediately becomes subject to its effect, but creatures that leave are no longer affected.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/10/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
void main()
|
||||
{
|
||||
object oCaster = GetAreaOfEffectCreator();
|
||||
object oTarget = GetExitingObject();
|
||||
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_AURA_OF_THE_SUN)
|
||||
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteLocalInt(oTarget, "PRCAuraSunDC");
|
||||
}
|
||||
49
trunk/users/Tenjac/spells/sp_aurasunC.nss
Normal file
49
trunk/users/Tenjac/spells/sp_aurasunC.nss
Normal file
@@ -0,0 +1,49 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Aura of the Sun Heartbeat
|
||||
//:: FileName sp_aurasunC.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Aura of the Sun
|
||||
Abjuration [Light]
|
||||
Level: Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius emanation centered on you
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: No
|
||||
Spell Resistance: None
|
||||
|
||||
By casting aura of the sun, you fill the area around you with warm, glowing light that eliminates natural
|
||||
shadows and hampers magical darkness.Any creature attempting to cast a spell from the shadow subschool or
|
||||
a spell with the darkness descriptor within an aura of the sun must succeed on a caster level check (DC 11 +
|
||||
your caster level), or the spell fails. Areas of magical darkness originating from 3rd-level or lower spells
|
||||
and effects are temporarily suppressed when overlapping with an aura of the sun. Creatures that take penalties
|
||||
in bright light also take them while within an aura of the sun, and an undead creature takes 1d6 points of positive
|
||||
energy damage at the end of its turn every round that it spends within the spell's area.Furthermore, any creature
|
||||
attempting to hide within the aura takes a -4 penalty on Hide checks.
|
||||
This effect is centered on you and moves with you.
|
||||
Anyone who enters the aura immediately becomes subject to its effect, but creatures that leave are no longer affected.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/10/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main
|
||||
{
|
||||
object oTarget = GetFirstInPersistentObject();
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_COM_HIT_DIVINE), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectDamage(oTarget, d6(1), DAMAGE_TYPE_DIVINE), oTarget);
|
||||
}
|
||||
oTarget = GetNextInPersistentObject();
|
||||
}
|
||||
|
||||
}
|
||||
105
trunk/users/Tenjac/spells/sp_axio_storm.nss
Normal file
105
trunk/users/Tenjac/spells/sp_axio_storm.nss
Normal file
@@ -0,0 +1,105 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Axiomatic Storm
|
||||
//:: FileName sp_axio_storm.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation)
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of law and a heavy rain
|
||||
begins to fall around you, its raindrops harsh and
|
||||
metallic. Above you, a jet of caustic acid lances
|
||||
down from the heavens.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed
|
||||
area once created. The storm reduces hearing and
|
||||
visibility, resulting in a <20>4 penalty on Listen, Spot,
|
||||
and Search checks. It also applies a <20>4 penalty on ranged
|
||||
attacks made into, out of, or through the storm. Finally,
|
||||
it automatically extinguishes any unprotected flames and
|
||||
has a 50% chance to extinguish protected flames (such as
|
||||
those of lanterns).
|
||||
|
||||
The rain damages chaotic creatures, dealing 2d6 points
|
||||
of damage per round (chaotic outsiders take double damage).
|
||||
In addition, each round, a gout of acid strikes a randomly
|
||||
selected chaotic outsider within the spell's area, dealing
|
||||
5d6 points of acid damage.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void DoAcid(int nCount, location lLoc, object oPC)
|
||||
{
|
||||
if(nCount >0)
|
||||
{
|
||||
object oChaotic = GetFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(20), lLoc);
|
||||
{
|
||||
while(GetIsObjectValid(oChaotic))
|
||||
{
|
||||
if(GetAlignmentLawChaos(oChaotic) == ALIGNMENT_CHAOTIC))
|
||||
{
|
||||
if(PRCGetRacialType(oChaotic) == RACIAL_TYPE_OUTSIDER))
|
||||
{
|
||||
//increment count of chaotic outsiders
|
||||
nOutsiders++;
|
||||
|
||||
//Set as a target
|
||||
SetLocalObject(oPC, "oAxioStorm" + IntToString(nOutsiders), oChaotic);
|
||||
}
|
||||
}
|
||||
oChaotic = GetNextObjectInShape(SHAPE_SPHERE, FeetToMeters(20), lLoc);
|
||||
}
|
||||
}
|
||||
//get a random number
|
||||
int nRandom = Random(nOutsiders);
|
||||
|
||||
//Get the target
|
||||
object oTarget = GetLocalObject(oPC, "oAxioStorm" + IntToString(nRandom));
|
||||
|
||||
//Deal acid damage
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectDamage(oTarget, d6(5), DAMAGE_TYPE_ACID));
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_GAS_EXPLOSION_ACID), oTarget);
|
||||
|
||||
//another round down
|
||||
nCount--;
|
||||
nOutsiders=0;
|
||||
|
||||
if(nCount >0) DelayCommand(6.0f, DoAcid(nCount, lLoc, oPC));
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nCount = nCasterLvl;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND)
|
||||
{
|
||||
fDur += fDur;
|
||||
nCount += nCount;
|
||||
}
|
||||
|
||||
//Apply AoE
|
||||
effect eAoe = EffectAreaOfEffect(AOE_PER_AXIOMATIC_STORM);
|
||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, eAoe, lLoc, fDur);
|
||||
|
||||
DoAcid(nCount, lLoc, oPC);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
60
trunk/users/Tenjac/spells/sp_axio_stormA.nss
Normal file
60
trunk/users/Tenjac/spells/sp_axio_stormA.nss
Normal file
@@ -0,0 +1,60 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Axiomatic Storm On Enter
|
||||
//:: FileName sp_axio_stormA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation)
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of law and a heavy rain
|
||||
begins to fall around you, its raindrops harsh and
|
||||
metallic. Above you, a jet of caustic acid lances
|
||||
down from the heavens.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed
|
||||
area once created. The storm reduces hearing and
|
||||
visibility, resulting in a <20>4 penalty on Listen, Spot,
|
||||
and Search checks. It also applies a <20>4 penalty on ranged
|
||||
attacks made into, out of, or through the storm. Finally,
|
||||
it automatically extinguishes any unprotected flames and
|
||||
has a 50% chance to extinguish protected flames (such as
|
||||
those of lanterns).
|
||||
|
||||
The rain damages chaotic creatures, dealing 2d6 points
|
||||
of damage per round (chaotic outsiders take double damage).
|
||||
In addition, each round, a gout of acid strikes a randomly
|
||||
selected chaotic outsider within the spell's area, dealing
|
||||
5d6 points of acid damage.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetEnteringObject();
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
effect eLink = EffectLinkEffects(EffectSkillDecrease(SKILL_LISTEN, 4), EffectSkillDecrease(SKILL_SPOT, 4));
|
||||
eLink = EffectLinkEffects(eLink, EffectSkillDecrease(SKILL_SEARCH, 4));
|
||||
|
||||
//Apply permanently, AoE exit will remove
|
||||
SPApplyEffectToObject(DURATION_TYPE_PERMANENT, eLink, oTarget);
|
||||
|
||||
if GetWeaponRanged(oItem)
|
||||
{
|
||||
SPApplyEffectToObject(DURAITON_TYPE_TEMPORARY, EffectAttackDecrease(4), oTarget, 6.0f)
|
||||
}
|
||||
|
||||
//Can't do hit penalty to ranged, approximate with hit chance
|
||||
SPApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectConcealment(20, MISS_CHANCE_TYPE_VS_RANGED), oTarget);
|
||||
}
|
||||
60
trunk/users/Tenjac/spells/sp_axio_stormB.nss
Normal file
60
trunk/users/Tenjac/spells/sp_axio_stormB.nss
Normal file
@@ -0,0 +1,60 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Axiomatic Storm
|
||||
//:: FileName sp_axio_storm.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation)
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of law and a heavy rain
|
||||
begins to fall around you, its raindrops harsh and
|
||||
metallic. Above you, a jet of caustic acid lances
|
||||
down from the heavens.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed
|
||||
area once created. The storm reduces hearing and
|
||||
visibility, resulting in a <20>4 penalty on Listen, Spot,
|
||||
and Search checks. It also applies a <20>4 penalty on ranged
|
||||
attacks made into, out of, or through the storm. Finally,
|
||||
it automatically extinguishes any unprotected flames and
|
||||
has a 50% chance to extinguish protected flames (such as
|
||||
those of lanterns).
|
||||
|
||||
The rain damages chaotic creatures, dealing 2d6 points
|
||||
of damage per round (chaotic outsiders take double damage).
|
||||
In addition, each round, a gout of acid strikes a randomly
|
||||
selected chaotic outsider within the spell's area, dealing
|
||||
5d6 points of acid damage.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
void main()
|
||||
{
|
||||
object oCaster = GetAreaOfEffectCreator();
|
||||
object oTarget = GetExitingObject();
|
||||
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_AXIOMATIC_STORM)
|
||||
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
trunk/users/Tenjac/spells/sp_axio_stormC.nss
Normal file
51
trunk/users/Tenjac/spells/sp_axio_stormC.nss
Normal file
@@ -0,0 +1,51 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Axiomatic Storm
|
||||
//:: FileName sp_axio_storm.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation)
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of law and a heavy rain
|
||||
begins to fall around you, its raindrops harsh and
|
||||
metallic. Above you, a jet of caustic acid lances
|
||||
down from the heavens.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed
|
||||
area once created. The storm reduces hearing and
|
||||
visibility, resulting in a <20>4 penalty on Listen, Spot,
|
||||
and Search checks. It also applies a <20>4 penalty on ranged
|
||||
attacks made into, out of, or through the storm. Finally,
|
||||
it automatically extinguishes any unprotected flames and
|
||||
has a 50% chance to extinguish protected flames (such as
|
||||
those of lanterns).
|
||||
|
||||
The rain damages chaotic creatures, dealing 2d6 points
|
||||
of damage per round (chaotic outsiders take double damage).
|
||||
In addition, each round, a gout of acid strikes a randomly
|
||||
selected chaotic outsider within the spell's area, dealing
|
||||
5d6 points of acid damage.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetEnteringObject();
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
if GetWeaponRanged(oItem)
|
||||
{
|
||||
SPApplyEffectToObject(oTarget, EffectAttackDecrease(4), 6.0f);
|
||||
}
|
||||
}
|
||||
45
trunk/users/Tenjac/spells/sp_axiowater.nss
Normal file
45
trunk/users/Tenjac/spells/sp_axiowater.nss
Normal file
@@ -0,0 +1,45 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Axiomatic Water
|
||||
//:: FileName sp_axiowater.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Lawful]
|
||||
Level: Cleric 1, Paladin 1,
|
||||
Components: V, S, M,
|
||||
Casting Time: 1 minute
|
||||
Range: Touch
|
||||
Target: Flask of water touched
|
||||
Duration: Instantaneous
|
||||
Saving Throw: Will negates (object)
|
||||
Spell Resistance: Yes (object)
|
||||
|
||||
You speak the ancient, slippery words as you pour the iron and silver into the flask. Despite the fact that there is more powder than will fit in the container, all of it dissolves, leaving a flask of water dotted with motes of gunmetal gray.
|
||||
|
||||
This transmutation imbues a flask (1 pint) of water with the order of law, turning it into axiomatic water. Axiomatic water damages chaotic outsiders the way holy water damages undead and evil outsiders. A flask of axiomatic water can be thrown as a splash weapon. Treat this attack as a ranged touch attack with a range increment of 10 feet. A flask breaks if thrown against the body of a corporeal creature, but to use it against an incorporeal creature, the bearer must open the flask and pout the axiomatic water out onto the target. Thus, a character can douse an incorporeal creature with axiomatic water only if he is adjacent to it. Doing so is a ranged touch attack that does not provoke attacks of opportunity.
|
||||
|
||||
A direct hit by a flask of axiomatic water deals 2d4 points of damage to a chaotic outsider. Each such creature within 5 feet of the point where the flask hits takes 1 point of damage from the splash.
|
||||
|
||||
Material Component: 5 pounds of powdered iron and silver (worth 25 gp).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/10/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
|
||||
object oPC = OBJECT_SELF;
|
||||
|
||||
CreateItemOnObject("prc_axiowater", oPC, 1);
|
||||
|
||||
PRCSetSchool();
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
69
trunk/users/Tenjac/spells/sp_bladebane.nss
Normal file
69
trunk/users/Tenjac/spells/sp_bladebane.nss
Normal file
@@ -0,0 +1,69 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Bladebane
|
||||
//:: FileName sp_bladebane.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation
|
||||
Level: Paladin 2, Cleric 3, Sorcerer 4, Wizard 4,
|
||||
Components: V, S, M,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Weapon touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: Will negates (harmless, object)
|
||||
Spell Resistance: Yes (harmless, object)
|
||||
|
||||
You impart a deadly quality to a single bladed weapon
|
||||
(any slashing weapon) for a short time.
|
||||
Bladebane confers the bane ability on the weapon touched,
|
||||
against a creature type (and subtype, if necessary) of
|
||||
your choice.
|
||||
The weapon's enhancement bonus increases by +2 against
|
||||
the appropriate creature type, and it deals +2d6 points
|
||||
of bonus damage to those creatures.
|
||||
|
||||
Material Component: A drop of blood and ruby dust worth 500 gp.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/27/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oWeapon = PRCGetSpellTargetObject();
|
||||
|
||||
//only bladed
|
||||
if(GetDamageTypeOfWeapon(oWeapon) != DAMAGE_TYPE_SLASHING)
|
||||
{
|
||||
SendMessageToPC(oPC, "Invalid target. This spell must target slashing weapons.");
|
||||
return;
|
||||
}
|
||||
|
||||
//+2 increase
|
||||
int nBonus = IPGetWeaponEnhancementBonus(oWeapon) + 2;
|
||||
|
||||
//convo for race
|
||||
SetLocalInt(oPC, "BladebaneRace");
|
||||
StartDynamicConversation("prc_c_bladebane", oPC, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oPC);
|
||||
|
||||
int nRace = GetLocalInt(oPC, "BladebaneRace");
|
||||
|
||||
itemproperty iEnhance = ItemPropertyEnhancementBonusVsRace(nRace, nBonus)
|
||||
itemproperty iDam = ItemPropertyDamageBonusVsRace(nRace, IP_CONST_DAMAGETYPE_SLASHING, IP_CONST_DAMAGEBONUS_2d6);
|
||||
|
||||
IPSafeAddItemProperty(oWeapon, iEnhance, fDur);
|
||||
IPSafeAddItemProperty(oWeapon, iDam, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
65
trunk/users/Tenjac/spells/sp_blazelight.nss
Normal file
65
trunk/users/Tenjac/spells/sp_blazelight.nss
Normal file
@@ -0,0 +1,65 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Blaze of Light
|
||||
//:: FileName sp_blazelight.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Light]
|
||||
Level: Paladin 1, Druid 2,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 60 ft.
|
||||
Area: Cone
|
||||
Duration: Instantaneous
|
||||
Saving Throw: Fortitude negates
|
||||
Spell Resistance: Yes
|
||||
|
||||
A cone of bright light shines forth from just above the caster's head.
|
||||
All creatures within the cone that fail a Fortitude saving throw are dazzled for 1 minute.
|
||||
Sightless creatures are not affected by blaze of light.
|
||||
A light spell (one with the light descriptor) counters and dispels a darkness spell
|
||||
(one with the darkness descriptor) of an equal or lower level.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/10/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
float fDur = 60.0f;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_HEAD_HOLY);
|
||||
float fRadius = FeetToMeters(60);
|
||||
location lLoc = PRCGetSpellTargetLocation();
|
||||
effect eDazzled = EffectLinkEffects(EffectAttackDecrease(1), EffectVisualEffect(VFX_DUR_MIND_AFFECTING_DISABLED));
|
||||
eDazzled = EffectLinkEffects(eDazzled, EffectSkillDecrease(SKILL_SPOT, 1));
|
||||
eDazzled = EffectLinkEffects(eDazzled, EffectSkillDecrease(SKILL_SEARCH, 1));
|
||||
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPELLCONE, fRadius, lLoc, TRUE);
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
//Resist
|
||||
if(!PRCDoResistSpell(OBJECT_SELF, oTarget,CasterLvl) && (oTarget != OBJECT_SELF))
|
||||
{
|
||||
//Fort Save
|
||||
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, PRCGetSaveDC(oTarget, oPC), SAVING_THROW_TYPE_SPELL, oPC))
|
||||
{
|
||||
//Not blind
|
||||
if(!GetHasEffect(EFFECT_TYPE_BLINDNESS, oTarget))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDazzled, oTarget, fDur);
|
||||
}
|
||||
}
|
||||
}
|
||||
MyNextObjectInShape(SHAPE_SPELLCONE, fRadius, lLoc, TRUE);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
45
trunk/users/Tenjac/spells/sp_blessedaim.nss
Normal file
45
trunk/users/Tenjac/spells/sp_blessedaim.nss
Normal file
@@ -0,0 +1,45 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Blessed Aim
|
||||
//:: FileName sp_blessedaim.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Divination
|
||||
Level: Blackguard 1, Cleric 1, Paladin 1,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 50 ft.
|
||||
Effect: 50-ft.-radius spread centered on you
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: No
|
||||
|
||||
With the blessing of your deity, you bolster your
|
||||
allies' aim with an exhortation.
|
||||
|
||||
This spell grants your allies within the spread
|
||||
a +2 morale bonus on ranged attack rolls.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On:
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_DIVINATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 60 * nCasterLvl;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
effect eAOE = EffectAreaOfEffect(AOE_PER_BLESSEDAIM);
|
||||
|
||||
SPApplyEffectToObejct(DURATION_TYPE_TEMPORARY, eAOE, oPC, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_PULSE_HOLY), oPC);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
47
trunk/users/Tenjac/spells/sp_blessedaimA.nss
Normal file
47
trunk/users/Tenjac/spells/sp_blessedaimA.nss
Normal file
@@ -0,0 +1,47 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Blessed Aim on Enter
|
||||
//:: FileName sp_blessedaimA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Blessed Aim
|
||||
Divination
|
||||
Level: Blackguard 1, Cleric 1, Paladin 1,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 50 ft.
|
||||
Effect: 50-ft.-radius spread centered on you
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: No
|
||||
|
||||
With the blessing of your deity, you bolster your allies' aim with an exhortation.
|
||||
|
||||
This spell grants your allies within the spread a +2 morale bonus on ranged attack rolls.
|
||||
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On:
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
location lLoc = GetLocation(OBJECT_SELF);
|
||||
object oItem;
|
||||
|
||||
object oTarget = GetEnteringObject();
|
||||
{
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
if(GetIsReactionTypeFriendly(oTarget))
|
||||
{
|
||||
if GetWeaponRanged(oItem)
|
||||
{
|
||||
SPApplyEffectToObject(oTarget, EffectAttackIncrease(2), 6.0f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
trunk/users/Tenjac/spells/sp_blessedaimB.nss
Normal file
32
trunk/users/Tenjac/spells/sp_blessedaimB.nss
Normal file
@@ -0,0 +1,32 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Name Blessed Aim On Exit
|
||||
//:: FileName sp_blessedaimB.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/**@file
|
||||
|
||||
Author: Tenjac
|
||||
Created: 1/27/21
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:://////////////////////////////////////////////
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_add_spell_dc"
|
||||
void main()
|
||||
{
|
||||
object oCaster = GetAreaOfEffectCreator();
|
||||
object oTarget = GetExitingObject();
|
||||
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_BLESSED_AIM)
|
||||
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
47
trunk/users/Tenjac/spells/sp_blessedaimc.nss
Normal file
47
trunk/users/Tenjac/spells/sp_blessedaimc.nss
Normal file
@@ -0,0 +1,47 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Blessed Aim Heartbeat
|
||||
//:: FileName sp_blessedaimc.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Blessed Aim
|
||||
Divination
|
||||
Level: Blackguard 1, Cleric 1, Paladin 1,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 50 ft.
|
||||
Effect: 50-ft.-radius spread centered on you
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: No
|
||||
|
||||
With the blessing of your deity, you bolster your allies' aim with an exhortation.
|
||||
|
||||
This spell grants your allies within the spread a +2 morale bonus on ranged attack rolls.
|
||||
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On:
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
location lLoc = GetLocation(OBJECT_SELF);
|
||||
object oItem;
|
||||
|
||||
object oTarget = GetFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(50.0), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
{
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
if(GetIsReactionTypeFriendly(oTarget)
|
||||
{
|
||||
if GetWeaponRanged(oItem)
|
||||
{
|
||||
SPApplyEffectToObject(oTarget, EffectAttackIncrease(2), 6.0f)
|
||||
}
|
||||
}
|
||||
oTarget = GetNextObjectInShape(SHAPE_SPHERE, FeetToMeters(50.0), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
61
trunk/users/Tenjac/spells/sp_blessright.nss
Normal file
61
trunk/users/Tenjac/spells/sp_blessright.nss
Normal file
@@ -0,0 +1,61 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Blessing of the Righteous
|
||||
//:: FileName sp_blessright.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Blessing of the Righteous
|
||||
Evocation [Good]
|
||||
Level: Cleric 4, Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 40 ft.
|
||||
Area: All allies in a 40-ft.-radius burst centered on you
|
||||
Duration: 1 round/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
A sudden burst of warm, radiant light engulfs you and your allies.
|
||||
The light fades quickly but lingers on the weapons of those affected.
|
||||
You bless yourself and your allies.
|
||||
You and your allies'melee and ranged attacks deal an extra 1d6 points
|
||||
of holy damage and are considered good-aligned for the purpose of
|
||||
overcoming damage reduction.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/26/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
location lLoc = PRCGetSpellTargetLocation();
|
||||
int nBonus = DAMAGE_BONUS_1d6;
|
||||
|
||||
if (nMetaMagic & METAMAGIC_EXTEND) fDur *= 2;
|
||||
if (nMetaMagic & METAMAGIC_MAXIMIZE) nBonus = DAMAGE_BONUS_6;
|
||||
|
||||
object oTarget = GetFirstObjectinShape(SHAPE_SPHERE, FeetToMeters(40.0), lLoc);
|
||||
|
||||
while (GetIsObjectValid(oTarget))
|
||||
{
|
||||
//if it's friendly
|
||||
if(GetIsReactionTypeFriendly(oTarget))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectDamageIncrease(nBonus, DAMAGE_TYPE_POSITIVE), oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HOLY_AID), oTarget);
|
||||
}
|
||||
OTarget = GetNextObjectInShape(SHAPE_SPHERE, FeetToMeters(40.0), lLoc);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
49
trunk/users/Tenjac/spells/sp_callmount.nss
Normal file
49
trunk/users/Tenjac/spells/sp_callmount.nss
Normal file
@@ -0,0 +1,49 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Call Mount
|
||||
//:: FileName sp_callmount.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Conjuration (Calling) [Good]
|
||||
Level: Paladin 2,
|
||||
Components: V,
|
||||
Casting Time: 1 round
|
||||
Range: 10 ft.
|
||||
Effect: Your special mount
|
||||
Duration: 1 hour/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You summon your special mount from the celestial
|
||||
planes where it resides.
|
||||
|
||||
This works exactly as your normal, spell-like class a
|
||||
bility to summon the creature, except that the duration
|
||||
is shorter and you are not limited in how many times
|
||||
you can call the mount in a day (except by how many
|
||||
times you can cast call mount).
|
||||
|
||||
You can cast this spell even if you have already
|
||||
called your mount using your class ability on the same day.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/9/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
HorseSummonPaladinMount();
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
98
trunk/users/Tenjac/spells/sp_castigate.nss
Normal file
98
trunk/users/Tenjac/spells/sp_castigate.nss
Normal file
@@ -0,0 +1,98 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Castigate
|
||||
//:: FileName sp_castigate.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Sonic]
|
||||
Level: Cleric 4, Paladin 4, Purification 4,
|
||||
Components: V,
|
||||
Casting Time: 1 standard action
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius burst centered on you
|
||||
Duration: Instantaneous
|
||||
Saving Throw: Fortitude half
|
||||
Spell Resistance: Yes
|
||||
|
||||
Shouting your deity's teachings, you rebuke your foes with the magic
|
||||
of your sacred words.
|
||||
|
||||
This spell has no effect on creatures that cannot hear.
|
||||
All creatures whose alignment differs from yours on both
|
||||
the law<61>chaos and the good<6F>evil axes take 1d4 points of damage
|
||||
per caster level (maximum 10d4). All creatures whose alignment
|
||||
differs from yours on one component take half damage, and this
|
||||
spell does not deal damage to those who share your alignment.
|
||||
|
||||
A Fortitude saving throw reduces damage by half.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int nDC = PRCGetSaveDC(oTarget, oPC);
|
||||
float fDur = 3600 * nCasterLvl;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
location lLoc = PRCGetSpellTargetLocation();
|
||||
int nAlignGE = GetAlignmentGoodEvil(oPC);
|
||||
int nAlignLC = GetAlignmentLawChaos(oPC);
|
||||
int nTargetAlignGE;
|
||||
int nTargetAlignLC;
|
||||
int nDam;
|
||||
int nLevels = min(10, nCasterLvl);
|
||||
float fRadius = FeetToMeters(10);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_FNF_HOWL_WAR_CRY), oPC);
|
||||
|
||||
object oTarget = (MyFirstObjectInShape(SHAPE_SPHERE, fRadius. lLoc, FALSE));
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
//Not deaf
|
||||
if(GetHasEffect(EFFECT_TYPE_DEAF, oTarget) == FALSE)
|
||||
{
|
||||
//SR
|
||||
if(!PRCDoResistSpell(oPC, oTarget, nCasterLvl + SPGetPenetr()))
|
||||
{
|
||||
nTargetAlignGE = GetAlignmentGoodEvil(oTarget);
|
||||
nTargetAlignLC = GetAlignmentLawChaos(oTarget);
|
||||
|
||||
//Test alignment differences
|
||||
//Both
|
||||
if(nAlignGE != nTargetAlignGE) && (nAlignLC != nTargetAlignLC)
|
||||
{
|
||||
nDam = d4(nLevels);
|
||||
}
|
||||
//Half for one
|
||||
else if(nAlignGE != nTargetAlignGE) || (nAlignLC != nTargetAlignLC)
|
||||
{
|
||||
nDam = d4(nLevels)/2;
|
||||
}
|
||||
|
||||
//save for half
|
||||
if(PRCMySavingThrow(SAVING_THROW_FORT, oTarget, nDC, SAVING_THROW_TYPE_DIVINE))
|
||||
{
|
||||
nDam = nDam/2;
|
||||
}
|
||||
|
||||
if(nDam > 0)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(nDam, DAMAGE_TYPE_DIVINE), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectvisualEffect(VFX_IMP_HEAD_HOLY), oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, fRadius. lLoc, FALSE);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
72
trunk/users/Tenjac/spells/sp_checkmlt.nss
Normal file
72
trunk/users/Tenjac/spells/sp_checkmlt.nss
Normal file
@@ -0,0 +1,72 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Checkmate's Light
|
||||
//:: FileName sp_chkmlt.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Lawful]
|
||||
Level: Paladin 2, Cleric 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Melee weapon touched
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You intone your deity's name and the weapon you touch hums a
|
||||
harmonic response before it lights up with a soothing red glow.
|
||||
|
||||
You imbue the touched weapon with a +1 enhancement bonus per
|
||||
three caster levels (maximum +5 at 15th level), and it is treated
|
||||
as lawful-aligned for the purpose of overcoming damage reduction.
|
||||
In addition, you can cause it to cast a red glow as bright as a torch.
|
||||
Any creature within the radius of its clear illumination (20 feet)
|
||||
gets a +1 morale bonus on saving throws against fear effects.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/14/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
object oWeapon = PRCGetSpellCastItem(oPC);
|
||||
|
||||
object oTarget = PRCGetSpellTargetObject(oPC);
|
||||
|
||||
if (GetIsObjectValid(oWeapon))
|
||||
{
|
||||
int nBonus = min(nCasterLvl, 15)/3;
|
||||
|
||||
//Simulating lawful as +3, so give +3 enhancement and penalty to damage and hit to offset
|
||||
if(nBonus == 1)
|
||||
{
|
||||
AddItemProperty(oWeapon, DURATION_TYPE_TEMPORARY, ItemPropertyAttackPenalty(2), fDuration);
|
||||
AddItemProperty(oWeapon, DURATION_TYPE_TEMPORARY, ItemPropertyDamagePenalty(2), fDuration);
|
||||
nBonus=3;
|
||||
}
|
||||
if (nBonus == 2)
|
||||
{
|
||||
AddItemProperty(oWeapon, DURATION_TYPE_TEMPORARY, ItemPropertyAttackPenalty(1), fDuration);
|
||||
AddItemProperty(oWeapon, DURATION_TYPE_TEMPORARY, ItemPropertyDamagePenalty(1), fDuration);
|
||||
nBonus=3;
|
||||
}
|
||||
|
||||
IPSafeAddItemProperty(oWeapon, DURATION_TYPE_TEMPORARY, ItemPropertyEnhancementBonus(nBonus), fDuration);
|
||||
IPSafeAddItemProperty(oWeapon, DURATION_TYPE_TEMPORARY, ItemPropertyVisualEffect(ITEM_VISUAL_EVIL), fDuration);
|
||||
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
45
trunk/users/Tenjac/spells/sp_clearmind.nss
Normal file
45
trunk/users/Tenjac/spells/sp_clearmind.nss
Normal file
@@ -0,0 +1,45 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Clear Mind
|
||||
//:: FileName sp_clearmind.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Clear Mind
|
||||
Abjuration
|
||||
Level: Paladin 1
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 10 minutes/level
|
||||
|
||||
A silver glow sheathes your body as you complete the spell. As the glow fades, you feel a touch
|
||||
of the divine at the back of your mind. This divine touch spreads until you feel your concerns
|
||||
and anxieties fade away.
|
||||
|
||||
You gain a +4 sacred bonus on saving throws made against mind-affecting spells and effects.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/23/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 600 * nCasterLvl;
|
||||
effect eVis = EffectVisualEffect(VFX_DUR_AURA_BLUE_LIGHT);
|
||||
effect eBuff = EffectSavingThrowIncrease(SAVING_THROW_ALL, 4, SAVING_THROW_TYPE_MIND_SPELLS);
|
||||
|
||||
SPApplyEffectToObject(oPC, DURATION_TYPE_TEMPORARY, eVis, 3.0f);
|
||||
SPApplyEffectToObject(oPC, DURATION_TYPE_TEMPORARY, eBuff, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
47
trunk/users/Tenjac/spells/sp_cloakbrave.nss
Normal file
47
trunk/users/Tenjac/spells/sp_cloakbrave.nss
Normal file
@@ -0,0 +1,47 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Cloak of Bravery
|
||||
//:: FileName sp_cloakbrave.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Abjuration [Mind-Affecting]
|
||||
Level: Paladin 2, Cleric 3, Courage 3,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 60 ft.
|
||||
Area: 60-ft.-radius emanation centered on you
|
||||
Duration: 10 minutes/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
Summoning up your courage, you throw out your arm and sweep
|
||||
it over the area, cloaking all your allies in a glittering
|
||||
mantle of magic that bolsters their bravery.
|
||||
|
||||
All allies within the emanation (including you) gain a morale
|
||||
bonus on saves against fear effects equal to your caster level
|
||||
(to a maximum of +10 at caster level 10th).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(nCasterLvl)/6;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(VFX_MOB_CLOAK_OF_BRAVERY), oPC, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_LIGHT_WHITE_20), oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
49
trunk/users/Tenjac/spells/sp_cloakbraveA.nss
Normal file
49
trunk/users/Tenjac/spells/sp_cloakbraveA.nss
Normal file
@@ -0,0 +1,49 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Cloak of Bravery On Enter
|
||||
//:: FileName sp_cloakbraveA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Abjuration [Mind-Affecting]
|
||||
Level: Paladin 2, Cleric 3, Courage 3,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 60 ft.
|
||||
Area: 60-ft.-radius emanation centered on you
|
||||
Duration: 10 minutes/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
Summoning up your courage, you throw out your arm and sweep
|
||||
it over the area, cloaking all your allies in a glittering
|
||||
mantle of magic that bolsters their bravery.
|
||||
|
||||
All allies within the emanation (including you) gain a morale
|
||||
bonus on saves against fear effects equal to your caster level
|
||||
(to a maximum of +10 at caster level 10th).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oCreator = GetAreaOfEffectCreator();
|
||||
int nCasterLvl = PRCGetCasterLevel(oCreator);
|
||||
float fDur = HoursToSeconds(nCasterLvl)/6;
|
||||
object oTarget = GetEnteringObject();
|
||||
int nBonus = min(10, nCasterLvl);
|
||||
|
||||
if(GetFactionEqual(oCreator))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSavingThrowIncrease(SAVING_THROW_ALL, nBonus, SAVING_THROW_TYPE_FEAR), oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HEAD_HOLY), oTarget);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
51
trunk/users/Tenjac/spells/sp_cloakbraveB.nss
Normal file
51
trunk/users/Tenjac/spells/sp_cloakbraveB.nss
Normal file
@@ -0,0 +1,51 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Cloak of Bravery On Exit
|
||||
//:: FileName sp_cloakbraveB.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Abjuration [Mind-Affecting]
|
||||
Level: Paladin 2, Cleric 3, Courage 3,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 60 ft.
|
||||
Area: 60-ft.-radius emanation centered on you
|
||||
Duration: 10 minutes/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
Summoning up your courage, you throw out your arm and sweep
|
||||
it over the area, cloaking all your allies in a glittering
|
||||
mantle of magic that bolsters their bravery.
|
||||
|
||||
All allies within the emanation (including you) gain a morale
|
||||
bonus on saves against fear effects equal to your caster level
|
||||
(to a maximum of +10 at caster level 10th).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oCaster = GetAreaOfEffectCreator();
|
||||
object oTarget = GetExitingObject();
|
||||
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_CLOAK_OF_BRAVERY)
|
||||
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
trunk/users/Tenjac/spells/sp_conduitlife.nss
Normal file
61
trunk/users/Tenjac/spells/sp_conduitlife.nss
Normal file
@@ -0,0 +1,61 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Conduit of Life
|
||||
//:: FileName sp_conduitlife.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Conjuration (Healing)
|
||||
Level: Cleric 2, Paladin 2,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 10 minutes/level or until discharged
|
||||
|
||||
A small kernel of positive energy grows within your
|
||||
heart, warming your whole body.
|
||||
|
||||
The next time you use a class feature or racial ability
|
||||
to channel positive energy (such as turn undead or lay on hands),
|
||||
you also heal a number of points of damage to yourself equal to
|
||||
2d10+1/caster level (maximum 10).
|
||||
|
||||
If you are already subject to an ongoing healing effect
|
||||
(such as vigor), or if you receive a cure spell while conduit
|
||||
of life is still in effect, this spell instead heals a number of
|
||||
points of damage equal to 3d8+1/caster level and it is discharged.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/5/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = nCasterLvl * 600.0f;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//Apply VFX
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_YELLOW_WHITE), oPC, fDur);
|
||||
|
||||
//Ongoing healing triggering
|
||||
effect eTest = GetFirstEffect(oTarget);
|
||||
while(GetIsEffectValid(eTest))
|
||||
{
|
||||
if (eTest == EffectRegenerate())
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectHeal(d8(3) + nCasterLvl), oPC);
|
||||
PRCRemoveSpellEffects(SPELL_CONDUIT_OF_LIFE, oPC, oPC);
|
||||
break;
|
||||
}
|
||||
eTest = GetNextEffect(oTarget);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
62
trunk/users/Tenjac/spells/sp_cursebrute.nss
Normal file
62
trunk/users/Tenjac/spells/sp_cursebrute.nss
Normal file
@@ -0,0 +1,62 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Curse of the Brute
|
||||
//:: FileName sp_cursebrute.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation
|
||||
Level: Paladin 2, Cleric 3,
|
||||
Components: V, S,
|
||||
Casting Time: 1 action
|
||||
Range: Touch
|
||||
Target: Creature touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: Fortitude negates
|
||||
Spell Resistance: Yes
|
||||
|
||||
You can grant an enhancement bonus up to +1 per caster
|
||||
level to one physical ability of the creature touched
|
||||
(Strength, Constitution, or Dexterity).
|
||||
However, this temporarily suppresses both the creature's
|
||||
Intelligence and Charisma, each by the amount of the
|
||||
enhancement bonus. If this lowers any ability below 3,
|
||||
the spell fails.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/17/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nAbilBuff;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
|
||||
int nSpell = PRCGetSpellId();
|
||||
|
||||
//Get ability by which spell is used
|
||||
if (nSpell == SPELL_CURSE_BRUTE_STR) nAbilBuff = ABILITY_STRENGTH;
|
||||
if (nSpell == SPELL_CURSE_BRUTE_DEX) nAbilBuff = ABILITY_DEXTERITY;
|
||||
if (nSpell == SPELL_CURSE_BRUTE_CON) nAbilBuff = ABILITY_CONSTITUTION;
|
||||
|
||||
//Get maximum bonus without lowering either stat below 3
|
||||
int nBonus = min(GetAbilityScore(oTarget, ABILITY_CHARISMA), GetAbilityScore(oTarget, ABILITY_INTELLIGENCE)) - 3;
|
||||
nBonus = min(nCasterLvl, nBonus);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityIncrease(nAbilBuff, nBonus), oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_INTELLIGENCE, nBonus), oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityDecrease(ABILITY_CHARISMA, nBonus), oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_RED_LIGHT), oTarget, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
93
trunk/users/Tenjac/spells/sp_denounce.nss
Normal file
93
trunk/users/Tenjac/spells/sp_denounce.nss
Normal file
@@ -0,0 +1,93 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Denounce
|
||||
//:: FileName sp_denounce.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Enchantment [Mind-Affecting]
|
||||
Level: Cleric 2, Paladin 2
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: Close (25 ft. + 5 ft./2 levels)
|
||||
Target: One outsider
|
||||
Duration: 1 min./level (D); see text
|
||||
Saving Throw: Will negates; see text
|
||||
Spell Resistance: Yes
|
||||
|
||||
You point your finger and pronounce judgment.
|
||||
You instill feelings of shame and guilt in a target outsider, imposing a -4 insight penalty
|
||||
on its attack rolls, saves, and checks. Each round on its turn, the subject can attempt a new
|
||||
saving throw to end the effect.
|
||||
|
||||
(This is a full-round action that does not provoke attacks of opportunity).
|
||||
Outsiders with the good subtype are immune to denounce.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 5/25/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void SaveCheck(object oTarget, object oPC, int nRounds)
|
||||
{
|
||||
if(GetHasSpellEffect(SPELL_DENOUNCE, oTarget))
|
||||
{
|
||||
//Save
|
||||
if(PRCMySavingThrow(SAVING_THROW_WILL, oTarget, PRCGetSaveDC(oTarget, OBJECT_SELF)))
|
||||
{
|
||||
RemoveSpellEffects(SPELL_DENOUNCE);
|
||||
}
|
||||
|
||||
//Loop for another round
|
||||
else
|
||||
{
|
||||
nRounds--;
|
||||
DelayCommand(6.0f, SaveCheck(oTarget, oPC, nRounds));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ENCHANTMENT);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 60.0f *(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = SPGetSpellTargetObject();
|
||||
int nPenetr = nCaster + SPGetPenetr();
|
||||
|
||||
if(GetObjectType(oTarget) == OBJECT_TYPE_CREATURE)
|
||||
{
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_OUTSIDER)
|
||||
{
|
||||
//No good subtypes, interpret as good alignment
|
||||
if(GetAlignmentGoodEvil(oTarget) == ALIGNMENT_GOOD)
|
||||
{
|
||||
SendMessageToPC(oPC, "Outsiders of good alignment are immune to Denounce."
|
||||
}
|
||||
//Non-good outsider; resolve spell
|
||||
else
|
||||
{
|
||||
//SR
|
||||
if(!PRCDoResistSpell(oCreator, oTarget, nPenetr))
|
||||
{
|
||||
//Save
|
||||
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, PRCGetSaveDC(oTarget, OBJECT_SELF)))
|
||||
{
|
||||
effect eLink = EffectLinkEffects(EffectAttackDecrease(4), EffectSavingThrowDecrease(SAVING_THROW_ALL, 4));
|
||||
eLink = EffectLinkEffects(eLink, EffectSkillDecrease(SKILL_ALL_SKILLS, 4));
|
||||
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_AURA_PULSE_ORANGE_WHITE));
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDur);
|
||||
DelayCommand(6.0f, SaveCheck(oTarget, oPC, FloatToInt(fDur / 6)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
48
trunk/users/Tenjac/spells/sp_devsmite.nss
Normal file
48
trunk/users/Tenjac/spells/sp_devsmite.nss
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Devastating Smite
|
||||
//:: FileName sp_devsmite.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation
|
||||
Level: Blackguard 1, Cleric 1, Paladin 1,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Touch
|
||||
Target: Creature touched
|
||||
Duration: 1 round or until discharged; see text
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
The next smite attack made by the subject deals double
|
||||
its normal smite damage. For instance, a 9th-level paladin
|
||||
normally deals an extra 9 points of damage with her smite
|
||||
evil ability. Under the effect of this spell, she would
|
||||
deal an extra 18 points of damage. The spell applies to
|
||||
only one smite attack; if that attack misses, the spell
|
||||
is lost without effect.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(1);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//Apply VFX, handle damage in smite script
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_ORANGE_WHITE), oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
77
trunk/users/Tenjac/spells/sp_diamondsteel.nss
Normal file
77
trunk/users/Tenjac/spells/sp_diamondsteel.nss
Normal file
@@ -0,0 +1,77 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Diamondsteel
|
||||
//:: FileName sp_diamondsteel.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Diamondsteel
|
||||
Transmutation
|
||||
Level: Paladin 3, Sorcerer 3, Wizard 3,
|
||||
Components: V, S, M,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Suit of metal armor touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: Will negates (object)
|
||||
Spell Resistance: Yes (object)
|
||||
|
||||
You pass your hand over the suit of armor several times before finally touching it.
|
||||
As you do so, you feel a warmth grow in the palm of your hand. The warmth passes into
|
||||
the armor and manifests as a sparkling shine.
|
||||
|
||||
Diamondsteel enhances the strength of one suit of metal armor. The armor provides
|
||||
damage reduction equal to half the AC bonus of the armor. This damage reduction can
|
||||
be overcome only by adamantine weapons. For example, a suit of full plate would provide
|
||||
damage reduction 4/adamantine, and a +1 breastplate (+6 AC) would provide damage reduction
|
||||
3/adamantine.
|
||||
|
||||
Material Component: Diamond dust worth at least 50 gp.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/23/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int oTarget = SPGetSpellTargetObject();
|
||||
|
||||
if(GetObjectType(oTarget)) == OBJECT_TYPE_ITEM
|
||||
{
|
||||
oArmor = oTarget;
|
||||
}
|
||||
|
||||
if(GetObjectType(oTarget)) == OBJECT_TYPE_CREATURE
|
||||
{
|
||||
oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oTarget);
|
||||
}
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
int nAC = GetBaseAC(oArmor);
|
||||
|
||||
//Must be metal
|
||||
if(nAC > 3)
|
||||
{
|
||||
if(nMetaMagic & METAMAGIC_EXTEND)
|
||||
{
|
||||
fDur += fDur;
|
||||
}
|
||||
|
||||
//Get amount for bonus - includes any +
|
||||
int nBonus = GetItemACValue(oArmor)/2;
|
||||
|
||||
//Adamantine is x/+5
|
||||
effect eDR = EffectDamageReduction(nBonus, DAMAGE_POWER_PLUS_FIVE);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDR, oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_AC_BONUS), oTarget);
|
||||
}
|
||||
else SendMessageToPC(oPC, "Invalid target. Target armor must be metal."
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
107
trunk/users/Tenjac/spells/sp_enshield.nss
Normal file
107
trunk/users/Tenjac/spells/sp_enshield.nss
Normal file
@@ -0,0 +1,107 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Energy Shield
|
||||
//:: FileName sp_enshield.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration
|
||||
Level: Paladin 2, Cleric 3
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 Standard Action
|
||||
Range: Touch
|
||||
Target: Shield touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
A silver aura surrounds the touched shield for a
|
||||
moment before it appears to transform into the chosen
|
||||
type of energy. The shield hums with power.
|
||||
|
||||
When this spell is cast, the shield touched appears
|
||||
to be made entirely out of one type of energy (fire,
|
||||
cold, electricity, acid, or sonic). Whoever bears the
|
||||
shield gains resistance 10 against the chosen energy
|
||||
type. Additionally, if the wielder successfully hits
|
||||
someone with the shield with a shield bash attack, th
|
||||
e victim takes 2d6 points of the appropriate energy
|
||||
damage in addition to the normal shield bash damage.
|
||||
The energy type must be chosen when the spell is cast
|
||||
and cannot be changed during the duration of the spell.
|
||||
The energy resistance overlaps (and does not stack)
|
||||
with resist elements. A given shield cannot be the
|
||||
subject of more than one lesser energized shield
|
||||
or energized shield spell at the same time.
|
||||
|
||||
The descriptor of this spell is the same as the
|
||||
energy type you choose when you cast it.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/19/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
#include "prc_inc_fork"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
|
||||
|
||||
//Check that this is a shield, if not abort
|
||||
if(GetIsShield(oShield) == FALSE)
|
||||
{
|
||||
SendMessageToPC(OBJECT_SELF, "Target has no equipped shield.");
|
||||
break;
|
||||
}
|
||||
|
||||
//The type of damage resistance we're choosing
|
||||
int nDR;
|
||||
|
||||
//Get the type by which subradial spell is used to cast
|
||||
int nSpell = GetSpellId();
|
||||
if(nSpell == SPELL_ENERGIZED_SHIELD_FIRE)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_FIRE;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_FIRE);
|
||||
}
|
||||
if(nSpell == SPELL_ENERGIZED_SHIELD_COLD)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_COLD;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_COLD);
|
||||
}
|
||||
if(nSpell == SPELL_ENERGIZED_SHIELD_ELEC)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_ELECTRICAL;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_ELECTRICAL);
|
||||
}
|
||||
if(nSpell == SPELL_ENERGIZED_SHIELD_ACID)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_ACID;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_ACID);
|
||||
}
|
||||
if(nSpell == SPELL_ENERGIZED_SHIELD_SONIC)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_SONIC;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_SONIC);
|
||||
}
|
||||
|
||||
//Set local int for amount of shield damage on the wielder of the shield
|
||||
SetLocalInt(oTarget, "EnShieldD6", 2);
|
||||
|
||||
//Schedule ints for deletion
|
||||
DelayCommand(fDur, DeleteLocalInt(oTarget, "EnShieldType"));
|
||||
DelayCommand(fDur, DeleteLocalInt(oTarget, "EnShieldD6"));
|
||||
|
||||
//Add resistance property
|
||||
IPSafeAddItemProperty(oShield, ItemPropertyDamageResistance(nDR, 10), fDur, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
105
trunk/users/Tenjac/spells/sp_estanasstew.nss
Normal file
105
trunk/users/Tenjac/spells/sp_estanasstew.nss
Normal file
@@ -0,0 +1,105 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Estana's Stew
|
||||
//:: FileName sp_estanasstew.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Conjuration (Healing)
|
||||
Level: Cleric 2, Druid 2, Paladin 2,
|
||||
Components: V, S, AF,
|
||||
Casting Time: 1 round
|
||||
Range: 0 ft.
|
||||
Effect: Fills pot with healing stew (1 serving/2 levels)
|
||||
Duration: Instantaneous (see text)
|
||||
Saving Throw: Will half (harmless); see text
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
This spell calls upon Estanna, goddess of hearth and home
|
||||
, to fill a specially crafted stewpot with a potent healing stew.
|
||||
The caster must be hold the pot in hand when Estanna's stew
|
||||
is cast; otherwise, the spell fails and is wasted.
|
||||
The spell creates one serving per two caster levels (maximum 5).
|
||||
A single serving heals 1d6+1 points of damage and requires
|
||||
a standard action to consume. Any portion of the stew that
|
||||
is not consumed disappears after 1 hour.The stew can be
|
||||
splashed onto a single undead creature within 10 feet.
|
||||
If a ranged touch attack succeeds, the undead creature
|
||||
takes 1d6+1 points of damage per serving splashed on it.
|
||||
The undead creature can apply spell resistance and can
|
||||
attempt a Will save to take half damage.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/20/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nSpell = GetSpellId();
|
||||
|
||||
if (nSpell == SPELL_ESTANAS_STEW)
|
||||
{
|
||||
object oItem = CreateItemOnObject("prc_estanasstew", oPC, 1);
|
||||
int nServings = min(5, (nCasterLvl/2));
|
||||
SetItemCharges(oItem, nServings);
|
||||
}
|
||||
|
||||
if (nSpell == SPELL_ESTANAS_STEW_EAT)
|
||||
{
|
||||
int nHeal = d6(1) + 1;
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectHeal(nHeal), oPC);
|
||||
}
|
||||
|
||||
if (nSpell == SPELL_ESTANAS_STEW_SPLASH)
|
||||
{
|
||||
object oItem = PRCGetSpellCastItem(OBJECT_SELF);
|
||||
object oTarget = GetSpellTargetObject();
|
||||
|
||||
|
||||
if(GetIsObjectValid(oTarget))
|
||||
{
|
||||
nTouch = TouchAttackRanged(oTarget);
|
||||
}
|
||||
// Check if we hit, or even have anything to hit!
|
||||
if(nTouch >= 1)
|
||||
{
|
||||
int nServings = GetItemCharges(oItem);
|
||||
|
||||
//Chuck all of it
|
||||
int nDam = (d6(1) + 1) * nServings;
|
||||
|
||||
// Critical hit?
|
||||
if(nTouch == 2)
|
||||
{
|
||||
nDam *= 2;
|
||||
}
|
||||
int nPenetr = SPGetPenetr();
|
||||
|
||||
//Resist
|
||||
if(!PRCDoResistSpell(OBJECT_SELF, oTarget nPenetr);
|
||||
{
|
||||
if(PRCMySavingThrow(SAVING_THROW_WILL, oTarget, PRCGetSaveDC(oTarget, OBJECT_SELF)))
|
||||
{
|
||||
nDam = nDam/2'
|
||||
}
|
||||
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectDamage(oTarget, nDam, DAMAGE_TYPE_DIVINE), oTarget);
|
||||
}
|
||||
}
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPER_INSTANT, EffectVisualEffect(VFX_COM_CHUNK_YELLOW_SMALL), oTarget);
|
||||
}
|
||||
//Remove the object
|
||||
DestroyObject(oItem);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
72
trunk/users/Tenjac/spells/sp_favormartyr.nss
Normal file
72
trunk/users/Tenjac/spells/sp_favormartyr.nss
Normal file
@@ -0,0 +1,72 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Favor of the Martyr
|
||||
//:: FileName sp_favormartyr.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Necromancy
|
||||
Level: Paladin 4,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: Medium (100 ft. + 10 ft./level)
|
||||
Target: One willing creature
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: None
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
Calling upon the saints of your order, you imbue the person
|
||||
in need with the power to resist the dire forces arrayed
|
||||
against you.
|
||||
|
||||
The subject gains immunity to nonlethal damage, charm and
|
||||
compulsion effects, and attacks that function specifically
|
||||
by causing pain, such as the wrack spell (see page 243). it
|
||||
is further immune to effects that would cause it to be dazed,
|
||||
exhausted, fatigued, nauseated, sickened, staggered, or stunned.
|
||||
The subject remains conscious at -1 to -9 hit points and can
|
||||
take a single action each round while in that state, and does
|
||||
not lose hit point for acting. If any of the above conditions
|
||||
were in effect on the subject at the time of casting, they are
|
||||
suspended for the spell's duration. (Thus, an unconscious
|
||||
subject becomes conscious and functional.)
|
||||
|
||||
When the spell ends, any effects suspended by the spell that
|
||||
have not expired in the interim (such as the fatigued condition,
|
||||
which normally requires 8 hours of rest to recover from) return.
|
||||
Effects that expired during the duration of this spell do not
|
||||
resume when it ends.
|
||||
|
||||
In addition to these effects, the subject gains the benefit of
|
||||
the Endurance feat for the duration of the spell.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/29/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_NECROMANCY);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 60.0f * (nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
|
||||
//Immunities
|
||||
effect eLink = EffectLinkEffects(EffectImmunity(IMMUNITY_TYPE_CHARM), EffectImmunity(IMMUNITY_TYPE_DAZED));
|
||||
eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_STUN));
|
||||
|
||||
//+4 Save vs Death
|
||||
eLink = EffectLinkEffects(eLink, EffectSavingThrowIncrease(SAVING_THROW_ALL, 4, SAVING_THROW_TYPE_DEATH));
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
67
trunk/users/Tenjac/spells/sp_forceward.nss
Normal file
67
trunk/users/Tenjac/spells/sp_forceward.nss
Normal file
@@ -0,0 +1,67 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Forceward
|
||||
//:: FileName sp_forceward.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration
|
||||
Level: Cleric 3 (Helm), Paladin 3, Knight of the Weave 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 full round
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius emanation centered on you
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: Will negates
|
||||
Spell Resistance: Yes
|
||||
|
||||
You create an unmoving, transparent sphere of force
|
||||
centered on your location.
|
||||
The sphere illuminates its interior and everything
|
||||
within 5 feet of its edge.
|
||||
You and your allies may enter the sphere at will.
|
||||
Any other creature that tries to enter the sphere must
|
||||
make a Will saving throw, otherwise it cannot pass into
|
||||
the area defined by the sphere.
|
||||
A creature may leave the area freely, although it must
|
||||
make a Will save to enter again, even if the creature
|
||||
is you or one of your allies.
|
||||
Creatures within the area when the spell is cast are not
|
||||
forced out.
|
||||
The forceward does not prevent spells or objects from
|
||||
entering the forceward, so it is possible for two creatures
|
||||
on opposite sides of the forceward's edge to fight without
|
||||
penalties (although creatures using unarmed attacks or
|
||||
natural weapons still have tomake Will saves every round
|
||||
for their attacks to have a chance of entering the forceward).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 07/04/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
location lLoc = GetLocation(oPC);
|
||||
|
||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(VFX_PER_FORCEWARD), lLoc, fDur);
|
||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_LIGHT_ORANGE_15), lLoc, fDur);
|
||||
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, 3.048f, lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
SetLocalInt(oTarget, "PRCForcewardEntry", 1)
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, 3.048f, lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
60
trunk/users/Tenjac/spells/sp_forcewardA.nss
Normal file
60
trunk/users/Tenjac/spells/sp_forcewardA.nss
Normal file
@@ -0,0 +1,60 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Forceward On Enter
|
||||
//:: FileName sp_forcewardA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration
|
||||
Level: Cleric 3 (Helm), Paladin 3, Knight of the Weave 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 full round
|
||||
Range: 10 ft.
|
||||
Area: 10-ft.-radius emanation centered on you
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: Will negates
|
||||
Spell Resistance: Yes
|
||||
|
||||
You create an unmoving, transparent sphere of force
|
||||
centered on your location.
|
||||
The sphere illuminates its interior and everything
|
||||
within 5 feet of its edge.
|
||||
You and your allies may enter the sphere at will.
|
||||
Any other creature that tries to enter the sphere must
|
||||
make a Will saving throw, otherwise it cannot pass into
|
||||
the area defined by the sphere.
|
||||
A creature may leave the area freely, although it must
|
||||
make a Will save to enter again, even if the creature
|
||||
is you or one of your allies.
|
||||
Creatures within the area when the spell is cast are not
|
||||
forced out.
|
||||
The forceward does not prevent spells or objects from
|
||||
entering the forceward, so it is possible for two creatures
|
||||
on opposite sides of the forceward's edge to fight without
|
||||
penalties (although creatures using unarmed attacks or
|
||||
natural weapons still have tomake Will saves every round
|
||||
for their attacks to have a chance of entering the forceward).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 07/04/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetEnteringObject();
|
||||
object oCreator = GetAreaOfEffectCreator();
|
||||
int nDC = PRCGetSaveDC(oTarget, oCreator);
|
||||
int nCasterLvl = PRCGetCasterLevel(oCreator);
|
||||
location lAOE = GetLocation(OBJECT_SELF);
|
||||
|
||||
//Will save if it doesn't have the local int
|
||||
if(!GetLocalInt(oTarget, "PRCForcewardEntry"))
|
||||
{
|
||||
if(!PRCMySavingThrow(SAVING_THROW_WILL, oTarget, nDC, SAVING_THROW_TYPE_NONE, oCreator))
|
||||
{
|
||||
ActionMoveAwayFromLocation(lAOE, FALSE, 3.048f);
|
||||
}
|
||||
}
|
||||
}
|
||||
44
trunk/users/Tenjac/spells/sp_forcewardB.nss
Normal file
44
trunk/users/Tenjac/spells/sp_forcewardB.nss
Normal file
@@ -0,0 +1,44 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Forceward On Exit
|
||||
//:: FileName sp_forcewardB.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/4/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetExitingObject();
|
||||
|
||||
if(GetLocalInt(oTarget, "PRCForcewardEntry"))
|
||||
{
|
||||
DeleteLocalInt(oTarget, "PRCForcewardEntry"));
|
||||
}
|
||||
|
||||
effect eAOE;
|
||||
if(GetHasSpellEffect(SPELL_SOLID_FOG, oTarget))
|
||||
{
|
||||
//Search through the valid effects on the target.
|
||||
eAOE = GetFirstEffect(oTarget);
|
||||
while (GetIsEffectValid(eAOE))
|
||||
{
|
||||
if (GetEffectCreator(eAOE) == GetAreaOfEffectCreator())
|
||||
{
|
||||
//If the effect was created by either half of Fog from the Void
|
||||
if(GetEffectSpellId(eAOE) == SPELL_SOLID_FOG)
|
||||
{
|
||||
RemoveEffect(oTarget, eAOE);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Get next effect on the target
|
||||
eAOE = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
135
trunk/users/Tenjac/spells/sp_glorymartyr.nss
Normal file
135
trunk/users/Tenjac/spells/sp_glorymartyr.nss
Normal file
@@ -0,0 +1,135 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Glory of the Martyr
|
||||
//:: FileName sp_glorymartyr.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration [Good]
|
||||
Level: Champion of Gwynharwyf 4, Paladin 4,
|
||||
Components: V, S, AF, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Close (25 ft. + 5 ft./2 levels)
|
||||
Target: One creature/level
|
||||
Duration: 1 hour/level (D)
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
Like shield other, this spell wards the subjects,
|
||||
creating a mystic connection between them and you
|
||||
so that some of their wounds are transferred to you.
|
||||
The subjects each gain a +1 deflection bonus to AC
|
||||
and a +1 resistance bonus on saves.
|
||||
|
||||
All the subjects take only half damage from all
|
||||
wounds and attacks that deal them hit point damage.
|
||||
The amount of damage not taken by all the warded
|
||||
creatures is taken by you.
|
||||
|
||||
Forms of harm that do not involve hit points, such
|
||||
as charm effects, temporary ability damage, level
|
||||
draining, and disintegration, are not affected.
|
||||
If a subject suffers a reduction of hit points
|
||||
from a lowered Constitution score, the reduction
|
||||
is not split with you because it is not hit point damage.
|
||||
When the spell ends, subsequent damage is no
|
||||
longer divided between you and the subjects, but
|
||||
damage already split is not reassigned to the
|
||||
subjects.
|
||||
|
||||
If you die while this spell is in effect, the spell
|
||||
ends in a burst of positive energy that restores 1d8
|
||||
hit points to each subject.
|
||||
|
||||
If a subject moves out of range of the spell, that
|
||||
subject's connection to you is severed but the spell
|
||||
continues as long as there is at least one subject
|
||||
remaining and you remain alive.
|
||||
|
||||
Focus: A platinum ring (worth at least 50 gp) worn
|
||||
by you and each subject of the spell.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void DispelMonitor(object oManifester, object oTarget, int nSpellID, int nManifesterLevel, int nBeatsRemaining);
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nBeatsRemaining = FloatToInt(fDur)/6;
|
||||
int nMaxTargets = nCasterLvl;
|
||||
float fRadius = FeetToMeters(25.0f + (5.0f * (nCasterLvl / 2))))
|
||||
location lLoc = GetLocation(oPC);
|
||||
int nSpell = GetSpellId();
|
||||
effect eDurPos = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_POSITIVE);
|
||||
effect eDurNeg = EffectVisualEffect(VFX_DUR_MIND_AFFECTING_NEGATIVE);
|
||||
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTarget) && nMaxTargets >0)
|
||||
{
|
||||
if(oTarget != oPC)
|
||||
{
|
||||
if(GetIsReactionTypeFriendly(oTarget))
|
||||
{
|
||||
// Get the OnHitCast: Unique on the caster's armor / hide
|
||||
ExecuteScript("prc_keep_onhit_a", oPC);
|
||||
|
||||
// Hook eventscript
|
||||
AddEventScript(oPC, EVENT_ONHIT, "psi_pow_shrpnaux", TRUE, FALSE);
|
||||
|
||||
// Store the target for use in the damage script
|
||||
SetLocalObject(oPC, "PRC_Power_SharePain_Target", oTarget);
|
||||
|
||||
//Apply bonuses to target
|
||||
effect eLink = EffectLinkEffects(EffectACIncrease(1, AC_DEFLECTION_BONUS), EffectSavingThrowIncrease(SAVING_THROW_ALL, 1, SAVING_THROW_TYPE_ALL));
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDur);
|
||||
|
||||
// Do VFX for the monitor to look for
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDurNeg, oTarget, fDur, TRUE, nSpell, nCasterLvl);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eDurPos, oPC, fDur, TRUE, nSpell, nCasterLvl);
|
||||
|
||||
// Start effect end monitor
|
||||
DelayCommand(6.0f, DispelMonitor(oPC, oTarget, nSpell, nCasterLvl, nBeatsRemaining);
|
||||
nMaxTargets--;
|
||||
}
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
|
||||
void DispelMonitor(object oPC, object oTarget, int nSpellID, int CasterLvl, int nBeatsRemaining)
|
||||
{
|
||||
// Has the power ended since the last beat, or does the duration run out now
|
||||
if((--nBeatsRemaining == 0) ||
|
||||
GetIsDead(oTarget) ||
|
||||
PRCGetDelayedSpellEffectsExpired(nSpellID, oTarget, oPC) ||
|
||||
PRCGetDelayedSpellEffectsExpired(nSpellID, oPC, oPC) ||
|
||||
GetDistanceBetween(oPC, oTarget) > FeetToMeters(25.0f + (5.0f * (nCasterLvl / 2))))
|
||||
{
|
||||
if(DEBUG) DoDebug("Glory of the Martyr: Effect expired, clearing");
|
||||
// Clear the target local
|
||||
DeleteLocalObject(PC, "PRC_Power_SharePain_Target");
|
||||
// Remove the eventscript
|
||||
RemoveEventScript(oPC, EVENT_ONHIT, "psi_pow_shrpnaux", TRUE, FALSE);
|
||||
|
||||
// Remove remaining effects
|
||||
PRCRemoveSpellEffects(nSpellID, oPC, oTarget);
|
||||
PRCRemoveSpellEffects(nSpellID, oPC, oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
nBeatsRemaining --;
|
||||
DelayCommand(6.0f, DispelMonitor(oPC, oTarget, nSpellID, nCasterLvl, nBeatsRemaining));
|
||||
|
||||
}
|
||||
46
trunk/users/Tenjac/spells/sp_holyfire.nss
Normal file
46
trunk/users/Tenjac/spells/sp_holyfire.nss
Normal file
@@ -0,0 +1,46 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Fire
|
||||
//:: FileName sp_holyfire.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Fire, Good]
|
||||
Level: Cleric 2, Paladin 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round
|
||||
|
||||
All undead within range of your next turning attempt
|
||||
(if you make it before this spell's duration expires)
|
||||
are especially vulnerable to the attempt. Whether you
|
||||
succeed in turning them or not, the undead take hit
|
||||
point damage equal to the result of your turning damage
|
||||
roll. This damage is half fire and half sacred energy.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/21/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(1);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//Set a VFX
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_PROTECTION_GOOD_MAJOR), oPC);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(VFX_MOB_HOLYFIRE), oPC);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
35
trunk/users/Tenjac/spells/sp_holyfireA.nss
Normal file
35
trunk/users/Tenjac/spells/sp_holyfireA.nss
Normal file
@@ -0,0 +1,35 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Fire On Enter
|
||||
//:: FileName sp_holyfireA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Fire, Good]
|
||||
Level: Cleric 2, Paladin 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round
|
||||
|
||||
All undead within range of your next turning attempt
|
||||
(if you make it before this spell's duration expires)
|
||||
are especially vulnerable to the attempt. Whether you
|
||||
succeed in turning them or not, the undead take hit
|
||||
point damage equal to the result of your turning damage
|
||||
roll. This damage is half fire and half sacred energy.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/21/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetEnteringObject();
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_YELLOW_ORANGE), oTarget, 6.0f);
|
||||
}
|
||||
46
trunk/users/Tenjac/spells/sp_holyfireB.nss
Normal file
46
trunk/users/Tenjac/spells/sp_holyfireB.nss
Normal file
@@ -0,0 +1,46 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Fire On Exit
|
||||
//:: FileName sp_holyfireB.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Fire, Good]
|
||||
Level: Cleric 2, Paladin 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round
|
||||
|
||||
All undead within range of your next turning attempt
|
||||
(if you make it before this spell's duration expires)
|
||||
are especially vulnerable to the attempt. Whether you
|
||||
succeed in turning them or not, the undead take hit
|
||||
point damage equal to the result of your turning damage
|
||||
roll. This damage is half fire and half sacred energy.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/21/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_add_spell_dc"
|
||||
void main()
|
||||
{
|
||||
object oCaster = GetAreaOfEffectCreator();
|
||||
object oTarget = GetExitingObject();
|
||||
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_HOLY_FIRE)
|
||||
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
trunk/users/Tenjac/spells/sp_holystorm.nss
Normal file
62
trunk/users/Tenjac/spells/sp_holystorm.nss
Normal file
@@ -0,0 +1,62 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Storm
|
||||
//:: FileName sp_holystorm.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation) [Good, Water]
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft.
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of good, and a heavy rain begins to fall
|
||||
around you, its raindrops soft and warm.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed area once
|
||||
created. The storm reduces hearing and visibility, resulting in a
|
||||
-4 penalty on Listen, Spot, and Search checks. It also applies a
|
||||
-4 penalty on ranged attacks made into, out of, or through the
|
||||
storm. Finally, it automatically extinguishes any unprotected
|
||||
flames and has a 50% chance to extinguish protected flames
|
||||
(such as those of lanterns).
|
||||
|
||||
The rain damages evil creatures, dealing 2d6 points of damage
|
||||
per round (evil outsiders take double damage) at the beginning
|
||||
of your turn.
|
||||
|
||||
Material Component: A flask of holy water (25 gp).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/9/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//VFX
|
||||
effect eVis = EffectVisualEffect(VFX_FNF_STORM);
|
||||
|
||||
ApplyEffectAtLocation(DURATION_TYPE_INSTANT, eVis, lTarget);
|
||||
ApplyEffectAtLocation(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(AOE_PER_STORM, "sp_holystormA", "sp_holystormB", "sp_holystormC"), lTarget, fDur);
|
||||
|
||||
object oAoE = GetAreaOfEffectObject(lTarget, "VFX_PER_STORM");
|
||||
SetAllAoEInts(SPELL_HOLY_STORM, oAoE, PRCGetSpellSaveDC(SPELL_HOLY_STORM, SPELL_SCHOOL_CONJURATION), 0, PRCGetCasterLevel(oPC));
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
48
trunk/users/Tenjac/spells/sp_holystormA.nss
Normal file
48
trunk/users/Tenjac/spells/sp_holystormA.nss
Normal file
@@ -0,0 +1,48 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Storm On Enter
|
||||
//:: FileName sp_holystormA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation) [Good, Water]
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft.
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of good, and a heavy rain begins to fall
|
||||
around you, its raindrops soft and warm.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed area once
|
||||
created. The storm reduces hearing and visibility, resulting in a
|
||||
-4 penalty on Listen, Spot, and Search checks. It also applies a
|
||||
-4 penalty on ranged attacks made into, out of, or through the
|
||||
storm.
|
||||
|
||||
The rain damages evil creatures, dealing 2d6 points of damage
|
||||
per round (evil outsiders take double damage) at the beginning
|
||||
of your turn.
|
||||
|
||||
Material Component: A flask of holy water (25 gp).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/9/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetEnteringObject();
|
||||
|
||||
effect ePenalty = EffectLinkEffects(EffectSkillDecrease(SKILL_LISTEN, 4), EffectSkillDecrease(SKILL_SPOT), 4));
|
||||
ePenalty = EffectLinkEffects(ePenalty, EffectSkillDecrease(SKILL_SEARCH, 4));
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePenalty, oTarget, RoundsToSeconds(1));
|
||||
}
|
||||
53
trunk/users/Tenjac/spells/sp_holystormB.nss
Normal file
53
trunk/users/Tenjac/spells/sp_holystormB.nss
Normal file
@@ -0,0 +1,53 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Storm On Enter
|
||||
//:: FileName sp_holystormA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation) [Good, Water]
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft.
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of good, and a heavy rain begins to fall
|
||||
around you, its raindrops soft and warm.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed area once
|
||||
created. The storm reduces hearing and visibility, resulting in a
|
||||
-4 penalty on Listen, Spot, and Search checks. It also applies a
|
||||
-4 penalty on ranged attacks made into, out of, or through the
|
||||
storm.
|
||||
|
||||
The rain damages evil creatures, dealing 2d6 points of damage
|
||||
per round (evil outsiders take double damage) at the beginning
|
||||
of your turn.
|
||||
|
||||
Material Component: A flask of holy water (25 gp).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/9/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oTarget = GetExitingObject();
|
||||
effect eToDispel = GetFirstEffect(oTarget);
|
||||
while(GetIsEffectValid(eToDispel))
|
||||
{
|
||||
if(GetEffectSpellId(eToDispel) == SPELL_HOLY_STORM)
|
||||
{
|
||||
RemoveEffect(oTarget, eToDispel);
|
||||
}
|
||||
|
||||
eToDispel = GetNextEffect(oTarget);
|
||||
}
|
||||
}
|
||||
76
trunk/users/Tenjac/spells/sp_holystormC.nss
Normal file
76
trunk/users/Tenjac/spells/sp_holystormC.nss
Normal file
@@ -0,0 +1,76 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Holy Storm On Enter
|
||||
//:: FileName sp_holystormA.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Creation) [Good, Water]
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 20 ft.
|
||||
Area: Cylinder (20-ft. radius, 20 ft. high)
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
You call upon the forces of good, and a heavy rain begins to fall
|
||||
around you, its raindrops soft and warm.
|
||||
|
||||
A driving rain falls around you. It falls in a fixed area once
|
||||
created. The storm reduces hearing and visibility, resulting in a
|
||||
-4 penalty on Listen, Spot, and Search checks. It also applies a
|
||||
-4 penalty on ranged attacks made into, out of, or through the
|
||||
storm.
|
||||
|
||||
The rain damages evil creatures, dealing 2d6 points of damage
|
||||
per round (evil outsiders take double damage) at the beginning
|
||||
of your turn.
|
||||
|
||||
Material Component: A flask of holy water (25 gp).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/9/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
location lLoc = GetLocation(OBJECT_SELF);
|
||||
int nDam;
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, 6.096f, lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
effect ePenalty = EffectLinkEffects(EffectSkillDecrease(SKILL_LISTEN, 4), EffectSkillDecrease(SKILL_SPOT), 4));
|
||||
ePenalty = EffectLinkEffects(ePenalty, EffectSkillDecrease(SKILL_SEARCH, 4));
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
//Penalties to skills
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, ePenalty, oTarget, RoundsToSeconds(1));
|
||||
|
||||
//Penalty to attack if ranged equipped
|
||||
if(GetWeaponRanged(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAttackDecrease(4), 6.0f);
|
||||
}
|
||||
|
||||
//Bonus AC vs Ranged?
|
||||
|
||||
//if evil
|
||||
if(GetAlignmentGoodEvil(oTarget) == ALIGNMENT_EVIL)
|
||||
{
|
||||
nDam = d6(2);
|
||||
//if outsider
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_OUTSIDER)
|
||||
{
|
||||
nDam+=nDam;
|
||||
}
|
||||
|
||||
//damage
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(DAMAGE_TYPE_DIVINE, nDam, oTarget));
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, 6.096f, lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
}
|
||||
130
trunk/users/Tenjac/spells/sp_invcs.nss
Normal file
130
trunk/users/Tenjac/spells/sp_invcs.nss
Normal file
@@ -0,0 +1,130 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Invoke the Cerulean Sign
|
||||
//:: FileName sp_invCS.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Evocation
|
||||
Level: Druid 2, Ranger 2, Bard 3, Cleric 3, Paladin 3, Sorcerer 3, Wizard 3,
|
||||
Components: S,
|
||||
Casting Time: 1 standard action
|
||||
Range: 30 ft.
|
||||
Area: Multiple aberrations whose combined total Hit Dice do not exceed twice
|
||||
caster level in a spread emanating from the character to the extreme of the range
|
||||
Duration: Instantaneous
|
||||
Saving Throw: Fortitude negates
|
||||
Spell Resistance: No
|
||||
|
||||
The cerulean sign is an ancient symbol said to embody
|
||||
the purity of the natural world, and as such it is
|
||||
anathema to aberrations.
|
||||
While druids and rangers are the classes most often
|
||||
known to cast this ancient spell, its magic is nearly
|
||||
universal and can be mastered by all spellcasting classes.
|
||||
When you cast this spell, you trace the cerulean sign
|
||||
in the air with a hand, leaving a glowing blue rune
|
||||
in the air for a brief moment before it flashes and fills
|
||||
the area of effect with a pulse of cerulean light.
|
||||
Any aberration within the area must make a Fortitude
|
||||
saving throw or suffer the following ill effects.
|
||||
Closer aberrations are affected first.
|
||||
Each effect lasts for 1 round.
|
||||
|
||||
None: The aberration suffers no ill effect, even if it fails the
|
||||
saving throw.
|
||||
Sickened: The aberration takes a -2 penalty on attack
|
||||
rolls, saving throws, skill checks, and ability checks for 1 round.
|
||||
Nauseated: The aberration cannot attack, cast spells, concentrate
|
||||
on spells, or do anything but take a single move action for 1 round.
|
||||
Dazed: The aberration can take no actions, but has no penalty to
|
||||
its Armor Class, for 1 round.
|
||||
Stunned: The aberration drops everything held, can't take actions,
|
||||
takes a -2 penalty to AC, and loses its Dexterity bonus to AC (if any)
|
||||
for 1 round.
|
||||
|
||||
Once a creature recovers from an effect, it moves up one level on the table.
|
||||
Thus, a creature that is stunned by this spell is dazed the round after
|
||||
that, nauseated the round after that, sickened the round after that, and
|
||||
then recovers fully the next round.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/13/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
#include "prc_effect_inc"
|
||||
|
||||
void DoDrop(object oTarget)
|
||||
{
|
||||
object oTargetWep = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
object oOffhand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
|
||||
object oNewWeap = CopyObject(oTargetWep, GetLocation(oTarget));
|
||||
object oNewOff = CopyObject(oOffhand, GetLocation(oTarget));
|
||||
DestroyObject(oTargetWep);
|
||||
DestroyObject(oOffhand);
|
||||
}
|
||||
|
||||
void DoSign(object oTarget)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FROST_L), oTarget);
|
||||
|
||||
//2nd round sickened
|
||||
DelayCommand(6.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSickened(), oTarget, 6.0f));
|
||||
|
||||
//3rd round Nauseated
|
||||
DelayCommand(12.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNausea(oTarget, 6.0f), oTarget, 6.0f));
|
||||
|
||||
//4th round Dazed
|
||||
DelayCommand(18.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneParalyze(), oTarget, 6.0f));
|
||||
|
||||
//5th round Stunned
|
||||
DelayCommand(24.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneParalyze(), oTarget, 6.0f));
|
||||
DelayCommand(24.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectACDecrease(2), oTarget, 6.0f));
|
||||
DelayCommand(24.0f, DoDrop(oTarget));
|
||||
|
||||
//6th round Dazed
|
||||
DelayCommand(30.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectCutsceneParalyze(), oTarget, 6.0f));
|
||||
|
||||
//7th round Nauseated
|
||||
DelayCommand(36.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNausea(oTarget, 6.0f), oTarget, 6.0f));
|
||||
|
||||
//8th round sickened
|
||||
DelayCommand(42.0f, SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSickened(), oTarget, 6.0f));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int nDice = nCasterLvl * 2;
|
||||
location lLoc = GetLocation(oPC);
|
||||
int nTargetDice;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FROST_L), oPC);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HASTE), oPC);
|
||||
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, 9.144f, lLocl, FALSE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid && nDice > 0)
|
||||
{
|
||||
//Aberration
|
||||
if(MyPRCGetRacialType(oTarget) == RACIAL_TYPE_ABERRATION)
|
||||
{
|
||||
//Save
|
||||
if(!PRCMySavingThrow(SAVING_THROW_FORT, oTarget, PRCGetSaveDC(oTarget, oPC)))
|
||||
{
|
||||
nTargetDice = GetHitDice(oTarget);
|
||||
if(nDice >= nTargetDice)
|
||||
{
|
||||
nDice -= nTargetDice;
|
||||
DoSign(oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, 9.144f, lLocl, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
46
trunk/users/Tenjac/spells/sp_irresforce.nss
Normal file
46
trunk/users/Tenjac/spells/sp_irresforce.nss
Normal file
@@ -0,0 +1,46 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Irresistable Force
|
||||
//:: FileName sp_irresforce.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation
|
||||
Level: Paladin 4,
|
||||
Components: V, S,
|
||||
Casting Time: 1 action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round/level
|
||||
|
||||
Charging yourself with divine energy, you become the epitome of force in motion.
|
||||
You are protected by freedom of movement.
|
||||
You gain a +10 bonus on bull rush attempts.
|
||||
You gain a +10 bonus on checks made to avoid being tripped.
|
||||
When moving in combat, you act as if you had the Mobility feat.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/14/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//Freedom of Movement
|
||||
effect eLink = EffectLinkEffects(EffectImmunity(IMMUNITY_TYPE_PARALYSIS), EffectImmunity(IMMUNITY_TYPE_SLOW));
|
||||
eLink = EffectLinkEffects(eLink, EffectImmunity(IMMUNITY_TYPE_ENTANGLE));
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, fDur);
|
||||
|
||||
//Mobility
|
||||
IPSafeAddItemProperty(GetPCSkin(oPC), PRCItemPropertyBonusFeat(FEAT_MOBILITY), fDur);
|
||||
PRCSetSchool();
|
||||
}
|
||||
49
trunk/users/Tenjac/spells/sp_laspdiety.nss
Normal file
49
trunk/users/Tenjac/spells/sp_laspdiety.nss
Normal file
@@ -0,0 +1,49 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Lesser Aspect of the Diety
|
||||
//:: FileName sp_laspdiety.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Transmutation [Good]
|
||||
Level: Apostle of Peace 4, Exalted Arcanist 4, Paladin 4, Knight of the Chalice 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round/level
|
||||
|
||||
When you cast this spell, your body changes into a form that is more like
|
||||
your deity (in a very limited fashion, of course).
|
||||
|
||||
You gain a +4 enhancement bonus to your Charisma score.
|
||||
|
||||
You also gain acid, cold, and electricity resistance 10.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/7/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
effect eLink = EffectAbilityIncrease(ABILITY_CHARISMA, 4);
|
||||
eLink = EffectLinkEffects(eLink, EffectDamageResistance(DAMAGE_TYPE_ACID, 10));
|
||||
eLink = EffectLinkEffects(eLink, EffectDamageResistance(DAMAGE_TYPE_COLD, 10));
|
||||
eLink = EffectLinkEffects(eLink, EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, 10));
|
||||
eLink = EffectLinkEffects(eLink, EffectVisualEffect(VFX_DUR_IOUNSTONE_YELLOW));
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
67
trunk/users/Tenjac/spells/sp_lauracold.nss
Normal file
67
trunk/users/Tenjac/spells/sp_lauracold.nss
Normal file
@@ -0,0 +1,67 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Lesser Aura of Cold
|
||||
//:: FileName sp_lauracold.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Cold]
|
||||
Level: Cleric 3, Druid 3, Disciple of Thrym 3, Paladin 4, Ranger 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: 5 ft.
|
||||
Area: 5-ft.-radius spherical emanation, centered on you
|
||||
Duration: 1 round/level (D)
|
||||
Saving Throw: None
|
||||
Spell Resistance: Yes
|
||||
|
||||
You are covered in a thin layer of white frost and frigid cold emanates from your
|
||||
body, dealing 1d6 points of cold damage at the start of your round to each creature
|
||||
within 5 feet.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 6/8/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void DoCold(object oPC, int nRounds)
|
||||
{
|
||||
if(nRounds > 0)
|
||||
{
|
||||
location lLoc=GetLocation(oPC);
|
||||
//Do the AoE
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE,FeetToMeters(5.0), lLoc);
|
||||
{
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(oTarget != oPC)
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(d6(1), DAMAGE_TYPE_COLD), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FROST_S), oTarget);
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(5.0), lLoc);
|
||||
}
|
||||
}
|
||||
nRounds--;
|
||||
DelayCommand(6.0f, DoCold(oPC, nRounds));
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nRounds = nCasterLvl;
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) nRounds += nRounds;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_BLUE_WHITE), oPC, fDur);
|
||||
|
||||
DoCold(oPC, nRounds);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
67
trunk/users/Tenjac/spells/sp_lawsword.nss
Normal file
67
trunk/users/Tenjac/spells/sp_lawsword.nss
Normal file
@@ -0,0 +1,67 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Lawful Sword
|
||||
//:: FileName sp_lawsword.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Evocation
|
||||
Level: Paladin 4,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Weapon touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
Calling to mind thoughts of justice, you run your
|
||||
fingers along the weapon, imbuing it with power.
|
||||
|
||||
This spell functions like holy sword (PH 242), except
|
||||
as follows. The weapon functions as a +5 axiomatic
|
||||
weapon (+5 enhancement bonus on attack rolls and damage
|
||||
rolls, lawful-aligned, deals an extra 2d6 points of damage
|
||||
against chaotic opponents). It also emits a magic circle
|
||||
against chaos effect (as the spell).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 2/2/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
object oTarget = GetSpellTargetObject();
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//+2d6 vs chaotic
|
||||
itemproperty iDam = ItemPropertyDamageBonusVsAlign(IP_CONST_ALIGNMENTGROUP_CHAOTIC, IP_CONST_DAMAGETYPE_PHYSICAL, IP_CONST_DAMAGEBONUS_2d6);
|
||||
//+5 vs everything
|
||||
itemproperty iAttack = ItemPropertyEnhancementBonus(5);
|
||||
|
||||
if(GetObjectType(oTarget)) == OBJECT_TYPE_CREATURE
|
||||
{
|
||||
oTarget = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
}
|
||||
|
||||
IPSafeAddItemProperty(oTarget, iDam, fDur);
|
||||
IPSafeAddItemProperty(oTarget, iAttack, fDur);
|
||||
|
||||
//magic circle on the weapon
|
||||
effect eCircle = EffectAreaOfEffect(AOE_MOB_CIRCCHAOS);
|
||||
effect eVis = EffectVisualEffect(VFX_IMP_EVIL_HELP);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eCircle, oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
107
trunk/users/Tenjac/spells/sp_lenshield.nss
Normal file
107
trunk/users/Tenjac/spells/sp_lenshield.nss
Normal file
@@ -0,0 +1,107 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Lesser Energy Shield
|
||||
//:: FileName sp_lenshield.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration
|
||||
Level: Paladin 1, Cleric 2
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 Standard Action
|
||||
Range: Touch
|
||||
Target: Shield touched
|
||||
Duration: 1 round/level
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
A silver aura surrounds the touched shield for a
|
||||
moment before it appears to transform into the chosen
|
||||
type of energy. The shield hums with power.
|
||||
|
||||
When this spell is cast, the shield touched appears
|
||||
to be made entirely out of one type of energy (fire,
|
||||
cold, electricity, acid, or sonic). Whoever bears the
|
||||
shield gains resistance 5 against the chosen energy
|
||||
type. Additionally, if the wielder successfully hits
|
||||
someone with the shield with a shield bash attack, th
|
||||
e victim takes 1d6 points of the appropriate energy
|
||||
damage in addition to the normal shield bash damage.
|
||||
The energy type must be chosen when the spell is cast
|
||||
and cannot be changed during the duration of the spell.
|
||||
The energy resistance overlaps (and does not stack)
|
||||
with resist elements. A given shield cannot be the
|
||||
subject of more than one lesser energized shield
|
||||
or energized shield spell at the same time.
|
||||
|
||||
The descriptor of this spell is the same as the
|
||||
energy type you choose when you cast it.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/28/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
#include "prc_inc_fork"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
|
||||
|
||||
//Check that this is a shield, if not abort
|
||||
if(GetIsShield(oShield) == FALSE)
|
||||
{
|
||||
SendMessageToPC(OBJECT_SELF, "Target has no equipped shield.");
|
||||
break;
|
||||
}
|
||||
|
||||
//The type of damage resistance we're choosing
|
||||
int nDR;
|
||||
|
||||
//Get the type by which subradial spell is used to cast
|
||||
int nSpell = GetSpellId();
|
||||
if(nSpell == SPELL_LESSER_ENERGIZED_SHIELD_FIRE)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_FIRE;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_FIRE);
|
||||
}
|
||||
if(nSpell == SPELL_LESSER_ENERGIZED_SHIELD_COLD)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_COLD;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_COLD);
|
||||
}
|
||||
if(nSpell == SPELL_LESSER_ENERGIZED_SHIELD_ELEC)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_ELECTRICAL;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_ELECTRICAL);
|
||||
}
|
||||
if(nSpell == SPELL_LESSER_ENERGIZED_SHIELD_ACID)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_ACID;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_ACID);
|
||||
}
|
||||
if(nSpell == SPELL_LESSER_ENERGIZED_SHIELD_SONIC)
|
||||
{
|
||||
nDR = IP_CONST_DAMAGETYPE_SONIC;
|
||||
SetLocalInt(oTarget, "EnShieldType", DAMAGE_TYPE_SONIC);
|
||||
}
|
||||
|
||||
//Set local int for amount of shield damage on the wielder of the shield
|
||||
SetLocalInt(oTarget, "EnShieldD6", 1);
|
||||
|
||||
//Schedule ints for deletion
|
||||
DelayCommand(fDur, DeleteLocalInt(oTarget, "EnShieldType"));
|
||||
DelayCommand(fDur, DeleteLocalInt(oTarget, "EnShieldD6"));
|
||||
|
||||
//Add resistance property
|
||||
IPSafeAddItemProperty(oShield, ItemPropertyDamageResistance(nDR, 5), fDur, X2_IP_ADDPROP_POLICY_KEEP_EXISTING);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
56
trunk/users/Tenjac/spells/sp_lmagweap.nss
Normal file
56
trunk/users/Tenjac/spells/sp_lmagweap.nss
Normal file
@@ -0,0 +1,56 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Legion's Magic Weapon
|
||||
//:: FileName sp_lmagweap.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Transmutation
|
||||
Level: Cleric 2, Paladin 2, Sorcerer 2, Wizard 2,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Close (25 ft. + 5 ft./2 levels)
|
||||
Target: Melee or ranged weapons held by allied creatures in a 20-ft.-radius burst
|
||||
Duration: 1 round/level
|
||||
Saving Throw: Will negates (harmless, object)
|
||||
Spell Resistance: Yes (harmless, object)
|
||||
|
||||
This spell functions like magic weapon (see page 251 of the
|
||||
Player's Handbook), except as noted above and as follows. It
|
||||
affects only weapons held by allies when the spell is cast.
|
||||
It has no effect on ammunition.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/13/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
location lLoc = GetLocation(oPC);
|
||||
|
||||
object oTarget = MyGetFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(30), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(GetIsReactionTypeFriendly(oTarget))
|
||||
{
|
||||
object oItem = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
|
||||
if(GetIsObjectValid(oItem))
|
||||
{
|
||||
IPSafeAddItemProperty(oItem,ItemPropertyEnhancementBonus(1), fDur, X2_IP_ADDPROP_POLICY_KEEP_EXISTING ,TRUE,TRUE);
|
||||
}
|
||||
}
|
||||
oTarget = MyGetNextObjectInShape(SHAPE_SPHERE, FeetToMeters(30), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
65
trunk/users/Tenjac/spells/sp_lvisdeity.nss
Normal file
65
trunk/users/Tenjac/spells/sp_lvisdeity.nss
Normal file
@@ -0,0 +1,65 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Lesser Visage of the Deity
|
||||
//:: FileName sp_lvisdiety.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Transmutation [Good or Evil]
|
||||
Level: Cleric 3, Blackguard 4, Paladin 4, Mysticism 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round/level
|
||||
|
||||
As you end your prayer, you can feel the hand of your
|
||||
deity upon you. Your appearance reflects her divine power,
|
||||
and her touch grants you resistance from some of the damage
|
||||
of this world.
|
||||
|
||||
You gain a +4 enhancement bonus to Charisma. You also gain
|
||||
resistance to acid 10, cold 10, and electricity 10 if you
|
||||
are good, or resistance to cold 10 and fire 10 if you are evil.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/26/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
int nAlign = GetAlignmentGoodEvil(oPC);
|
||||
int nBonus = 4;
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityIncrease(ABILITY_CHARISMA, nBonus), oPC, fDur);
|
||||
|
||||
if (nAlign == ALIGNMENT_GOOD)
|
||||
{
|
||||
effect eResAcid = EffectDamageResistance(DAMAGE_TYPE_ACID, 10);
|
||||
effect eResCold = EffectDamageResistance(DAMAGE_TYPE_COLD, 10);
|
||||
effect eResElec = EffectDamageResistance(DAMAGE_TYPE_ELECTRICAL, 10);
|
||||
effect eLink = EffectLinkEffects(eResAcid, eResCold);
|
||||
eLink = EffectLinkEffects(eLink, eResElec);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_GOOD_HELP), oPC);
|
||||
}
|
||||
|
||||
else if (nAlign == ALIGNMENT_EVIL)
|
||||
{
|
||||
effect eLink = EffectLinkEffects(EffectDamageResistance(DAMAGE_TYPE_COLD, 10), EffectDamageResistance(DAMAGE_TYPE_FIRE, 10));
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_EVIL_HELP), oPC);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
44
trunk/users/Tenjac/spells/sp_majorresist.nss
Normal file
44
trunk/users/Tenjac/spells/sp_majorresist.nss
Normal file
@@ -0,0 +1,44 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Major Resistance
|
||||
//:: FileName sp_majorresist.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Abjuration
|
||||
Level: Bard 2, Cleric 2, Druid 2, Paladin 2, Sorcerer 2, Wizard 2,
|
||||
Components: V, S, M, DF,
|
||||
Casting Time: 1 action
|
||||
Range: Touch
|
||||
Target: Creature touched
|
||||
Duration: 1 hour/level
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
You imbue the subject with a strong magical energy that protects
|
||||
her from harm, granting a +3 resistance bonus on saves.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/14/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = GetSpellTargetObject();
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_WHITE), oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectSavingThrowIncrease(SAVING_THROW_ALL, 3), oTarget, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
52
trunk/users/Tenjac/spells/sp_meteoric.nss
Normal file
52
trunk/users/Tenjac/spells/sp_meteoric.nss
Normal file
@@ -0,0 +1,52 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Meteoric Strike
|
||||
//:: FileName sp_meteoric.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Fire]
|
||||
Level: Druid 4, Paladin 4, Cleric 5,
|
||||
Components: V, S,
|
||||
Casting Time: 1 swift action
|
||||
Range: 0 ft.
|
||||
Target: Your melee weapon
|
||||
Duration: 1 round or until discharged
|
||||
Saving Throw: None or Reflex half; see text
|
||||
Spell Resistance: See text
|
||||
|
||||
Your melee weapon bursts into orange, red, and gold
|
||||
flames, and shining sparks trail in its wake.
|
||||
Your next successful melee attack deals extra fire
|
||||
damage equal to 1d6 points + 1d6 points per four caster
|
||||
levels.
|
||||
In addition, the flames splash into all squares adjacent
|
||||
to the target.
|
||||
Any creatures standing in these squares take half damage
|
||||
from the explosion, with a Reflex save allowed to halve
|
||||
this again.
|
||||
If a creature has spell resistance, it applies to this
|
||||
splash effect.
|
||||
You are not harmed by your own meteoric strike.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/15/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
|
||||
object oTarget = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
|
||||
itemproperty ipHook = ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1);
|
||||
IPSafeAddItemProperty(oTarget, ipHook, 6.0f)
|
||||
AddEventScript(oTarget, "sp_meteoriconhit", FALSE, FALSE);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
93
trunk/users/Tenjac/spells/sp_meteoriconhit.nss
Normal file
93
trunk/users/Tenjac/spells/sp_meteoriconhit.nss
Normal file
@@ -0,0 +1,93 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Meteoric Strike On Hit
|
||||
//:: FileName sp_meteoriconhit.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Fire]
|
||||
Level: Druid 4, Paladin 4, Cleric 5,
|
||||
Components: V, S,
|
||||
Casting Time: 1 swift action
|
||||
Range: 0 ft.
|
||||
Target: Your melee weapon
|
||||
Duration: 1 round or until discharged
|
||||
Saving Throw: None or Reflex half; see text
|
||||
Spell Resistance: See text
|
||||
|
||||
Your melee weapon bursts into orange, red, and gold flames,
|
||||
and shining sparks trail in its wake.
|
||||
Your next successful melee attack deals extra fire damage equal
|
||||
to 1d6 points + 1d6 points per four caster levels.
|
||||
In addition, the flames splash into all squares adjacent to the t
|
||||
arget.
|
||||
Any creatures standing in these squares take half damage from the
|
||||
explosion, with a Reflex save allowed to halve this again.
|
||||
If a creature has spell resistance, it applies to this splash effect.
|
||||
You are not harmed by your own meteoric strike.
|
||||
You can cast meteoric strike before you make an unarmed attack.
|
||||
If you do, your unarmed attack is considered armed.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/14/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
#include "prc_alterations"
|
||||
#include "prc_inc_combat"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oSpellOrigin = OBJECT_SELF;
|
||||
|
||||
// route all onhit-cast spells through the unique power script (hardcoded to "prc_onhitcast")
|
||||
// in order to fix the Bioware bug, that only executes the first onhitcast spell found on an item
|
||||
// any onhitcast spell should have the check ContinueOnHitCast() at the beginning of its code
|
||||
// if you want to force the execution of an onhitcast spell script, that has the check, without routing the call
|
||||
// through prc_onhitcast, you must use ForceExecuteSpellScript(), to be found in prc_inc_spells
|
||||
if(!ContinueOnHitCastSpell(oSpellOrigin)) return;
|
||||
|
||||
// DeleteLocalInt(oSpellOrigin, "X2_L_LAST_SPELLSCHOOL_VAR");
|
||||
SetLocalInt(oSpellOrigin, "X2_L_LAST_SPELLSCHOOL_VAR", SPELL_SCHOOL_TRANSMUTATION);
|
||||
|
||||
// find the weapon
|
||||
object oWeapon = PRCGetSpellCastItem(oSpellOrigin);
|
||||
|
||||
//Get Caster level
|
||||
int nBonus = GetLocalInt(oWeapon, "MeteoricCasterLvl") / 4;
|
||||
|
||||
// find the target of the spell
|
||||
object oTarget = PRCGetSpellTargetObject(oSpellOrigin);
|
||||
|
||||
// only do anything if we have a valid weapon and a valid living target
|
||||
if (GetIsObjectValid(oWeapon) && GetIsObjectValid(oTarget)&& !GetIsDead(oTarget))
|
||||
{
|
||||
int nDam = d6(1 + nBonus);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_FLAME_M), oTarget);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(oTarget, nDam, DAMAGE_TYPE_FIRE), oTarget);
|
||||
|
||||
//Burst
|
||||
nDam = nDam/2;
|
||||
location lLoc = GetLocation(oTarget);
|
||||
object oTargetB = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(5), lLoc, TRUE);
|
||||
|
||||
while(GetIsObjectValid(oTargetB))
|
||||
{
|
||||
if(oTargetB != oPC)
|
||||
{
|
||||
if(!PRCDoResistSpell(oTargetB))
|
||||
{
|
||||
if (PRCMySavingThrow(SAVING_THROW_REFLEX, oTargetB, (PRCGetSaveDC(oTargetB, oSpellOrigin))))
|
||||
{
|
||||
nDam = nDam/2;
|
||||
}
|
||||
|
||||
effect eLink = EffectLinkEffects(EffectDamage(DAMAGE_TYPE_FIRE, nDam), EffectVisualEffect(VFX_COM_HIT_FIRE));
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, eLink, oTargetB);
|
||||
}
|
||||
}
|
||||
oTargetB = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(5), lLoc, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
trunk/users/Tenjac/spells/sp_quickmarch.nss
Normal file
56
trunk/users/Tenjac/spells/sp_quickmarch.nss
Normal file
@@ -0,0 +1,56 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Quick March
|
||||
//:: FileName sp_quickmarch.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation
|
||||
Level: Cleric 2, Paladin 2,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Medium (100 ft. + 10 ft./level)
|
||||
Target: Allies in a 20-ft.-radius burst
|
||||
Duration: 1 round
|
||||
Saving Throw: Will negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
Upon casting this spell, your feet and those of your
|
||||
allies glow with a yellow nimbus of light.
|
||||
|
||||
Quick march increases your allies' base land speed by
|
||||
30 feet. (This adjustment is considered an enhancement
|
||||
bonus.) There is no effect on other modes of movement,
|
||||
such as burrow, climb, fly, or swim. As with any
|
||||
effect that increases a creature's speed, this spell
|
||||
affects maximum jumping distance.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/19/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
float fDur = RoundsToSeconds(1);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
effect eSpeed = EffectMovementSpeedIncrease(100);
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(20), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTarget))
|
||||
{
|
||||
if(GetIsReactionTypeFriendly(oTarget))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eSpeed, oTarget, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_HASTE), oTarget);
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(20), lLoc, FALSE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
93
trunk/users/Tenjac/spells/sp_resenergy.nss
Normal file
93
trunk/users/Tenjac/spells/sp_resenergy.nss
Normal file
@@ -0,0 +1,93 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Resist Energy
|
||||
//:: FileName sp_resenergy.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration
|
||||
Level: Ranger 1, Duskblade 1, Cleric 2, Death Master 2,
|
||||
Sha'ir 2, Wu Jen 2 (All), Death Delver 2, Fatemaker 2,
|
||||
Knight of the Chalice 2, Knight of the Weave 2,
|
||||
Vassal of Bahamut 2, Hoardstealer 2, Adept 2, Wizard 2,
|
||||
Sorcerer 2, Paladin 2, Druid 2, Urban Druid 2, Dragon 2,
|
||||
Fire 3
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Creature touched
|
||||
Duration: 10 min./level
|
||||
Saving Throw: Fortitude negates (harmless)
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
This abjuration grants a creature limited protection from
|
||||
damage of whichever one of five energy types you select:
|
||||
acid, cold, electricity, fire, or sonic. The subject gains
|
||||
energy resistance 10 against the energy type chosen, meaning
|
||||
that each time the creature is subjected to such damage
|
||||
(whether from a natural or magical source), that damage is
|
||||
reduced by 10 points before being applied to the creature's
|
||||
hit points. The value of the energy resistance granted increases
|
||||
to 20 points at 7th level and to a maximum of 30 points at 11th
|
||||
level. The spell protects the recipient's equipment as well.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/20/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 600.0f * (nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nSpell = GetSpellId();
|
||||
int nDamType;
|
||||
int nVis;
|
||||
|
||||
if(nSpell == SPELL_RESIST_ENERGY_ACID)
|
||||
{
|
||||
nDamType = DAMAGE_TYPE_ACID;
|
||||
nVis = VFX_DUR_AURA_GREEN;
|
||||
}
|
||||
|
||||
else if (nSpell == SPELL_RESIST_ENERGY_COLD)
|
||||
{
|
||||
nDamType = DAMAGE_TYPE_COLD;
|
||||
nVis = VFX_DUR_AURA_CYAN;
|
||||
}
|
||||
else if (nSpell == SPELL_RESIST_ENERGY_ELEC)
|
||||
{
|
||||
nDamType = DAMAGE_TYPE_ELECTRICAL;
|
||||
nVis = VFX_DUR_AURA_WHITE;
|
||||
}
|
||||
else if (nSpell == SPELL_RESIST_ENERGY_FIRE)
|
||||
{
|
||||
nDamType = DAMAGE_TYPE_FIRE;
|
||||
nVis = VFX_DUR_AURA_RED;
|
||||
}
|
||||
else if (nSpell == SPELL_RESIST_ENERGY_SONIC)
|
||||
{
|
||||
nDamType = DAMAGE_TYPE_SONIC;
|
||||
nVis = VFX_DUR_AURA_BLUE_LIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageToPC(oPC, "Invalid spell ID.");
|
||||
break;
|
||||
}
|
||||
|
||||
int nDamRes = 10;
|
||||
if(nCasterLvl > 6) nDamRes +=10;
|
||||
if(nCasterLvl > 10) nDamRes +=10;
|
||||
|
||||
effect eLink = EffectLinkEffects(EffectVisualEffect(nVis), EffectDamageResistance(nDamType, nDamRes));
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oTarget, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
62
trunk/users/Tenjac/spells/sp_revenance.nss
Normal file
62
trunk/users/Tenjac/spells/sp_revenance.nss
Normal file
@@ -0,0 +1,62 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Revenance
|
||||
//:: FileName sp_revenance.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Conjuration (Healing)
|
||||
Level: Blackguard 4, Cleric 4, Paladin 4, Bard 6
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: Dead ally touched
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: None; see text
|
||||
Spell Resistance: Yes (harmless)
|
||||
|
||||
You rush to your fallen companion amid the chaos of the
|
||||
battle and cry out the words that will bring her back for
|
||||
one last fight.
|
||||
|
||||
This spell brings a dead ally temporarily back to life.
|
||||
The subject can have been dead for up to 1 round per level.
|
||||
Your target functions as if a raise dead spell (PH 268)
|
||||
had been cast upon her, except that she does not lose a level
|
||||
and has half of her full normal hit points. She is alive
|
||||
(not undead) for the duration of the spell and can be healed
|
||||
normally, but dies as soon as the spell ends.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/20/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = (nCasterLvl * 60);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = GetSpellTargetObject();
|
||||
|
||||
if(!GetIsDead(oTarget) || GetIsReactionTypeHostile(oTarget))
|
||||
{
|
||||
SendMessageToPC(oPC, "Must target a dead ally.");
|
||||
break;
|
||||
}
|
||||
|
||||
//resurrect
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), oTarget);
|
||||
//Heal by half
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, PRCEffectHeal(GetMaxHitPoints(oTarget) / 2, oTarget), oTarget);
|
||||
//Schedule doom
|
||||
DelayCommand(fDur, SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDeath(), oTarget);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
39
trunk/users/Tenjac/spells/sp_rhinorush.nss
Normal file
39
trunk/users/Tenjac/spells/sp_rhinorush.nss
Normal file
@@ -0,0 +1,39 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Rhino's Rush
|
||||
//:: FileName sp_rhinorush.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation
|
||||
Level: Paladin 1, Ranger 1, Wrath (SpC) 1,
|
||||
Components: V, S,
|
||||
Casting Time: 1 swift action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round
|
||||
|
||||
This spell allows you to propel yourself in a single deadly
|
||||
charge. The first charge attack you make before the end of
|
||||
the round deals double damage on a successful hit.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/21/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(1);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_IOUNSTONE_RED), oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
58
trunk/users/Tenjac/spells/sp_rightaura.nss
Normal file
58
trunk/users/Tenjac/spells/sp_rightaura.nss
Normal file
@@ -0,0 +1,58 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Righteous Aura
|
||||
//:: FileName sp_rightaura.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration [Good, Light]
|
||||
Level: Paladin 4,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 hour/level
|
||||
|
||||
You invoke the powers of good and law, and in response
|
||||
to your pleas, you glow with the golden radiance of the sun.
|
||||
|
||||
You are bathed in an unearthly glow for the duration of the
|
||||
spell, as if a daylight spell (PH 216) had been cast on you.
|
||||
You get a +4 sacred bonus to Charisma.
|
||||
|
||||
If you die, your body is converted into an explosive blast
|
||||
of energy in a 20-foot-radius burst centered where you fell,
|
||||
dealing 2d6 points of damage per caster level (maximum 20d6)
|
||||
to all evil creatures in the burst's area. Good creatures in
|
||||
the area are healed by the same amount, and undead take
|
||||
double this damage. Spell resistance cannot prevent this
|
||||
damage, but a successful Reflex save reduces it to half.
|
||||
Your body is disintegrated, so you cannot be raised with a
|
||||
raise dead spell. Spells that do not require an intact body,
|
||||
such as true resurrection, can be used to bring you back to
|
||||
life as normal.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/20/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAbilityIncrease(ABILITY_CHARISMA, 4), fDur, oPC);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectAreaOfEffect(VFX_MOB_DAYLIGHT), fDur, oPC);
|
||||
|
||||
AddEventScript(oPC, EVENT_ONPLAYERDEATH, "prc_rightaura", FALSE, TRUE);
|
||||
AddEventScript(oPC, EVENT_NPC_ONDEATH, "prc_rightaura", FALSE, TRUE);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
49
trunk/users/Tenjac/spells/sp_rightfury.nss
Normal file
49
trunk/users/Tenjac/spells/sp_rightfury.nss
Normal file
@@ -0,0 +1,49 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Righteous Fury
|
||||
//:: FileName sp_rightfury.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Transmutation
|
||||
Level: Paladin 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 minute/level
|
||||
|
||||
You pull a holy aura about you that glows a golden red.
|
||||
|
||||
Summoning the power of your deity, you charge yourself
|
||||
with positive energy. This gives you 5 temporary hit
|
||||
points per caster level (maximum 50) and a +4 sacred
|
||||
bonus to Strength. These temporary hit points last for
|
||||
up to 1 hour.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/29/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 60*(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nHP = min(50, nCasterLvl * 5);
|
||||
|
||||
effect eBuff = EffectAbilityIncrease(ABILITY_STRENGTH, 4);
|
||||
effect eHP = EffectTemporaryHitpoints(nHP);
|
||||
effect eLink = EffectLinkEffects(eBuff, eHP);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, eLink, oPC, fDur);
|
||||
SPApplyEffectToObject(DURATION_TYPE_INSTANT, EffectVisualEffect(VFX_IMP_GOOD_HELP), oPC);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
44
trunk/users/Tenjac/spells/sp_seeketrest.nss
Normal file
44
trunk/users/Tenjac/spells/sp_seeketrest.nss
Normal file
@@ -0,0 +1,44 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Seek Eternal Rest
|
||||
//:: FileName sp_seeketrest.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
Conjuration (Healing)
|
||||
Level: Paladin 3,
|
||||
Components: V, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 hour/level
|
||||
|
||||
You invoke the greater powers and are infused with
|
||||
a great, golden glow, empowering you with holy glory.
|
||||
|
||||
You improve your ability to turn undead. For the
|
||||
purpose of turning or destroying undead, you are
|
||||
treated as a cleric of your paladin level.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 1/29/21
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
//Apply VFX, need to alter the turning script
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_YELLOW_LIGHT), oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
63
trunk/users/Tenjac/spells/sp_shieldward.nss
Normal file
63
trunk/users/Tenjac/spells/sp_shieldward.nss
Normal file
@@ -0,0 +1,63 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Shield of Warding
|
||||
//:: FileName sp_shieldward.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Abjuration [Good]
|
||||
Level: Paladin 2, Cleric 3,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: Touch
|
||||
Target: One shield or buckler touched
|
||||
Duration: 1 minute/level
|
||||
Saving Throw: Will negates (object, harmless)
|
||||
Spell Resistance: No
|
||||
|
||||
The touched shield or buckler grants its wielder a +1
|
||||
sacred bonus to Armor Class and on Reflex saves, +1 per
|
||||
five caster levels (maximum +5 at 20th level). The bonus
|
||||
applies only when the shield is worn or carried normally
|
||||
(but not, for instance, if it is slung over the shoulder).
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/21/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_ABJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl) * 60;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oTarget = PRCGetSpellTargetObject();
|
||||
object oShield;
|
||||
|
||||
if GetObjectType(oTarget == OBJECT_TYPE_CREATURE) oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
|
||||
if GetObjectType(oTarget == OBJECT_TYPE_ITEM) oShield = oTarget;
|
||||
|
||||
//Check that this is a shield, if not abort
|
||||
if(GetIsShield(oShield) == FALSE)
|
||||
{
|
||||
SendMessageToPC(OBJECT_SELF, "Target has no equipped shield.");
|
||||
break;
|
||||
}
|
||||
|
||||
int nBonus = 1;
|
||||
if nCasterLvl > 4 nBonus +=1;
|
||||
if nCasterLvl > 9 nBonus +=1;
|
||||
if nCasterLvl > 14 nBonus +=1;
|
||||
if nCasterLvl > 19 nBonus +=1;
|
||||
|
||||
IPSafeAddItemProperty(oShield, ItemPropertyACBonus(nBonus), fDur);
|
||||
IPSafeAddItemProperty(oShield, ItemProperBonusSavingThrow(IP_CONST_SAVEBASETYPE_REFLEX, nBonus), fDur);
|
||||
PRCSetSchool();
|
||||
}
|
||||
|
||||
|
||||
43
trunk/users/Tenjac/spells/sp_smiteher.nss
Normal file
43
trunk/users/Tenjac/spells/sp_smiteher.nss
Normal file
@@ -0,0 +1,43 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Smite Heretic
|
||||
//:: FileName sp_smiteher.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Conjuration
|
||||
Level: Paladin 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 10 minutes/level
|
||||
|
||||
For the duration of the spell, when using your smite
|
||||
evil class ability against an evil creature with the
|
||||
ability to cast divine spells, you gain a +2 sacred
|
||||
bonus on the attack roll.
|
||||
|
||||
Furthermore, the attack deals 2 extra points of damage
|
||||
(instead of 1) per paladin level.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/25/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_CONJURATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 600 * nCasterLvl;
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_PULSE_YELLOW_WHITE), oPC, fDur);
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
62
trunk/users/Tenjac/spells/sp_smitesacfire.nss
Normal file
62
trunk/users/Tenjac/spells/sp_smitesacfire.nss
Normal file
@@ -0,0 +1,62 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Smite of Sacred Fire
|
||||
//:: FileName sp_smitesacfire.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Good]
|
||||
Level: Paladin 2,
|
||||
Components: V, DF,
|
||||
Casting Time: 1 swift action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 round/level; see text
|
||||
|
||||
You must cast this spell in the same round when you
|
||||
attempt a smite attack. If the attack hits, you deal
|
||||
an extra 2d6 points of damage to the target of the
|
||||
smite. Whether or not you succeed on the smite attempt,
|
||||
during each subsequent round of the spell?s duration,
|
||||
you deal an extra 2d6 points of damage on any successful
|
||||
melee attack against the target you attempted to smite.
|
||||
The spell ends prematurely after any round when you do not
|
||||
attempt a melee attack against the target you previously
|
||||
attempted to smite, or if you fail to hit with any of
|
||||
your attacks in a round.
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 7/25/2022
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void SmiteCheck(object oWeapon)
|
||||
{
|
||||
//No smite attempt last round
|
||||
if(!GetLocalInt(oWeapon, "PRCSmiteLastRound"))
|
||||
{
|
||||
RemoveEventScript(oWeapon, EVENT_ITEM_ONHIT, "prc_evnt_ssf", TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = RoundsToSeconds(nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
|
||||
itemproperty ipHook = ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1);
|
||||
IPSafeAddItemProperty(oWeapon, ipHook, fDur);
|
||||
|
||||
//Add onhit
|
||||
AddEventScript(oWeapon, EVENT_ITEM_ONHIT, "prc_evnt_ssf", TRUE, FALSE);
|
||||
|
||||
DelayCommand(6.0f, SmiteCheck(oWeapon));
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
76
trunk/users/Tenjac/spells/sp_soldsanc.nss
Normal file
76
trunk/users/Tenjac/spells/sp_soldsanc.nss
Normal file
@@ -0,0 +1,76 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Soldiers of Sanctity
|
||||
//:: FileName sp_soldsanc.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Evocation [Good]
|
||||
Level: Cleric 3, Paladin 3,
|
||||
Components: V, S, DF,
|
||||
Casting Time: 1 full round
|
||||
Range: Close (25 ft. + 5 ft./2 levels)
|
||||
Target: You, plus one willing creature/2 levels; see text
|
||||
Duration: 1 min./level
|
||||
Saving Throw: None
|
||||
Spell Resistance: No
|
||||
|
||||
For the duration of soldiers of sanctity, you gain a
|
||||
bonus on turning checks and turning damage rolls made
|
||||
when you have allies within 30 feet of you. This is a
|
||||
sacred bonus, equal to the number of allies within 30
|
||||
feet, to a maximum of +6.
|
||||
|
||||
In addition, each target gains a +2 bonus to AC against
|
||||
all attacks made by undead creatures. This bonus
|
||||
applies for the duration of the spell as long as an
|
||||
ally is within 30 feet of you.
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/4/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
void AllyCheck(object oPC, float fDur)
|
||||
{
|
||||
int nCount;
|
||||
object oTest = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(30), GetLocation(oPC), OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(GetIsObjectValid(oTest))
|
||||
{
|
||||
if(GetIsReactionTypeFriendly(oTest))
|
||||
{
|
||||
nCount++;
|
||||
}
|
||||
oTest = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(30), GetLocation(oPC), OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
SetLocalInt(oPC, "SOLDIERS_OF_SANCTITY_ALLIES", nCount);
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, VersusRacialTypeEffect(EffectACIncrease(2), RACIAL_TYPE_UNDEAD), oPC, 6.0f);
|
||||
DelayCommand(6.0f, AllyCheck(oPC, fDur- 6.0));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_EVOCATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = 60.0f * (nCasterLvl);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
int nTargets = min(6, nCasterLvl/2);
|
||||
|
||||
AllyCheck(oPC, fDur);
|
||||
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, FeetToMeters(30), GetLocation(oPC), OBJECT_TYPE_CREATURE);
|
||||
|
||||
while(nTargets > 0)
|
||||
{
|
||||
AllyCheck(oTarget, fDur);
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, FeetToMeters(30), GetLocation(oPC), OBJECT_TYPE_CREATURE);
|
||||
nTargets--;
|
||||
}
|
||||
PRCSetSchool();
|
||||
}
|
||||
87
trunk/users/Tenjac/spells/sp_soullight.nss
Normal file
87
trunk/users/Tenjac/spells/sp_soullight.nss
Normal file
@@ -0,0 +1,87 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Name Soul of Light
|
||||
//:: FileName sp_soulight.nss
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file Transmutation [Good]
|
||||
Level: Paladin 2, Cleric 3,
|
||||
Components: V, S,
|
||||
Casting Time: 1 standard action
|
||||
Range: Personal
|
||||
Target: You
|
||||
Duration: 1 hour
|
||||
|
||||
Bright, clear light sprouts from your body, quickly
|
||||
flaring before fading to a faint white pulse. This spell
|
||||
infuses your body with energy drawn from the Positive
|
||||
Energy Plane, making it easier to repair injuries.
|
||||
|
||||
Whenever you cast or are the target of a conjuration
|
||||
(healing) spell, you can choose for the spell to heal
|
||||
a number of extra points of damage equal to twice the spell's level.
|
||||
|
||||
If such a spell heals at least 10 points of damage,
|
||||
it also removes the fatigued condition from the
|
||||
target (or reduces exhaustion to fatigue).
|
||||
|
||||
If soul of light and soul of order are active on you at the
|
||||
same time, you gain damage reduction 3/+3
|
||||
|
||||
*/
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Tenjac
|
||||
//:: Created On: 8/8/22
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_sp_func"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
if(!X2PreSpellCastCode()) return;
|
||||
PRCSetSchool(SPELL_SCHOOL_TRANSMUTATION);
|
||||
object oPC = OBJECT_SELF;
|
||||
int nCasterLvl = PRCGetCasterLevel(oPC);
|
||||
float fDur = HoursToSeconds(1);
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
if(nMetaMagic & METAMAGIC_EXTEND) fDur += fDur;
|
||||
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_AURA_WHITE), oPC, fDur);
|
||||
|
||||
if(GetHasSpellEffect(SPELL_SOUL_OF_ORDER, oPC))
|
||||
{
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectDamageReduction(3, DAMAGE_POWER_PLUS_THREE, 0), oPC, fDur);
|
||||
}
|
||||
|
||||
/**To add into PRCEffectHeal
|
||||
if(GetHasSpellEffect(SPELL_SOUL_OF_LIGHT, oTarget))
|
||||
{
|
||||
//2x the spell level bonus
|
||||
nHP += (StringToInt(Get2DACache("spells", "Innate", PRCGetSpellId()) *2);
|
||||
if(nHP >= 10)
|
||||
{
|
||||
effect eEffect = GetFirstEffect(oPC);
|
||||
while(GetIsEffectValid(eEffect))
|
||||
{
|
||||
//remove fatigue
|
||||
if(GetEffectTag(eEffect) == "PRCFatigue")
|
||||
{
|
||||
RemoveEffect(oPC, eEffect);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffecVisualEffect(VFX_DUR_CESSATE_POSITIVE) oTarget, 6.0f);
|
||||
}
|
||||
|
||||
//downgrade exhaustion
|
||||
if(GetEffectTag(eEffect) == "PRCExhausted")
|
||||
{
|
||||
float fNew = IntToFloat(GetEffectDurationRemaining(eEffect));
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectFatigue(), oTarget, fNew);
|
||||
SPApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffecVisualEffect(VFX_DUR_CESSATE_POSITIVE) oTarget, 6.0f);
|
||||
|
||||
}
|
||||
eEffect = GetNextEffect(oPC);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
PRCSetSchool();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user